The BIG graph update
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Tue, 15 Jan 2002 22:51:07 +0000 (22:51 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Tue, 15 Jan 2002 22:51:07 +0000 (22:51 +0000)
  * Replace libgd with libart
  * Added freetype
  * Updated zlib and libpng
  * rrd_gfx.c intrduced as libart wrapper
  * LINE takes now a float as argument
  * rrdtool uses truetype for fonts
  * thanks to libart there is now full alpha transparenc
    and antialiasing.
  * the new option --font lets customize the font
    and size for various graph elements
  * Updated to -> libtool 1.4.2 automake 2.12 autoconf 2.52
  * new --zoom commandline option for zoom ans shrinking
  -- tobias oetiker

git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@61 a5681a0c-68f1-0310-ab6d-d61299d08faa

394 files changed:
CONTRIBUTORS
MakeMakefile
Makefile.am
NEWS
config/acconfig.h [deleted file]
config/aclocal.m4 [deleted file]
config/config.guess [deleted file]
config/config.h.in [deleted file]
config/config.sub [deleted file]
config/install-sh [deleted file]
config/ltconfig [deleted file]
config/ltmain.sh [deleted file]
config/missing [deleted file]
config/mkinstalldirs [deleted file]
config/stamp-h [deleted file]
config/stamp-h.in [deleted file]
configure.ac [new file with mode: 0644]
configure.in [deleted file]
doc/rrdgraph.src
doc/rrdgraph_graph.src
examples/4charts.pl.in
examples/bigtops.pl
examples/bigtops.pl.in
examples/cgi-demo.cgi
examples/minmax.pl
examples/minmax.pl.in
examples/piped-demo.pl
examples/piped-demo.pl.in
examples/shared-demo.pl
examples/shared-demo.pl.in
examples/stripes.pl
examples/stripes.pl.in
libraries/Makefile.am
libraries/cgilib-0.4/Makefile.am
libraries/freetype-2.0.5-import.txt [new file with mode: 0644]
libraries/freetype-2.0.5/Makefile.am [new file with mode: 0644]
libraries/freetype-2.0.5/README [new file with mode: 0644]
libraries/freetype-2.0.5/ahangles.c [new file with mode: 0644]
libraries/freetype-2.0.5/ahglobal.c [new file with mode: 0644]
libraries/freetype-2.0.5/ahglyph.c [new file with mode: 0644]
libraries/freetype-2.0.5/ahhint.c [new file with mode: 0644]
libraries/freetype-2.0.5/ahmodule.c [new file with mode: 0644]
libraries/freetype-2.0.5/ahoptim.c [new file with mode: 0644]
libraries/freetype-2.0.5/autohint.c [new file with mode: 0644]
libraries/freetype-2.0.5/cff.c [new file with mode: 0644]
libraries/freetype-2.0.5/cffdrivr.c [new file with mode: 0644]
libraries/freetype-2.0.5/cffgload.c [new file with mode: 0644]
libraries/freetype-2.0.5/cffload.c [new file with mode: 0644]
libraries/freetype-2.0.5/cffobjs.c [new file with mode: 0644]
libraries/freetype-2.0.5/cffparse.c [new file with mode: 0644]
libraries/freetype-2.0.5/cidgload.c [new file with mode: 0644]
libraries/freetype-2.0.5/cidload.c [new file with mode: 0644]
libraries/freetype-2.0.5/cidobjs.c [new file with mode: 0644]
libraries/freetype-2.0.5/cidparse.c [new file with mode: 0644]
libraries/freetype-2.0.5/cidriver.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftbase.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftbbox.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftcache.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftcalc.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftcchunk.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftcglyph.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftcimage.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftcmanag.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftcsbits.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftdebug.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftextend.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftglyph.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftgrays.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftinit.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftlist.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftlru.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftmac.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftmm.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftnames.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftobjs.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftoutln.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftraster.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftrend1.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftsmooth.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftstream.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftsynth.c [new file with mode: 0644]
libraries/freetype-2.0.5/ftsystem.c [new file with mode: 0644]
libraries/freetype-2.0.5/fttrigon.c [new file with mode: 0644]
libraries/freetype-2.0.5/include/Makefile.am [new file with mode: 0644]
libraries/freetype-2.0.5/include/ahangles.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/aherrors.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ahglobal.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ahglyph.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ahhint.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ahloader.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ahmodule.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ahoptim.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ahtypes.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cffdrivr.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cfferrs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cffgload.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cffload.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cffobjs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cffparse.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cfftoken.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ciderrs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cidgload.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cidload.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cidobjs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cidparse.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cidriver.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/cidtoken.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/fnterrs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/Makefile.am [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/cache/Makefile.am [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/cache/ftcchunk.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/cache/ftcglyph.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/cache/ftcimage.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/cache/ftcmanag.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/cache/ftcsbits.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/cache/ftlru.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/config/Makefile.am [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/config/ftconfig.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/config/ftheader.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/config/ftmodule.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/config/ftoption.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/freetype.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftbbox.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftcache.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftchapters.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/fterrors.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftglyph.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftimage.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftlist.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftmac.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftmm.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftmoderr.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftmodule.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftoutln.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftrender.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftsizes.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftsnames.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftsynth.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ftsystem.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/fttrigon.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/fttypes.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/Makefile.am [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/autohint.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/cfftypes.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/fnttypes.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/ftcalc.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/ftdebug.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/ftdriver.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/ftextend.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/ftmemory.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/ftobjs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/ftstream.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/internal.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/pcftypes.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/psaux.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/psnames.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/sfnt.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/t1types.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/internal/tttypes.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/t1tables.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/ttnameid.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/tttables.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/freetype/tttags.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ft2build.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ftcerror.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ftgrays.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ftraster.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ftrend1.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ftsmerrs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ftsmooth.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/pcf.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/pcfdriver.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/pcferror.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/pcfutil.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/psauxerr.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/psauxmod.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/psmodule.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/psnamerr.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/psobjs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/pstables.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/rasterrs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/sfdriver.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/sferrors.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/sfobjs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/t1afm.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/t1decode.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/t1driver.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/t1errors.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/t1gload.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/t1load.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/t1objs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/t1parse.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/t1tokens.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ttcmap.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ttdriver.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/tterrors.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ttgload.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ttinterp.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ttload.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ttobjs.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ttpload.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ttpost.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/ttsbit.h [new file with mode: 0644]
libraries/freetype-2.0.5/include/winfnt.h [new file with mode: 0644]
libraries/freetype-2.0.5/license.txt [new file with mode: 0644]
libraries/freetype-2.0.5/pcf.c [new file with mode: 0644]
libraries/freetype-2.0.5/pcfdriver.c [new file with mode: 0644]
libraries/freetype-2.0.5/pcfread.c [new file with mode: 0644]
libraries/freetype-2.0.5/pcfutil.c [new file with mode: 0644]
libraries/freetype-2.0.5/psaux.c [new file with mode: 0644]
libraries/freetype-2.0.5/psauxmod.c [new file with mode: 0644]
libraries/freetype-2.0.5/psmodule.c [new file with mode: 0644]
libraries/freetype-2.0.5/psnames.c [new file with mode: 0644]
libraries/freetype-2.0.5/psobjs.c [new file with mode: 0644]
libraries/freetype-2.0.5/raster.c [new file with mode: 0644]
libraries/freetype-2.0.5/sfdriver.c [new file with mode: 0644]
libraries/freetype-2.0.5/sfnt.c [new file with mode: 0644]
libraries/freetype-2.0.5/sfobjs.c [new file with mode: 0644]
libraries/freetype-2.0.5/smooth.c [new file with mode: 0644]
libraries/freetype-2.0.5/t1afm.c [new file with mode: 0644]
libraries/freetype-2.0.5/t1decode.c [new file with mode: 0644]
libraries/freetype-2.0.5/t1driver.c [new file with mode: 0644]
libraries/freetype-2.0.5/t1gload.c [new file with mode: 0644]
libraries/freetype-2.0.5/t1load.c [new file with mode: 0644]
libraries/freetype-2.0.5/t1objs.c [new file with mode: 0644]
libraries/freetype-2.0.5/t1parse.c [new file with mode: 0644]
libraries/freetype-2.0.5/test_bbox.c [new file with mode: 0644]
libraries/freetype-2.0.5/test_trig.c [new file with mode: 0644]
libraries/freetype-2.0.5/truetype.c [new file with mode: 0644]
libraries/freetype-2.0.5/ttcmap.c [new file with mode: 0644]
libraries/freetype-2.0.5/ttdriver.c [new file with mode: 0644]
libraries/freetype-2.0.5/ttgload.c [new file with mode: 0644]
libraries/freetype-2.0.5/ttinterp.c [new file with mode: 0644]
libraries/freetype-2.0.5/ttload.c [new file with mode: 0644]
libraries/freetype-2.0.5/ttobjs.c [new file with mode: 0644]
libraries/freetype-2.0.5/ttpload.c [new file with mode: 0644]
libraries/freetype-2.0.5/ttpost.c [new file with mode: 0644]
libraries/freetype-2.0.5/ttsbit.c [new file with mode: 0644]
libraries/freetype-2.0.5/type1.c [new file with mode: 0644]
libraries/freetype-2.0.5/type1cid.c [new file with mode: 0644]
libraries/freetype-2.0.5/winfnt.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/AUTHORS [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/COPYING [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/ChangeLog [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/INSTALL [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/Makefile [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/Makefile.am [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/Makefile.in [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/NEWS [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/README [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_affine.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_affine.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_alphagamma.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_alphagamma.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_bpath.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_bpath.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_config.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_filterlevel.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_gray_svp.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_gray_svp.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_misc.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_misc.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_pathcode.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_pixbuf.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_pixbuf.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_point.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rect.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rect.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rect_svp.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rect_svp.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rect_uta.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rect_uta.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_render.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_render.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_render_gradient.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_render_gradient.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_render_svp.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_render_svp.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_a_affine.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_a_affine.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_affine.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_affine.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_affine_private.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_affine_private.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_bitmap_affine.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_bitmap_affine.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_pixbuf_affine.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_pixbuf_affine.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_rgba_affine.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_rgba_affine.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_svp.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgb_svp.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgba.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_rgba.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_intersect.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_intersect.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_ops.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_ops.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_point.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_point.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_render_aa.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_render_aa.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_vpath.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_vpath.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_vpath_stroke.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_vpath_stroke.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_wind.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_svp_wind.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_uta.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_uta.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_uta_ops.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_uta_ops.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_uta_rect.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_uta_rect.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_uta_svp.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_uta_svp.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_uta_vpath.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_uta_vpath.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_vpath.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_vpath.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_vpath_bpath.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_vpath_bpath.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_vpath_dash.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_vpath_dash.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_vpath_svp.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/art_vpath_svp.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/gen_art_config.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/install-sh [new file with mode: 0755]
libraries/libart_lgpl-2.3.7/libart-2.0.pc.in [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/libart-config.in [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/libart-features.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/libart-features.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/libart-features.h.in [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/libart.h [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/libart_lgpl_2.la [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/missing [new file with mode: 0755]
libraries/libart_lgpl-2.3.7/mkinstalldirs [new file with mode: 0755]
libraries/libart_lgpl-2.3.7/stamp-h.in [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/testart.c [new file with mode: 0644]
libraries/libart_lgpl-2.3.7/testuta.c [new file with mode: 0644]
libraries/libpng-1.2.0-import.txt [new file with mode: 0644]
libraries/libpng-1.2.0/ANNOUNCE [new file with mode: 0644]
libraries/libpng-1.2.0/CHANGES [new file with mode: 0644]
libraries/libpng-1.2.0/INSTALL [new file with mode: 0644]
libraries/libpng-1.2.0/KNOWNBUG [new file with mode: 0644]
libraries/libpng-1.2.0/LICENSE [new file with mode: 0644]
libraries/libpng-1.2.0/Makefile [new file with mode: 0644]
libraries/libpng-1.2.0/Makefile.am [new file with mode: 0644]
libraries/libpng-1.2.0/Makefile.in [new file with mode: 0644]
libraries/libpng-1.2.0/README [new file with mode: 0644]
libraries/libpng-1.2.0/TODO [new file with mode: 0644]
libraries/libpng-1.2.0/Y2KINFO [new file with mode: 0644]
libraries/libpng-1.2.0/example.c [new file with mode: 0644]
libraries/libpng-1.2.0/libpng.3 [new file with mode: 0644]
libraries/libpng-1.2.0/libpng.txt [new file with mode: 0644]
libraries/libpng-1.2.0/libpngpf.3 [new file with mode: 0644]
libraries/libpng-1.2.0/png.5 [new file with mode: 0644]
libraries/libpng-1.2.0/png.c [new file with mode: 0644]
libraries/libpng-1.2.0/png.h [new file with mode: 0644]
libraries/libpng-1.2.0/pngasmrd.h [new file with mode: 0644]
libraries/libpng-1.2.0/pngbar.jpg [new file with mode: 0644]
libraries/libpng-1.2.0/pngbar.png [new file with mode: 0644]
libraries/libpng-1.2.0/pngconf.h [new file with mode: 0644]
libraries/libpng-1.2.0/pngerror.c [new file with mode: 0644]
libraries/libpng-1.2.0/pnggccrd.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngget.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngmem.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngnow.png [new file with mode: 0644]
libraries/libpng-1.2.0/pngpread.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngread.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngrio.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngrtran.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngrutil.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngset.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngtest.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngtest.png [new file with mode: 0644]
libraries/libpng-1.2.0/pngtrans.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngvcrd.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngwio.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngwrite.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngwtran.c [new file with mode: 0644]
libraries/libpng-1.2.0/pngwutil.c [new file with mode: 0644]
src/Makefile.am
src/rrd_format.h
src/rrd_gfx.c [new file with mode: 0644]
src/rrd_gfx.h [new file with mode: 0644]
src/rrd_graph.c
src/rrd_graph.h
src/rrd_tool.c
src/rrd_tool.h

index 51f3e06..fd86627 100644 (file)
@@ -87,8 +87,8 @@ Further I would like to note, that rrdtool would not exist without
 the following free software products:
 
        Perl by Larry Wall
-       gd library by Thomas Boutell
-       gifcode from David Koblas
+       libart by Raph Levien
+       freetype by David Turner, Robert Wilhelm, and Werner Lemberg
        libpng by Glenn Randers-Pehrson / Andreas Eric Dilger / Guy Eric Schalnat
        cgilib by Martin Schulze
        zlib by Jean-loup Gailly and Mark Adler
index 6faa343..3d6fae9 100755 (executable)
@@ -4,5 +4,16 @@
 # makefiles and friends
 set -x
 #
-automake --foreign --verbose
-autoconf --localdir=./config
+find . -name Makefile | xargs rm
+find . -name Makefile.in | xargs rm
+
+# libtool 1.4.2
+libtoolize --automake
+# automake 2.12
+aclocal
+autoheader --warnings=all
+automake --foreign --add-missing --force-missing --copy 
+# autoconf 2.52
+autoconf 
+
+
index cef4ed2..4bba56a 100644 (file)
@@ -10,10 +10,11 @@ EXTRA_DIST = COPYRIGHT CHANGES NT-BUILD-TIPS.txt TODO CONTRIBUTORS rrdtool.spec
 CLEANFILES = config.cache
 
 # use relaxed rules when building dists
-AUTOMAKE_OPTIONS= foreign no-dependencies
+AUTOMAKE_OPTIONS= foreign 
 
 # where we keep local rules for automake
-ACLOCAL_M4=    $(top_srcdir)/config/aclocal.m4
+
+ACLOCAL_M4= $(top_srcdir)/aclocal.m4
 AUTOHEADER = @AUTOHEADER@ --localdir=$(top_srcdir)/config
 AUTOCONF = @AUTOCONF@ --localdir=$(top_srcdir)/config
 
diff --git a/NEWS b/NEWS
index ef37928..403f700 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,23 @@ RRDTOOL NEWS
 In this file I am noting the Major changes to rrdtool
 for details check the cvs ChangeLog
 
+2002/01/15 Tobias Oetiker <tobi@oetiker.ch>
+  The BIG graph update
+  * Replace libgd with libart
+  * Added freetype
+  * Updated zlib and libpng
+  * rrd_gfx.c intrduced as libart wrapper
+  * LINE takes now a float as argument
+  * rrdtool uses truetype for fonts
+  * thanks to libart there is now full alpha transparenc
+    and antialiasing.
+  * the new option --font lets customize the font
+    and size for various graph elements
+  * Updated to -> libtool 1.4.2 automake 2.12 autoconf 2.52
+  * new --zoom commandline option for zoom ans shrinking
+  ---- Still missing is rotatet text for the yaxis description
+  ---- Still missing is tab support in the text rendere
+  ---- Still missing is autoconf support for a default truetype font
 
 2001/07/26 Alex van den Bogaerdt <alex@ergens.op.Het.Net>
   Added TOTAL to the VDEF functions.
diff --git a/config/acconfig.h b/config/acconfig.h
deleted file mode 100644 (file)
index eac8a94..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef CONFIG_H
-#define CONFIG_H
-
-@TOP@
-
-/* IEEE can be prevented from raising signals with fpsetmask(0) */
-#undef MUST_DISABLE_FPMASK
-
-/* IEEE math only works if SIGFPE gets actively set to IGNORE */
-
-#undef MUST_DISABLE_SIGFPE
-
-/* realloc does not support NULL as argument */
-#undef NO_NULL_REALLOC
-
-@BOTTOM@
-
-/* define strrchr, strchr and memcpy, memmove in terms of bsd funcs
-   make sure you are NOT using bcopy, index or rindex in the code */
-      
-#if STDC_HEADERS
-# include <string.h>
-#else
-# ifndef HAVE_STRCHR
-#  define strchr index
-#  define strrchr rindex
-# endif
-char *strchr (), *strrchr ();
-# ifndef HAVE_MEMMOVE
-#  define memcpy(d, s, n) bcopy ((s), (d), (n))
-#  define memmove(d, s, n) bcopy ((s), (d), (n))
-# endif
-#endif
-
-
-#if NO_NULL_REALLOC
-# define rrd_realloc(a,b) ( (a) == NULL ? malloc( (b) ) : realloc( (a) , (b) ))
-#else
-# define rrd_realloc(a,b) realloc((a), (b))
-#endif      
-
-#if HAVE_MATH_H
-#  include <math.h>
-#endif
-
-#if HAVE_FLOAT_H
-#  include <float.h>
-#endif
-
-#if HAVE_IEEEFP_H
-#  include <ieeefp.h>
-#endif
-
-#if HAVE_FP_CLASS_H
-#  include <fp_class.h>
-#endif
-
-/* for Solaris */
-#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASS))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fpclass(a) == FP_NINF || fpclass(a) == FP_PINF)
-#endif
-
-/* for OSF1 Digital Unix */
-#if (! defined(HAVE_ISINF) && defined(HAVE_FP_CLASS) && defined(HAVE_FP_CLASS_H))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fp_class(a) == FP_NEG_INF || fp_class(a) == FP_POS_INF)
-#endif
-
-#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASSIFY) && defined(FP_PLUS_INF) && defined(FP_MINUS_INF))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fpclassify(a) == FP_MINUS_INF || fpclassify(a) == FP_PLUS_INF)
-#endif
-
-#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASSIFY) && defined(FP_INFINITE))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fpclassify(a) == FP_INFINITE)
-#endif
-
-/* for AIX */
-#if (! defined(HAVE_ISINF) && defined(HAVE_CLASS))
-#  define HAVE_ISINF 1
-#  define isinf(a) (class(a) == FP_MINUS_INF || class(a) == FP_PLUS_INF)
-#endif
-
-#if (! defined (HAVE_FINITE) && defined (HAVE_ISFINITE))
-#  define HAVE_FINITE 1
-#  define finite(a) isfinite(a)
-#endif
-
-#if (! defined(HAVE_FINITE) && defined(HAVE_ISNAN) && defined(HAVE_ISINF))
-#  define HAVE_FINITE 1
-#  define finite(a) (! isnan(a) && ! isinf(a))
-#endif
-
-#ifndef HAVE_FINITE
-#error "Can't compile without finite function"
-#endif
-
-#ifndef HAVE_ISINF
-#error "Can't compile without isinf function"
-#endif
-
-#endif /* CONFIG_H */
-
diff --git a/config/aclocal.m4 b/config/aclocal.m4
deleted file mode 100644 (file)
index a2df3f1..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-dnl aclocal.m4 generated automatically by aclocal 1.4
-
-dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-dnl This program is distributed in the hope that it will be useful,
-dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-dnl PARTICULAR PURPOSE.
-
-# Do all the work for Automake.  This macro actually does too much --
-# some checks are only needed if your package does certain things.
-# But this isn't really a big deal.
-
-# serial 1
-
-dnl Usage:
-dnl AM_INIT_AUTOMAKE(package,version, [no-define])
-
-AC_DEFUN(AM_INIT_AUTOMAKE,
-[AC_REQUIRE([AC_PROG_INSTALL])
-PACKAGE=[$1]
-AC_SUBST(PACKAGE)
-VERSION=[$2]
-AC_SUBST(VERSION)
-dnl test to see if srcdir already configured
-if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
-  AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
-fi
-ifelse([$3],,
-AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
-AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
-AC_REQUIRE([AM_SANITY_CHECK])
-AC_REQUIRE([AC_ARG_PROGRAM])
-dnl FIXME This is truly gross.
-missing_dir=`cd $ac_aux_dir && pwd`
-AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
-AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
-AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
-AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
-AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
-AC_REQUIRE([AC_PROG_MAKE_SET])])
-
-#
-# Check to make sure that the build environment is sane.
-#
-
-AC_DEFUN(AM_SANITY_CHECK,
-[AC_MSG_CHECKING([whether build environment is sane])
-# Just in case
-sleep 1
-echo timestamp > conftestfile
-# Do `set' in a subshell so we don't clobber the current shell's
-# arguments.  Must try -L first in case configure is actually a
-# symlink; some systems play weird games with the mod time of symlinks
-# (eg FreeBSD returns the mod time of the symlink's containing
-# directory).
-if (
-   set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
-   if test "[$]*" = "X"; then
-      # -L didn't work.
-      set X `ls -t $srcdir/configure conftestfile`
-   fi
-   if test "[$]*" != "X $srcdir/configure conftestfile" \
-      && test "[$]*" != "X conftestfile $srcdir/configure"; then
-
-      # If neither matched, then we have a broken ls.  This can happen
-      # if, for instance, CONFIG_SHELL is bash and it inherits a
-      # broken ls alias from the environment.  This has actually
-      # happened.  Such a system could not be considered "sane".
-      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
-alias in your environment])
-   fi
-
-   test "[$]2" = conftestfile
-   )
-then
-   # Ok.
-   :
-else
-   AC_MSG_ERROR([newly created file is older than distributed files!
-Check your system clock])
-fi
-rm -f conftest*
-AC_MSG_RESULT(yes)])
-
-dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
-dnl The program must properly implement --version.
-AC_DEFUN(AM_MISSING_PROG,
-[AC_MSG_CHECKING(for working $2)
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf.  Sigh.
-if ($2 --version) < /dev/null > /dev/null 2>&1; then
-   $1=$2
-   AC_MSG_RESULT(found)
-else
-   $1="$3/missing $2"
-   AC_MSG_RESULT(missing)
-fi
-AC_SUBST($1)])
-
-# Like AC_CONFIG_HEADER, but automatically create stamp file.
-
-AC_DEFUN(AM_CONFIG_HEADER,
-[AC_PREREQ([2.12])
-AC_CONFIG_HEADER([$1])
-dnl When config.status generates a header, we must update the stamp-h file.
-dnl This file resides in the same directory as the config header
-dnl that is generated.  We must strip everything past the first ":",
-dnl and everything past the last "/".
-AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
-ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
-<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
-<<am_indx=1
-for am_file in <<$1>>; do
-  case " <<$>>CONFIG_HEADERS " in
-  *" <<$>>am_file "*<<)>>
-    echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
-    ;;
-  esac
-  am_indx=`expr "<<$>>am_indx" + 1`
-done<<>>dnl>>)
-changequote([,]))])
-
-# Define a conditional.
-
-AC_DEFUN(AM_CONDITIONAL,
-[AC_SUBST($1_TRUE)
-AC_SUBST($1_FALSE)
-if $2; then
-  $1_TRUE=
-  $1_FALSE='#'
-else
-  $1_TRUE='#'
-  $1_FALSE=
-fi])
-
-
-# serial 40 AC_PROG_LIBTOOL
-AC_DEFUN(AC_PROG_LIBTOOL,
-[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
-
-# Save cache, so that ltconfig can load it
-AC_CACHE_SAVE
-
-# Actually configure libtool.  ac_aux_dir is where install-sh is found.
-CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
-LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
-LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \
-DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \
-${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
-$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \
-|| AC_MSG_ERROR([libtool configure failed])
-
-# Reload cache, that may have been modified by ltconfig
-AC_CACHE_LOAD
-
-# This can be used to rebuild libtool when needed
-LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
-
-# Always use our own libtool.
-LIBTOOL='$(SHELL) $(top_builddir)/libtool'
-AC_SUBST(LIBTOOL)dnl
-
-# Redirect the config.log output again, so that the ltconfig log is not
-# clobbered by the next message.
-exec 5>>./config.log
-])
-
-AC_DEFUN(AC_LIBTOOL_SETUP,
-[AC_PREREQ(2.13)dnl
-AC_REQUIRE([AC_ENABLE_SHARED])dnl
-AC_REQUIRE([AC_ENABLE_STATIC])dnl
-AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
-AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
-AC_REQUIRE([AC_PROG_RANLIB])dnl
-AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([AC_PROG_LD])dnl
-AC_REQUIRE([AC_PROG_NM])dnl
-AC_REQUIRE([AC_PROG_LN_S])dnl
-dnl
-
-case "$target" in
-NONE) lt_target="$host" ;;
-*) lt_target="$target" ;;
-esac
-
-# Check for any special flags to pass to ltconfig.
-libtool_flags="--cache-file=$cache_file"
-test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
-test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
-test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
-test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
-test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
-ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN],
-[libtool_flags="$libtool_flags --enable-dlopen"])
-ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
-[libtool_flags="$libtool_flags --enable-win32-dll"])
-AC_ARG_ENABLE(libtool-lock,
-  [  --disable-libtool-lock  avoid locking (might break parallel builds)])
-test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock"
-test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
-
-# Some flags need to be propagated to the compiler or linker for good
-# libtool support.
-case "$lt_target" in
-*-*-irix6*)
-  # Find out which ABI we are using.
-  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
-  if AC_TRY_EVAL(ac_compile); then
-    case "`/usr/bin/file conftest.o`" in
-    *32-bit*)
-      LD="${LD-ld} -32"
-      ;;
-    *N32*)
-      LD="${LD-ld} -n32"
-      ;;
-    *64-bit*)
-      LD="${LD-ld} -64"
-      ;;
-    esac
-  fi
-  rm -rf conftest*
-  ;;
-
-*-*-sco3.2v5*)
-  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
-  SAVE_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -belf"
-  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
-    [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])])
-  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
-    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
-    CFLAGS="$SAVE_CFLAGS"
-  fi
-  ;;
-
-ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
-[*-*-cygwin* | *-*-mingw*)
-  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
-  AC_CHECK_TOOL(AS, as, false)
-  AC_CHECK_TOOL(OBJDUMP, objdump, false)
-  ;;
-])
-esac
-])
-
-# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
-AC_DEFUN(AC_LIBTOOL_DLOPEN, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
-
-# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
-AC_DEFUN(AC_LIBTOOL_WIN32_DLL, [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
-
-# AC_ENABLE_SHARED - implement the --enable-shared flag
-# Usage: AC_ENABLE_SHARED[(DEFAULT)]
-#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
-#   `yes'.
-AC_DEFUN(AC_ENABLE_SHARED, [dnl
-define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
-AC_ARG_ENABLE(shared,
-changequote(<<, >>)dnl
-<<  --enable-shared[=PKGS]  build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
-changequote([, ])dnl
-[p=${PACKAGE-default}
-case "$enableval" in
-yes) enable_shared=yes ;;
-no) enable_shared=no ;;
-*)
-  enable_shared=no
-  # Look at the argument we got.  We use all the common list separators.
-  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
-  for pkg in $enableval; do
-    if test "X$pkg" = "X$p"; then
-      enable_shared=yes
-    fi
-  done
-  IFS="$ac_save_ifs"
-  ;;
-esac],
-enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
-])
-
-# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
-AC_DEFUN(AC_DISABLE_SHARED, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-AC_ENABLE_SHARED(no)])
-
-# AC_ENABLE_STATIC - implement the --enable-static flag
-# Usage: AC_ENABLE_STATIC[(DEFAULT)]
-#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
-#   `yes'.
-AC_DEFUN(AC_ENABLE_STATIC, [dnl
-define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
-AC_ARG_ENABLE(static,
-changequote(<<, >>)dnl
-<<  --enable-static[=PKGS]  build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
-changequote([, ])dnl
-[p=${PACKAGE-default}
-case "$enableval" in
-yes) enable_static=yes ;;
-no) enable_static=no ;;
-*)
-  enable_static=no
-  # Look at the argument we got.  We use all the common list separators.
-  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
-  for pkg in $enableval; do
-    if test "X$pkg" = "X$p"; then
-      enable_static=yes
-    fi
-  done
-  IFS="$ac_save_ifs"
-  ;;
-esac],
-enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
-])
-
-# AC_DISABLE_STATIC - set the default static flag to --disable-static
-AC_DEFUN(AC_DISABLE_STATIC, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-AC_ENABLE_STATIC(no)])
-
-
-# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
-# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
-#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
-#   `yes'.
-AC_DEFUN(AC_ENABLE_FAST_INSTALL, [dnl
-define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
-AC_ARG_ENABLE(fast-install,
-changequote(<<, >>)dnl
-<<  --enable-fast-install[=PKGS]  optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
-changequote([, ])dnl
-[p=${PACKAGE-default}
-case "$enableval" in
-yes) enable_fast_install=yes ;;
-no) enable_fast_install=no ;;
-*)
-  enable_fast_install=no
-  # Look at the argument we got.  We use all the common list separators.
-  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
-  for pkg in $enableval; do
-    if test "X$pkg" = "X$p"; then
-      enable_fast_install=yes
-    fi
-  done
-  IFS="$ac_save_ifs"
-  ;;
-esac],
-enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
-])
-
-# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install
-AC_DEFUN(AC_DISABLE_FAST_INSTALL, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-AC_ENABLE_FAST_INSTALL(no)])
-
-# AC_PROG_LD - find the path to the GNU or non-GNU linker
-AC_DEFUN(AC_PROG_LD,
-[AC_ARG_WITH(gnu-ld,
-[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
-test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
-AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([AC_CANONICAL_HOST])dnl
-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
-ac_prog=ld
-if test "$ac_cv_prog_gcc" = yes; then
-  # Check if gcc -print-prog-name=ld gives a path.
-  AC_MSG_CHECKING([for ld used by GCC])
-  ac_prog=`($CC -print-prog-name=ld) 2>&5`
-  case "$ac_prog" in
-    # Accept absolute paths.
-changequote(,)dnl
-    [\\/]* | [A-Za-z]:[\\/]*)
-      re_direlt='/[^/][^/]*/\.\./'
-changequote([,])dnl
-      # Canonicalize the path of ld
-      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
-      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
-       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
-      done
-      test -z "$LD" && LD="$ac_prog"
-      ;;
-  "")
-    # If it fails, then pretend we aren't using GCC.
-    ac_prog=ld
-    ;;
-  *)
-    # If it is relative, then search for the first ld in PATH.
-    with_gnu_ld=unknown
-    ;;
-  esac
-elif test "$with_gnu_ld" = yes; then
-  AC_MSG_CHECKING([for GNU ld])
-else
-  AC_MSG_CHECKING([for non-GNU ld])
-fi
-AC_CACHE_VAL(ac_cv_path_LD,
-[if test -z "$LD"; then
-  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
-  for ac_dir in $PATH; do
-    test -z "$ac_dir" && ac_dir=.
-    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
-      ac_cv_path_LD="$ac_dir/$ac_prog"
-      # Check to see if the program is GNU ld.  I'd rather use --version,
-      # but apparently some GNU ld's only accept -v.
-      # Break only if it was the GNU/non-GNU ld that we prefer.
-      if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
-       test "$with_gnu_ld" != no && break
-      else
-       test "$with_gnu_ld" != yes && break
-      fi
-    fi
-  done
-  IFS="$ac_save_ifs"
-else
-  ac_cv_path_LD="$LD" # Let the user override the test with a path.
-fi])
-LD="$ac_cv_path_LD"
-if test -n "$LD"; then
-  AC_MSG_RESULT($LD)
-else
-  AC_MSG_RESULT(no)
-fi
-test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
-AC_PROG_LD_GNU
-])
-
-AC_DEFUN(AC_PROG_LD_GNU,
-[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
-[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
-if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
-  ac_cv_prog_gnu_ld=yes
-else
-  ac_cv_prog_gnu_ld=no
-fi])
-])
-
-# AC_PROG_NM - find the path to a BSD-compatible name lister
-AC_DEFUN(AC_PROG_NM,
-[AC_MSG_CHECKING([for BSD-compatible nm])
-AC_CACHE_VAL(ac_cv_path_NM,
-[if test -n "$NM"; then
-  # Let the user override the test.
-  ac_cv_path_NM="$NM"
-else
-  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
-  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
-    test -z "$ac_dir" && ac_dir=.
-    if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then
-      # Check to see if the nm accepts a BSD-compat flag.
-      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
-      #   nm: unknown option "B" ignored
-      if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-       ac_cv_path_NM="$ac_dir/nm -B"
-       break
-      elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-       ac_cv_path_NM="$ac_dir/nm -p"
-       break
-      else
-       ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
-       continue # so that we can try to find one that supports BSD flags
-      fi
-    fi
-  done
-  IFS="$ac_save_ifs"
-  test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
-fi])
-NM="$ac_cv_path_NM"
-AC_MSG_RESULT([$NM])
-])
-
-# AC_CHECK_LIBM - check for math library
-AC_DEFUN(AC_CHECK_LIBM,
-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
-LIBM=
-case "$lt_target" in
-*-*-beos* | *-*-cygwin*)
-  # These system don't have libm
-  ;;
-*-ncr-sysv4.3*)
-  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
-  AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
-  ;;
-*)
-  AC_CHECK_LIB(m, main, LIBM="-lm")
-  ;;
-esac
-])
-
-# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
-# the libltdl convenience library, adds --enable-ltdl-convenience to
-# the configure arguments.  Note that LIBLTDL is not AC_SUBSTed, nor
-# is AC_CONFIG_SUBDIRS called.  If DIR is not provided, it is assumed
-# to be `${top_builddir}/libltdl'.  Make sure you start DIR with
-# '${top_builddir}/' (note the single quotes!) if your package is not
-# flat, and, if you're not using automake, define top_builddir as
-# appropriate in the Makefiles.
-AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-  case "$enable_ltdl_convenience" in
-  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
-  "") enable_ltdl_convenience=yes
-      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
-  esac
-  LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la
-  INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
-])
-
-# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
-# the libltdl installable library, and adds --enable-ltdl-install to
-# the configure arguments.  Note that LIBLTDL is not AC_SUBSTed, nor
-# is AC_CONFIG_SUBDIRS called.  If DIR is not provided, it is assumed
-# to be `${top_builddir}/libltdl'.  Make sure you start DIR with
-# '${top_builddir}/' (note the single quotes!) if your package is not
-# flat, and, if you're not using automake, define top_builddir as
-# appropriate in the Makefiles.
-# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
-AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
-  AC_CHECK_LIB(ltdl, main,
-  [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
-  [if test x"$enable_ltdl_install" = xno; then
-     AC_MSG_WARN([libltdl not installed, but installation disabled])
-   else
-     enable_ltdl_install=yes
-   fi
-  ])
-  if test x"$enable_ltdl_install" = x"yes"; then
-    ac_configure_args="$ac_configure_args --enable-ltdl-install"
-    LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la
-    INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
-  else
-    ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
-    LIBLTDL="-lltdl"
-    INCLTDL=
-  fi
-])
-
-dnl old names
-AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl
-AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl
-AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl
-AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl
-AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl
-AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl
-AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl
-
-dnl This is just to silence aclocal about the macro not being used
-ifelse([AC_DISABLE_FAST_INSTALL])dnl
-
diff --git a/config/config.guess b/config/config.guess
deleted file mode 100755 (executable)
index 6cb567b..0000000
+++ /dev/null
@@ -1,1087 +0,0 @@
-#! /bin/sh
-# Attempt to guess a canonical system name.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
-#   Free Software Foundation, Inc.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Written by Per Bothner <bothner@cygnus.com>.
-# The master version of this file is at the FSF in /home/gd/gnu/lib.
-# Please send patches to the Autoconf mailing list <autoconf@gnu.org>.
-#
-# This script attempts to guess a canonical system name similar to
-# config.sub.  If it succeeds, it prints the system name on stdout, and
-# exits with 0.  Otherwise, it exits with 1.
-#
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit system type (host/target name).
-#
-# Only a few systems have been added to this list; please add others
-# (but try to keep the structure clean).
-#
-
-# Use $HOST_CC if defined. $CC may point to a cross-compiler
-if test x"$CC_FOR_BUILD" = x; then
-  if test x"$HOST_CC" != x; then
-    CC_FOR_BUILD="$HOST_CC"
-  else
-    if test x"$CC" != x; then
-      CC_FOR_BUILD="$CC"
-    else
-      CC_FOR_BUILD=cc
-    fi
-  fi
-fi
-
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 8/24/94.)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
-       PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
-UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
-UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
-UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-
-dummy=dummy-$$
-trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
-    alpha:OSF1:*:*)
-       if test $UNAME_RELEASE = "V4.0"; then
-               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-       fi
-       # A Vn.n version is a released version.
-       # A Tn.n version is a released field test version.
-       # A Xn.n version is an unreleased experimental baselevel.
-       # 1.2 uses "1.2" for uname -r.
-       cat <<EOF >$dummy.s
-       .globl main
-       .ent main
-main:
-       .frame \$30,0,\$26,0
-       .prologue 0
-       .long 0x47e03d80 # implver $0
-       lda \$2,259
-       .long 0x47e20c21 # amask $2,$1
-       srl \$1,8,\$2
-       sll \$2,2,\$2
-       sll \$0,3,\$0
-       addl \$1,\$0,\$0
-       addl \$2,\$0,\$0
-       ret \$31,(\$26),1
-       .end main
-EOF
-       $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
-       if test "$?" = 0 ; then
-               ./$dummy
-               case "$?" in
-                       7)
-                               UNAME_MACHINE="alpha"
-                               ;;
-                       15)
-                               UNAME_MACHINE="alphaev5"
-                               ;;
-                       14)
-                               UNAME_MACHINE="alphaev56"
-                               ;;
-                       10)
-                               UNAME_MACHINE="alphapca56"
-                               ;;
-                       16)
-                               UNAME_MACHINE="alphaev6"
-                               ;;
-               esac
-       fi
-       rm -f $dummy.s $dummy
-       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-       exit 0 ;;
-    Alpha\ *:Windows_NT*:*)
-       # How do we know it's Interix rather than the generic POSIX subsystem?
-       # Should we change UNAME_MACHINE based on the output of uname instead
-       # of the specific Alpha model?
-       echo alpha-pc-interix
-       exit 0 ;;
-    21064:Windows_NT:50:3)
-       echo alpha-dec-winnt3.5
-       exit 0 ;;
-    Amiga*:UNIX_System_V:4.0:*)
-       echo m68k-cbm-sysv4
-       exit 0;;
-    amiga:NetBSD:*:*)
-      echo m68k-cbm-netbsd${UNAME_RELEASE}
-      exit 0 ;;
-    amiga:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    *:[Aa]miga[Oo][Ss]:*:*)
-       echo ${UNAME_MACHINE}-unknown-amigaos
-       exit 0 ;;
-    arc64:OpenBSD:*:*)
-       echo mips64el-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    arc:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    hkmips:OpenBSD:*:*)
-       echo mips-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    pmax:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    sgi:OpenBSD:*:*)
-       echo mips-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    wgrisc:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
-       echo arm-acorn-riscix${UNAME_RELEASE}
-       exit 0;;
-    arm32:NetBSD:*:*)
-       echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-       exit 0 ;;
-    SR2?01:HI-UX/MPP:*:*)
-       echo hppa1.1-hitachi-hiuxmpp
-       exit 0;;
-    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
-       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
-       if test "`(/bin/universe) 2>/dev/null`" = att ; then
-               echo pyramid-pyramid-sysv3
-       else
-               echo pyramid-pyramid-bsd
-       fi
-       exit 0 ;;
-    NILE*:*:*:dcosx)
-       echo pyramid-pyramid-svr4
-       exit 0 ;;
-    sun4H:SunOS:5.*:*)
-       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit 0 ;;
-    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
-       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit 0 ;;
-    i86pc:SunOS:5.*:*)
-       echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit 0 ;;
-    sun4*:SunOS:6*:*)
-       # According to config.sub, this is the proper way to canonicalize
-       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
-       # it's likely to be more like Solaris than SunOS4.
-       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit 0 ;;
-    sun4*:SunOS:*:*)
-       case "`/usr/bin/arch -k`" in
-           Series*|S4*)
-               UNAME_RELEASE=`uname -v`
-               ;;
-       esac
-       # Japanese Language versions have a version number like `4.1.3-JL'.
-       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
-       exit 0 ;;
-    sun3*:SunOS:*:*)
-       echo m68k-sun-sunos${UNAME_RELEASE}
-       exit 0 ;;
-    sun*:*:4.2BSD:*)
-       UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
-       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
-       case "`/bin/arch`" in
-           sun3)
-               echo m68k-sun-sunos${UNAME_RELEASE}
-               ;;
-           sun4)
-               echo sparc-sun-sunos${UNAME_RELEASE}
-               ;;
-       esac
-       exit 0 ;;
-    aushp:SunOS:*:*)
-       echo sparc-auspex-sunos${UNAME_RELEASE}
-       exit 0 ;;
-    atari*:NetBSD:*:*)
-       echo m68k-atari-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    atari*:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    # The situation for MiNT is a little confusing.  The machine name
-    # can be virtually everything (everything which is not
-    # "atarist" or "atariste" at least should have a processor 
-    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
-    # to the lowercase version "mint" (or "freemint").  Finally
-    # the system name "TOS" denotes a system which is actually not
-    # MiNT.  But MiNT is downward compatible to TOS, so this should
-    # be no problem.
-    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
-       exit 0 ;;
-    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
-       echo m68k-atari-mint${UNAME_RELEASE}
-        exit 0 ;;
-    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
-       exit 0 ;;
-    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-        echo m68k-milan-mint${UNAME_RELEASE}
-        exit 0 ;;
-    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-        echo m68k-hades-mint${UNAME_RELEASE}
-        exit 0 ;;
-    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-        echo m68k-unknown-mint${UNAME_RELEASE}
-        exit 0 ;;
-    sun3*:NetBSD:*:*)
-       echo m68k-sun-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    sun3*:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mac68k:NetBSD:*:*)
-       echo m68k-apple-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mac68k:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mvme68k:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    mvme88k:OpenBSD:*:*)
-       echo m88k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    powerpc:machten:*:*)
-       echo powerpc-apple-machten${UNAME_RELEASE}
-       exit 0 ;;
-    macppc:NetBSD:*:*)
-        echo powerpc-apple-netbsd${UNAME_RELEASE}
-        exit 0 ;;
-    RISC*:Mach:*:*)
-       echo mips-dec-mach_bsd4.3
-       exit 0 ;;
-    RISC*:ULTRIX:*:*)
-       echo mips-dec-ultrix${UNAME_RELEASE}
-       exit 0 ;;
-    VAX*:ULTRIX*:*:*)
-       echo vax-dec-ultrix${UNAME_RELEASE}
-       exit 0 ;;
-    2020:CLIX:*:* | 2430:CLIX:*:*)
-       echo clipper-intergraph-clix${UNAME_RELEASE}
-       exit 0 ;;
-    mips:*:*:UMIPS | mips:*:*:RISCos)
-       sed 's/^        //' << EOF >$dummy.c
-#ifdef __cplusplus
-       int main (int argc, char *argv[]) {
-#else
-       int main (argc, argv) int argc; char *argv[]; {
-#endif
-       #if defined (host_mips) && defined (MIPSEB)
-       #if defined (SYSTYPE_SYSV)
-         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
-       #endif
-       #if defined (SYSTYPE_SVR4)
-         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
-       #endif
-       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
-         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
-       #endif
-       #endif
-         exit (-1);
-       }
-EOF
-       $CC_FOR_BUILD $dummy.c -o $dummy \
-         && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
-         && rm $dummy.c $dummy && exit 0
-       rm -f $dummy.c $dummy
-       echo mips-mips-riscos${UNAME_RELEASE}
-       exit 0 ;;
-    Night_Hawk:Power_UNIX:*:*)
-       echo powerpc-harris-powerunix
-       exit 0 ;;
-    m88k:CX/UX:7*:*)
-       echo m88k-harris-cxux7
-       exit 0 ;;
-    m88k:*:4*:R4*)
-       echo m88k-motorola-sysv4
-       exit 0 ;;
-    m88k:*:3*:R3*)
-       echo m88k-motorola-sysv3
-       exit 0 ;;
-    AViiON:dgux:*:*)
-        # DG/UX returns AViiON for all architectures
-        UNAME_PROCESSOR=`/usr/bin/uname -p`
-        if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
-       if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
-            -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
-               echo m88k-dg-dgux${UNAME_RELEASE}
-       else
-               echo m88k-dg-dguxbcs${UNAME_RELEASE}
-       fi
-        else echo i586-dg-dgux${UNAME_RELEASE}
-        fi
-       exit 0 ;;
-    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
-       echo m88k-dolphin-sysv3
-       exit 0 ;;
-    M88*:*:R3*:*)
-       # Delta 88k system running SVR3
-       echo m88k-motorola-sysv3
-       exit 0 ;;
-    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
-       echo m88k-tektronix-sysv3
-       exit 0 ;;
-    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
-       echo m68k-tektronix-bsd
-       exit 0 ;;
-    *:IRIX*:*:*)
-       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
-       exit 0 ;;
-    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
-       echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
-       exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
-    i?86:AIX:*:*)
-       echo i386-ibm-aix
-       exit 0 ;;
-    *:AIX:2:3)
-       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
-               sed 's/^                //' << EOF >$dummy.c
-               #include <sys/systemcfg.h>
-
-               main()
-                       {
-                       if (!__power_pc())
-                               exit(1);
-                       puts("powerpc-ibm-aix3.2.5");
-                       exit(0);
-                       }
-EOF
-               $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
-               rm -f $dummy.c $dummy
-               echo rs6000-ibm-aix3.2.5
-       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
-               echo rs6000-ibm-aix3.2.4
-       else
-               echo rs6000-ibm-aix3.2
-       fi
-       exit 0 ;;
-    *:AIX:*:4)
-       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
-       if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
-               IBM_ARCH=rs6000
-       else
-               IBM_ARCH=powerpc
-       fi
-       if [ -x /usr/bin/oslevel ] ; then
-               IBM_REV=`/usr/bin/oslevel`
-       else
-               IBM_REV=4.${UNAME_RELEASE}
-       fi
-       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
-       exit 0 ;;
-    *:AIX:*:*)
-       echo rs6000-ibm-aix
-       exit 0 ;;
-    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
-       echo romp-ibm-bsd4.4
-       exit 0 ;;
-    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC NetBSD and
-       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
-       exit 0 ;;                           # report: romp-ibm BSD 4.3
-    *:BOSX:*:*)
-       echo rs6000-bull-bosx
-       exit 0 ;;
-    DPX/2?00:B.O.S.:*:*)
-       echo m68k-bull-sysv3
-       exit 0 ;;
-    9000/[34]??:4.3bsd:1.*:*)
-       echo m68k-hp-bsd
-       exit 0 ;;
-    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
-       echo m68k-hp-bsd4.4
-       exit 0 ;;
-    9000/[34678]??:HP-UX:*:*)
-       case "${UNAME_MACHINE}" in
-           9000/31? )            HP_ARCH=m68000 ;;
-           9000/[34]?? )         HP_ARCH=m68k ;;
-           9000/[678][0-9][0-9])
-              sed 's/^              //' << EOF >$dummy.c
-              #include <stdlib.h>
-              #include <unistd.h>
-
-              int main ()
-              {
-              #if defined(_SC_KERNEL_BITS)
-                  long bits = sysconf(_SC_KERNEL_BITS);
-              #endif
-                  long cpu  = sysconf (_SC_CPU_VERSION);
-
-                  switch (cpu)
-               {
-               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-               case CPU_PA_RISC2_0:
-              #if defined(_SC_KERNEL_BITS)
-                   switch (bits)
-                       {
-                       case 64: puts ("hppa2.0w"); break;
-                       case 32: puts ("hppa2.0n"); break;
-                       default: puts ("hppa2.0"); break;
-                       } break;
-              #else  /* !defined(_SC_KERNEL_BITS) */
-                   puts ("hppa2.0"); break;
-              #endif
-               default: puts ("hppa1.0"); break;
-               }
-                  exit (0);
-              }
-EOF
-       ($CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
-       rm -f $dummy.c $dummy
-       esac
-       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
-       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
-       exit 0 ;;
-    3050*:HI-UX:*:*)
-       sed 's/^        //' << EOF >$dummy.c
-       #include <unistd.h>
-       int
-       main ()
-       {
-         long cpu = sysconf (_SC_CPU_VERSION);
-         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
-            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
-            results, however.  */
-         if (CPU_IS_PA_RISC (cpu))
-           {
-             switch (cpu)
-               {
-                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
-                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
-                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
-                 default: puts ("hppa-hitachi-hiuxwe2"); break;
-               }
-           }
-         else if (CPU_IS_HP_MC68K (cpu))
-           puts ("m68k-hitachi-hiuxwe2");
-         else puts ("unknown-hitachi-hiuxwe2");
-         exit (0);
-       }
-EOF
-       $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
-       rm -f $dummy.c $dummy
-       echo unknown-hitachi-hiuxwe2
-       exit 0 ;;
-    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
-       echo hppa1.1-hp-bsd
-       exit 0 ;;
-    9000/8??:4.3bsd:*:*)
-       echo hppa1.0-hp-bsd
-       exit 0 ;;
-    *9??*:MPE/iX:*:*)
-       echo hppa1.0-hp-mpeix
-       exit 0 ;;
-    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
-       echo hppa1.1-hp-osf
-       exit 0 ;;
-    hp8??:OSF1:*:*)
-       echo hppa1.0-hp-osf
-       exit 0 ;;
-    i?86:OSF1:*:*)
-       if [ -x /usr/sbin/sysversion ] ; then
-           echo ${UNAME_MACHINE}-unknown-osf1mk
-       else
-           echo ${UNAME_MACHINE}-unknown-osf1
-       fi
-       exit 0 ;;
-    parisc*:Lites*:*:*)
-       echo hppa1.1-hp-lites
-       exit 0 ;;
-    hppa*:OpenBSD:*:*)
-       echo hppa-unknown-openbsd
-       exit 0 ;;
-    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
-       echo c1-convex-bsd
-        exit 0 ;;
-    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
-       if getsysinfo -f scalar_acc
-       then echo c32-convex-bsd
-       else echo c2-convex-bsd
-       fi
-        exit 0 ;;
-    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
-       echo c34-convex-bsd
-        exit 0 ;;
-    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
-       echo c38-convex-bsd
-        exit 0 ;;
-    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
-       echo c4-convex-bsd
-        exit 0 ;;
-    CRAY*X-MP:*:*:*)
-       echo xmp-cray-unicos
-        exit 0 ;;
-    CRAY*Y-MP:*:*:*)
-       echo ymp-cray-unicos${UNAME_RELEASE}
-       exit 0 ;;
-    CRAY*[A-Z]90:*:*:*)
-       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
-       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
-       exit 0 ;;
-    CRAY*TS:*:*:*)
-       echo t90-cray-unicos${UNAME_RELEASE}
-       exit 0 ;;
-    CRAY*T3E:*:*:*)
-       echo t3e-cray-unicosmk${UNAME_RELEASE}
-       exit 0 ;;
-    CRAY-2:*:*:*)
-       echo cray2-cray-unicos
-        exit 0 ;;
-    F300:UNIX_System_V:*:*)
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-        echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-        exit 0 ;;
-    F301:UNIX_System_V:*:*)
-       echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
-       exit 0 ;;
-    hp3[0-9][05]:NetBSD:*:*)
-       echo m68k-hp-netbsd${UNAME_RELEASE}
-       exit 0 ;;
-    hp300:OpenBSD:*:*)
-       echo m68k-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    i?86:BSD/386:*:* | i?86:BSD/OS:*:*)
-       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
-       exit 0 ;;
-    sparc*:BSD/OS:*:*)
-       echo sparc-unknown-bsdi${UNAME_RELEASE}
-       exit 0 ;;
-    *:BSD/OS:*:*)
-       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
-       exit 0 ;;
-    *:FreeBSD:*:*)
-       if test -x /usr/bin/objformat; then
-           if test "elf" = "`/usr/bin/objformat`"; then
-               echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'`
-               exit 0
-           fi
-       fi
-       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
-       exit 0 ;;
-    *:NetBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-       exit 0 ;;
-    *:OpenBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
-       exit 0 ;;
-    i*:CYGWIN*:*)
-       echo ${UNAME_MACHINE}-pc-cygwin
-       exit 0 ;;
-    i*:MINGW*:*)
-       echo ${UNAME_MACHINE}-pc-mingw32
-       exit 0 ;;
-    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
-       # How do we know it's Interix rather than the generic POSIX subsystem?
-       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
-       # UNAME_MACHINE based on the output of uname instead of i386?
-       echo i386-pc-interix
-       exit 0 ;;
-    i*:UWIN*:*)
-       echo ${UNAME_MACHINE}-pc-uwin
-       exit 0 ;;
-    p*:CYGWIN*:*)
-       echo powerpcle-unknown-cygwin
-       exit 0 ;;
-    prep*:SunOS:5.*:*)
-       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit 0 ;;
-    *:GNU:*:*)
-       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
-       exit 0 ;;
-    *:Linux:*:*)
-       # uname on the ARM produces all sorts of strangeness, and we need to
-       # filter it out.
-       case "$UNAME_MACHINE" in
-         armv*)                      UNAME_MACHINE=$UNAME_MACHINE ;;
-         arm* | sa110*)              UNAME_MACHINE="arm" ;;
-       esac
-
-       # The BFD linker knows what the default object file format is, so
-       # first see if it will tell us. cd to the root directory to prevent
-       # problems with other programs or directories called `ld' in the path.
-       ld_help_string=`cd /; ld --help 2>&1`
-       ld_supported_emulations=`echo $ld_help_string \
-                        | sed -ne '/supported emulations:/!d
-                                   s/[         ][      ]*/ /g
-                                   s/.*supported emulations: *//
-                                   s/ .*//
-                                   p'`
-        case "$ld_supported_emulations" in
-         i?86linux)  echo "${UNAME_MACHINE}-pc-linux-gnuaout"      ; exit 0 ;;
-         i?86coff)   echo "${UNAME_MACHINE}-pc-linux-gnucoff"      ; exit 0 ;;
-         sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-         armlinux)   echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-         m68klinux)  echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
-         elf32ppc)
-               # Determine Lib Version
-               cat >$dummy.c <<EOF
-#include <features.h>
-#if defined(__GLIBC__)
-extern char __libc_version[];
-extern char __libc_release[];
-#endif
-main(argc, argv)
-     int argc;
-     char *argv[];
-{
-#if defined(__GLIBC__)
-  printf("%s %s\n", __libc_version, __libc_release);
-#else
-  printf("unkown\n");
-#endif
-  return 0;
-}
-EOF
-               LIBC=""
-               $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
-               if test "$?" = 0 ; then
-                       ./$dummy | grep 1\.99 > /dev/null
-                       if test "$?" = 0 ; then
-                               LIBC="libc1"
-                       fi
-               fi      
-               rm -f $dummy.c $dummy
-               echo powerpc-unknown-linux-gnu${LIBC} ; exit 0 ;;
-       esac
-
-       if test "${UNAME_MACHINE}" = "alpha" ; then
-               sed 's/^        //'  <<EOF >$dummy.s
-               .globl main
-               .ent main
-       main:
-               .frame \$30,0,\$26,0
-               .prologue 0
-               .long 0x47e03d80 # implver $0
-               lda \$2,259
-               .long 0x47e20c21 # amask $2,$1
-               srl \$1,8,\$2
-               sll \$2,2,\$2
-               sll \$0,3,\$0
-               addl \$1,\$0,\$0
-               addl \$2,\$0,\$0
-               ret \$31,(\$26),1
-               .end main
-EOF
-               LIBC=""
-               $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
-               if test "$?" = 0 ; then
-                       ./$dummy
-                       case "$?" in
-                       7)
-                               UNAME_MACHINE="alpha"
-                               ;;
-                       15)
-                               UNAME_MACHINE="alphaev5"
-                               ;;
-                       14)
-                               UNAME_MACHINE="alphaev56"
-                               ;;
-                       10)
-                               UNAME_MACHINE="alphapca56"
-                               ;;
-                       16)
-                               UNAME_MACHINE="alphaev6"
-                               ;;
-                       esac
-
-                       objdump --private-headers $dummy | \
-                         grep ld.so.1 > /dev/null
-                       if test "$?" = 0 ; then
-                               LIBC="libc1"
-                       fi
-               fi
-               rm -f $dummy.s $dummy
-               echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
-       elif test "${UNAME_MACHINE}" = "mips" ; then
-         cat >$dummy.c <<EOF
-#ifdef __cplusplus
-       int main (int argc, char *argv[]) {
-#else
-       int main (argc, argv) int argc; char *argv[]; {
-#endif
-#ifdef __MIPSEB__
-  printf ("%s-unknown-linux-gnu\n", argv[1]);
-#endif
-#ifdef __MIPSEL__
-  printf ("%sel-unknown-linux-gnu\n", argv[1]);
-#endif
-  return 0;
-}
-EOF
-         $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
-         rm -f $dummy.c $dummy
-       else
-         # Either a pre-BFD a.out linker (linux-gnuoldld)
-         # or one that does not give us useful --help.
-         # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
-         # If ld does not provide *any* "supported emulations:"
-         # that means it is gnuoldld.
-         echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
-         test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
-
-         case "${UNAME_MACHINE}" in
-         i?86)
-           VENDOR=pc;
-           ;;
-         *)
-           VENDOR=unknown;
-           ;;
-         esac
-         # Determine whether the default compiler is a.out or elf
-         cat >$dummy.c <<EOF
-#include <features.h>
-#ifdef __cplusplus
-       int main (int argc, char *argv[]) {
-#else
-       int main (argc, argv) int argc; char *argv[]; {
-#endif
-#ifdef __ELF__
-# ifdef __GLIBC__
-#  if __GLIBC__ >= 2
-    printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
-#  else
-    printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
-#  endif
-# else
-   printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
-# endif
-#else
-  printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
-#endif
-  return 0;
-}
-EOF
-         $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
-         rm -f $dummy.c $dummy
-       fi ;;
-# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.  earlier versions
-# are messed up and put the nodename in both sysname and nodename.
-    i?86:DYNIX/ptx:4*:*)
-       echo i386-sequent-sysv4
-       exit 0 ;;
-    i?86:UNIX_SV:4.2MP:2.*)
-        # Unixware is an offshoot of SVR4, but it has its own version
-        # number series starting with 2...
-        # I am not positive that other SVR4 systems won't match this,
-       # I just have to hope.  -- rms.
-        # Use sysv4.2uw... so that sysv4* matches it.
-       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
-       exit 0 ;;
-    i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
-       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
-               echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
-       else
-               echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
-       fi
-       exit 0 ;;
-    i?86:*:5:7*)
-       UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
-       (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
-       (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) && UNAME_MACHINE=i586
-       (/bin/uname -X|egrep '^Machine.*Pent.*II' >/dev/null) && UNAME_MACHINE=i686
-       (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) && UNAME_MACHINE=i585
-       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}${UNAME_VERSION}-sysv${UNAME_RELEASE}
-       exit 0 ;;
-    i?86:*:3.2:*)
-       if test -f /usr/options/cb.name; then
-               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
-               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
-       elif /bin/uname -X 2>/dev/null >/dev/null ; then
-               UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
-               (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
-               (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
-                       && UNAME_MACHINE=i586
-               (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
-                       && UNAME_MACHINE=i686
-               (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
-                       && UNAME_MACHINE=i686
-               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
-       else
-               echo ${UNAME_MACHINE}-pc-sysv32
-       fi
-       exit 0 ;;
-    pc:*:*:*)
-        # uname -m prints for DJGPP always 'pc', but it prints nothing about
-        # the processor, so we play safe by assuming i386.
-       echo i386-pc-msdosdjgpp
-        exit 0 ;;
-    Intel:Mach:3*:*)
-       echo i386-pc-mach3
-       exit 0 ;;
-    paragon:*:*:*)
-       echo i860-intel-osf1
-       exit 0 ;;
-    i860:*:4.*:*) # i860-SVR4
-       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
-         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
-       else # Add other i860-SVR4 vendors below as they are discovered.
-         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
-       fi
-       exit 0 ;;
-    mini*:CTIX:SYS*5:*)
-       # "miniframe"
-       echo m68010-convergent-sysv
-       exit 0 ;;
-    M68*:*:R3V[567]*:*)
-       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
-    3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
-       OS_REL=''
-       test -r /etc/.relid \
-       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
-       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-         && echo i486-ncr-sysv4.3${OS_REL} && exit 0
-       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-         && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
-    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-          && echo i486-ncr-sysv4 && exit 0 ;;
-    m68*:LynxOS:2.*:*)
-       echo m68k-unknown-lynxos${UNAME_RELEASE}
-       exit 0 ;;
-    mc68030:UNIX_System_V:4.*:*)
-       echo m68k-atari-sysv4
-       exit 0 ;;
-    i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*)
-       echo i386-unknown-lynxos${UNAME_RELEASE}
-       exit 0 ;;
-    TSUNAMI:LynxOS:2.*:*)
-       echo sparc-unknown-lynxos${UNAME_RELEASE}
-       exit 0 ;;
-    rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
-       echo rs6000-unknown-lynxos${UNAME_RELEASE}
-       exit 0 ;;
-    SM[BE]S:UNIX_SV:*:*)
-       echo mips-dde-sysv${UNAME_RELEASE}
-       exit 0 ;;
-    RM*:ReliantUNIX-*:*:*)
-       echo mips-sni-sysv4
-       exit 0 ;;
-    RM*:SINIX-*:*:*)
-       echo mips-sni-sysv4
-       exit 0 ;;
-    *:SINIX-*:*:*)
-       if uname -p 2>/dev/null >/dev/null ; then
-               UNAME_MACHINE=`(uname -p) 2>/dev/null`
-               echo ${UNAME_MACHINE}-sni-sysv4
-       else
-               echo ns32k-sni-sysv
-       fi
-       exit 0 ;;
-    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-                           # says <Richard.M.Bartel@ccMail.Census.GOV>
-        echo i586-unisys-sysv4
-        exit 0 ;;
-    *:UNIX_System_V:4*:FTX*)
-       # From Gerald Hewes <hewes@openmarket.com>.
-       # How about differentiating between stratus architectures? -djm
-       echo hppa1.1-stratus-sysv4
-       exit 0 ;;
-    *:*:*:FTX*)
-       # From seanf@swdc.stratus.com.
-       echo i860-stratus-sysv4
-       exit 0 ;;
-    mc68*:A/UX:*:*)
-       echo m68k-apple-aux${UNAME_RELEASE}
-       exit 0 ;;
-    news*:NEWS-OS:*:6*)
-       echo mips-sony-newsos6
-       exit 0 ;;
-    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
-       if [ -d /usr/nec ]; then
-               echo mips-nec-sysv${UNAME_RELEASE}
-       else
-               echo mips-unknown-sysv${UNAME_RELEASE}
-       fi
-        exit 0 ;;
-    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
-       echo powerpc-be-beos
-       exit 0 ;;
-    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
-       echo powerpc-apple-beos
-       exit 0 ;;
-    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
-       echo i586-pc-beos
-       exit 0 ;;
-    SX-4:SUPER-UX:*:*)
-       echo sx4-nec-superux${UNAME_RELEASE}
-       exit 0 ;;
-    SX-5:SUPER-UX:*:*)
-       echo sx5-nec-superux${UNAME_RELEASE}
-       exit 0 ;;
-    Power*:Rhapsody:*:*)
-       echo powerpc-apple-rhapsody${UNAME_RELEASE}
-       exit 0 ;;
-    *:Rhapsody:*:*)
-       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
-       exit 0 ;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
-  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
-     I don't know....  */
-  printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
-  printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
-          "4"
-#else
-         ""
-#endif
-         ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
-  printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
-  int version;
-  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
-  if (version < 4)
-    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
-  else
-    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
-  exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
-  printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
-  printf ("ns32k-encore-mach\n"); exit (0);
-#else
-  printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
-  printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
-  printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
-  printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
-    struct utsname un;
-
-    uname(&un);
-
-    if (strncmp(un.version, "V2", 2) == 0) {
-       printf ("i386-sequent-ptx2\n"); exit (0);
-    }
-    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
-       printf ("i386-sequent-ptx1\n"); exit (0);
-    }
-    printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-#if !defined (ultrix)
-  printf ("vax-dec-bsd\n"); exit (0);
-#else
-  printf ("vax-dec-ultrix\n"); exit (0);
-#endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
-EOF
-
-$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0
-rm -f $dummy.c $dummy
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
-    case `getsysinfo -f cpu_type` in
-    c1*)
-       echo c1-convex-bsd
-       exit 0 ;;
-    c2*)
-       if getsysinfo -f scalar_acc
-       then echo c32-convex-bsd
-       else echo c2-convex-bsd
-       fi
-       exit 0 ;;
-    c34*)
-       echo c34-convex-bsd
-       exit 0 ;;
-    c38*)
-       echo c38-convex-bsd
-       exit 0 ;;
-    c4*)
-       echo c4-convex-bsd
-       exit 0 ;;
-    esac
-fi
-
-#echo '(Unable to guess system type)' 1>&2
-
-exit 1
diff --git a/config/config.h.in b/config/config.h.in
deleted file mode 100644 (file)
index 50accc0..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/* config/config.h.in.  Generated automatically from configure.in by autoheader.  */
-#ifndef CONFIG_H
-#define CONFIG_H
-
-
-/* Define to empty if the keyword does not work.  */
-#undef const
-
-/* Define if you don't have vprintf but do have _doprnt.  */
-#undef HAVE_DOPRNT
-
-/* Define if you have the strftime function.  */
-#undef HAVE_STRFTIME
-
-/* Define if you have the vprintf function.  */
-#undef HAVE_VPRINTF
-
-/* Define if you have the ANSI C header files.  */
-#undef STDC_HEADERS
-
-/* Define if you can safely include both <sys/time.h> and <time.h>.  */
-#undef TIME_WITH_SYS_TIME
-
-/* Define if your <sys/time.h> declares struct tm.  */
-#undef TM_IN_SYS_TIME
-
-/* IEEE can be prevented from raising signals with fpsetmask(0) */
-#undef MUST_DISABLE_FPMASK
-
-#undef MUST_DISABLE_SIGFPE
-
-/* realloc does not support NULL as argument */
-#undef NO_NULL_REALLOC
-
-/* Define if you have the class function.  */
-#undef HAVE_CLASS
-
-/* Define if you have the finite function.  */
-#undef HAVE_FINITE
-
-/* Define if you have the fp_class function.  */
-#undef HAVE_FP_CLASS
-
-/* Define if you have the fpclass function.  */
-#undef HAVE_FPCLASS
-
-/* Define if you have the fpclassify function.  */
-#undef HAVE_FPCLASSIFY
-
-/* Define if you have the getrusage function.  */
-#undef HAVE_GETRUSAGE
-
-/* Define if you have the gettimeofday function.  */
-#undef HAVE_GETTIMEOFDAY
-
-/* Define if you have the isinf function.  */
-#undef HAVE_ISINF
-
-/* Define if you have the isnan function.  */
-#undef HAVE_ISNAN
-
-/* Define if you have the memmove function.  */
-#undef HAVE_MEMMOVE
-
-/* Define if you have the mktime function.  */
-#undef HAVE_MKTIME
-
-/* Define if you have the snprintf function.  */
-#undef HAVE_SNPRINTF
-
-/* Define if you have the strchr function.  */
-#undef HAVE_STRCHR
-
-/* Define if you have the strerror function.  */
-#undef HAVE_STRERROR
-
-/* Define if you have the vsnprintf function.  */
-#undef HAVE_VSNPRINTF
-
-/* Define if you have the <fcntl.h> header file.  */
-#undef HAVE_FCNTL_H
-
-/* Define if you have the <float.h> header file.  */
-#undef HAVE_FLOAT_H
-
-/* Define if you have the <fp_class.h> header file.  */
-#undef HAVE_FP_CLASS_H
-
-/* Define if you have the <ieeefp.h> header file.  */
-#undef HAVE_IEEEFP_H
-
-/* Define if you have the <malloc.h> header file.  */
-#undef HAVE_MALLOC_H
-
-/* Define if you have the <math.h> header file.  */
-#undef HAVE_MATH_H
-
-/* Define if you have the <sys/param.h> header file.  */
-#undef HAVE_SYS_PARAM_H
-
-/* Define if you have the <sys/resource.h> header file.  */
-#undef HAVE_SYS_RESOURCE_H
-
-/* Define if you have the <sys/time.h> header file.  */
-#undef HAVE_SYS_TIME_H
-
-/* Define if you have the <sys/times.h> header file.  */
-#undef HAVE_SYS_TIMES_H
-
-/* Define if you have the <unistd.h> header file.  */
-#undef HAVE_UNISTD_H
-
-/* Define if you have the m library (-lm).  */
-#undef HAVE_LIBM
-
-/* Name of package */
-#undef PACKAGE
-
-/* Version number of package */
-#undef VERSION
-
-
-/* define strrchr, strchr and memcpy, memmove in terms of bsd funcs
-   make sure you are NOT using bcopy, index or rindex in the code */
-      
-#if STDC_HEADERS
-# include <string.h>
-#else
-# ifndef HAVE_STRCHR
-#  define strchr index
-#  define strrchr rindex
-# endif
-char *strchr (), *strrchr ();
-# ifndef HAVE_MEMMOVE
-#  define memcpy(d, s, n) bcopy ((s), (d), (n))
-#  define memmove(d, s, n) bcopy ((s), (d), (n))
-# endif
-#endif
-
-
-#if NO_NULL_REALLOC
-# define rrd_realloc(a,b) ( (a) == NULL ? malloc( (b) ) : realloc( (a) , (b) ))
-#else
-# define rrd_realloc(a,b) realloc((a), (b))
-#endif      
-
-#if HAVE_MATH_H
-#  include <math.h>
-#endif
-
-#if HAVE_FLOAT_H
-#  include <float.h>
-#endif
-
-#if HAVE_IEEEFP_H
-#  include <ieeefp.h>
-#endif
-
-#if HAVE_FP_CLASS_H
-#  include <fp_class.h>
-#endif
-
-/* for Solaris */
-#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASS))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fpclass(a) == FP_NINF || fpclass(a) == FP_PINF)
-#endif
-
-/* for OSF1 Digital Unix */
-#if (! defined(HAVE_ISINF) && defined(HAVE_FP_CLASS) && defined(HAVE_FP_CLASS_H))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fp_class(a) == FP_NEG_INF || fp_class(a) == FP_POS_INF)
-#endif
-
-#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASSIFY) && defined(FP_PLUS_INF) && defined(FP_MINUS_INF))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fpclassify(a) == FP_MINUS_INF || fpclassify(a) == FP_PLUS_INF)
-#endif
-
-#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASSIFY) && defined(FP_INFINITE))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fpclassify(a) == FP_INFINITE)
-#endif
-
-/* for AIX */
-#if (! defined(HAVE_ISINF) && defined(HAVE_CLASS))
-#  define HAVE_ISINF 1
-#  define isinf(a) (class(a) == FP_MINUS_INF || class(a) == FP_PLUS_INF)
-#endif
-
-#if (! defined (HAVE_FINITE) && defined (HAVE_ISFINITE))
-#  define HAVE_FINITE 1
-#  define finite(a) isfinite(a)
-#endif
-
-#if (! defined(HAVE_FINITE) && defined(HAVE_ISNAN) && defined(HAVE_ISINF))
-#  define HAVE_FINITE 1
-#  define finite(a) (! isnan(a) && ! isinf(a))
-#endif
-
-#ifndef HAVE_FINITE
-#error "Can't compile without finite function"
-#endif
-
-#ifndef HAVE_ISINF
-#error "Can't compile without isinf function"
-#endif
-
-#endif /* CONFIG_H */
-
diff --git a/config/config.sub b/config/config.sub
deleted file mode 100755 (executable)
index 2436b45..0000000
+++ /dev/null
@@ -1,1215 +0,0 @@
-#! /bin/sh
-# Configuration validation subroutine script, version 1.1.
-#   Copyright (C) 1991, 92-97, 1998, 1999 Free Software Foundation, Inc.
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine.  It does not imply ALL GNU software can.
-#
-# This file is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Configuration subroutine to validate and canonicalize a configuration type.
-# Supply the specified configuration type as an argument.
-# If it is invalid, we print an error message on stderr and exit with code 1.
-# Otherwise, we print the canonical config type on stdout and succeed.
-
-# This file is supposed to be the same for all GNU packages
-# and recognize all the CPU types, system types and aliases
-# that are meaningful with *any* GNU software.
-# Each package is responsible for reporting which valid configurations
-# it does not support.  The user should be able to distinguish
-# a failure to support a valid configuration from a meaningless
-# configuration.
-
-# The goal of this file is to map all the various variations of a given
-# machine specification into a single specification in the form:
-#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or in some cases, the newer four-part form:
-#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-# It is wrong to echo any other type of specification.
-
-if [ x$1 = x ]
-then
-       echo Configuration name missing. 1>&2
-       echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
-       echo "or     $0 ALIAS" 1>&2
-       echo where ALIAS is a recognized configuration type. 1>&2
-       exit 1
-fi
-
-# First pass through any local machine types.
-case $1 in
-       *local*)
-               echo $1
-               exit 0
-               ;;
-       *)
-       ;;
-esac
-
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
-  linux-gnu*)
-    os=-$maybe_os
-    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
-    ;;
-  *)
-    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
-    if [ $basic_machine != $1 ]
-    then os=`echo $1 | sed 's/.*-/-/'`
-    else os=; fi
-    ;;
-esac
-
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work.  We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
-       -sun*os*)
-               # Prevent following clause from handling this invalid input.
-               ;;
-       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-       -apple)
-               os=
-               basic_machine=$1
-               ;;
-       -sim | -cisco | -oki | -wec | -winbond)
-               os=
-               basic_machine=$1
-               ;;
-       -scout)
-               ;;
-       -wrs)
-               os=vxworks
-               basic_machine=$1
-               ;;
-       -hiux*)
-               os=-hiuxwe2
-               ;;
-       -sco5)
-               os=-sco3.2v5
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -sco4)
-               os=-sco3.2v4
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -sco3.2.[4-9]*)
-               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -sco3.2v[4-9]*)
-               # Don't forget version if it is 3.2v4 or newer.
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -sco*)
-               os=-sco3.2v2
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -udk*)
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -isc)
-               os=-isc2.2
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -clix*)
-               basic_machine=clipper-intergraph
-               ;;
-       -isc*)
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
-               ;;
-       -lynx*)
-               os=-lynxos
-               ;;
-       -ptx*)
-               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
-               ;;
-       -windowsnt*)
-               os=`echo $os | sed -e 's/windowsnt/winnt/'`
-               ;;
-       -psos*)
-               os=-psos
-               ;;
-esac
-
-# Decode aliases for certain CPU-COMPANY combinations.
-case $basic_machine in
-       # Recognize the basic CPU types without company name.
-       # Some are omitted here because they have special meanings below.
-       tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
-               | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
-               | 580 | i960 | h8300 \
-               | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
-               | alpha | alphaev[4-7] | alphaev56 | alphapca5[67] \
-               | we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \
-               | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \
-               | mips64orion | mips64orionel | mipstx39 | mipstx39el \
-               | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
-               | mips64vr5000 | miprs64vr5000el \
-               | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \
-               | thumb | d10v)
-               basic_machine=$basic_machine-unknown
-               ;;
-       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65)
-               ;;
-
-       # We use `pc' rather than `unknown'
-       # because (1) that's what they normally are, and
-       # (2) the word "unknown" tends to confuse beginning users.
-       i[34567]86)
-         basic_machine=$basic_machine-pc
-         ;;
-       # Object if more than one company name word.
-       *-*-*)
-               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
-               exit 1
-               ;;
-       # Recognize the basic CPU types with company name.
-       vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \
-             | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
-             | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
-             | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
-             | xmp-* | ymp-* \
-             | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \
-             | alpha-* | alphaev[4-7]-* | alphaev56-* | alphapca5[67]-* \
-             | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
-             | clipper-* | orion-* \
-             | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
-             | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \
-             | mips64el-* | mips64orion-* | mips64orionel-* \
-             | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
-             | mipstx39-* | mipstx39el-* \
-             | f301-* | armv*-* | t3e-* \
-             | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
-             | thumb-* | v850-* | d30v-* | tic30-* | c30-* )
-               ;;
-       # Recognize the various machine names and aliases which stand
-       # for a CPU type and a company and sometimes even an OS.
-       386bsd)
-               basic_machine=i386-unknown
-               os=-bsd
-               ;;
-       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
-               basic_machine=m68000-att
-               ;;
-       3b*)
-               basic_machine=we32k-att
-               ;;
-       a29khif)
-               basic_machine=a29k-amd
-               os=-udi
-               ;;
-       adobe68k)
-               basic_machine=m68010-adobe
-               os=-scout
-               ;;
-       alliant | fx80)
-               basic_machine=fx80-alliant
-               ;;
-       altos | altos3068)
-               basic_machine=m68k-altos
-               ;;
-       am29k)
-               basic_machine=a29k-none
-               os=-bsd
-               ;;
-       amdahl)
-               basic_machine=580-amdahl
-               os=-sysv
-               ;;
-       amiga | amiga-*)
-               basic_machine=m68k-cbm
-               ;;
-       amigaos | amigados)
-               basic_machine=m68k-cbm
-               os=-amigaos
-               ;;
-       amigaunix | amix)
-               basic_machine=m68k-cbm
-               os=-sysv4
-               ;;
-       apollo68)
-               basic_machine=m68k-apollo
-               os=-sysv
-               ;;
-       apollo68bsd)
-               basic_machine=m68k-apollo
-               os=-bsd
-               ;;
-       aux)
-               basic_machine=m68k-apple
-               os=-aux
-               ;;
-       balance)
-               basic_machine=ns32k-sequent
-               os=-dynix
-               ;;
-       convex-c1)
-               basic_machine=c1-convex
-               os=-bsd
-               ;;
-       convex-c2)
-               basic_machine=c2-convex
-               os=-bsd
-               ;;
-       convex-c32)
-               basic_machine=c32-convex
-               os=-bsd
-               ;;
-       convex-c34)
-               basic_machine=c34-convex
-               os=-bsd
-               ;;
-       convex-c38)
-               basic_machine=c38-convex
-               os=-bsd
-               ;;
-       cray | ymp)
-               basic_machine=ymp-cray
-               os=-unicos
-               ;;
-       cray2)
-               basic_machine=cray2-cray
-               os=-unicos
-               ;;
-       [ctj]90-cray)
-               basic_machine=c90-cray
-               os=-unicos
-               ;;
-       crds | unos)
-               basic_machine=m68k-crds
-               ;;
-       da30 | da30-*)
-               basic_machine=m68k-da30
-               ;;
-       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
-               basic_machine=mips-dec
-               ;;
-       delta | 3300 | motorola-3300 | motorola-delta \
-             | 3300-motorola | delta-motorola)
-               basic_machine=m68k-motorola
-               ;;
-       delta88)
-               basic_machine=m88k-motorola
-               os=-sysv3
-               ;;
-       dpx20 | dpx20-*)
-               basic_machine=rs6000-bull
-               os=-bosx
-               ;;
-       dpx2* | dpx2*-bull)
-               basic_machine=m68k-bull
-               os=-sysv3
-               ;;
-       ebmon29k)
-               basic_machine=a29k-amd
-               os=-ebmon
-               ;;
-       elxsi)
-               basic_machine=elxsi-elxsi
-               os=-bsd
-               ;;
-       encore | umax | mmax)
-               basic_machine=ns32k-encore
-               ;;
-       es1800 | OSE68k | ose68k | ose | OSE)
-               basic_machine=m68k-ericsson
-               os=-ose
-               ;;
-       fx2800)
-               basic_machine=i860-alliant
-               ;;
-       genix)
-               basic_machine=ns32k-ns
-               ;;
-       gmicro)
-               basic_machine=tron-gmicro
-               os=-sysv
-               ;;
-       h3050r* | hiux*)
-               basic_machine=hppa1.1-hitachi
-               os=-hiuxwe2
-               ;;
-       h8300hms)
-               basic_machine=h8300-hitachi
-               os=-hms
-               ;;
-       h8300xray)
-               basic_machine=h8300-hitachi
-               os=-xray
-               ;;
-       h8500hms)
-               basic_machine=h8500-hitachi
-               os=-hms
-               ;;
-       harris)
-               basic_machine=m88k-harris
-               os=-sysv3
-               ;;
-       hp300-*)
-               basic_machine=m68k-hp
-               ;;
-       hp300bsd)
-               basic_machine=m68k-hp
-               os=-bsd
-               ;;
-       hp300hpux)
-               basic_machine=m68k-hp
-               os=-hpux
-               ;;
-       hp3k9[0-9][0-9] | hp9[0-9][0-9])
-               basic_machine=hppa1.0-hp
-               ;;
-       hp9k2[0-9][0-9] | hp9k31[0-9])
-               basic_machine=m68000-hp
-               ;;
-       hp9k3[2-9][0-9])
-               basic_machine=m68k-hp
-               ;;
-       hp9k6[0-9][0-9] | hp6[0-9][0-9])
-               basic_machine=hppa1.0-hp
-               ;;
-       hp9k7[0-79][0-9] | hp7[0-79][0-9])
-               basic_machine=hppa1.1-hp
-               ;;
-       hp9k78[0-9] | hp78[0-9])
-               # FIXME: really hppa2.0-hp
-               basic_machine=hppa1.1-hp
-               ;;
-       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
-               # FIXME: really hppa2.0-hp
-               basic_machine=hppa1.1-hp
-               ;;
-       hp9k8[0-9][13679] | hp8[0-9][13679])
-               basic_machine=hppa1.1-hp
-               ;;
-       hp9k8[0-9][0-9] | hp8[0-9][0-9])
-               basic_machine=hppa1.0-hp
-               ;;
-       hppa-next)
-               os=-nextstep3
-               ;;
-       hppaosf)
-               basic_machine=hppa1.1-hp
-               os=-osf
-               ;;
-       hppro)
-               basic_machine=hppa1.1-hp
-               os=-proelf
-               ;;
-       i370-ibm* | ibm*)
-               basic_machine=i370-ibm
-               os=-mvs
-               ;;
-# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
-       i[34567]86v32)
-               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-               os=-sysv32
-               ;;
-       i[34567]86v4*)
-               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-               os=-sysv4
-               ;;
-       i[34567]86v)
-               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-               os=-sysv
-               ;;
-       i[34567]86sol2)
-               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
-               os=-solaris2
-               ;;
-       i386mach)
-               basic_machine=i386-mach
-               os=-mach
-               ;;
-       i386-vsta | vsta)
-               basic_machine=i386-unknown
-               os=-vsta
-               ;;
-       i386-go32 | go32)
-               basic_machine=i386-unknown
-               os=-go32
-               ;;
-       i386-mingw32 | mingw32)
-               basic_machine=i386-unknown
-               os=-mingw32
-               ;;
-       iris | iris4d)
-               basic_machine=mips-sgi
-               case $os in
-                   -irix*)
-                       ;;
-                   *)
-                       os=-irix4
-                       ;;
-               esac
-               ;;
-       isi68 | isi)
-               basic_machine=m68k-isi
-               os=-sysv
-               ;;
-       m88k-omron*)
-               basic_machine=m88k-omron
-               ;;
-       magnum | m3230)
-               basic_machine=mips-mips
-               os=-sysv
-               ;;
-       merlin)
-               basic_machine=ns32k-utek
-               os=-sysv
-               ;;
-       miniframe)
-               basic_machine=m68000-convergent
-               ;;
-       *mint | *MiNT)
-               basic_machine=m68k-atari
-               os=-mint
-               ;;
-       mipsel*-linux*)
-               basic_machine=mipsel-unknown
-               os=-linux-gnu
-               ;;
-       mips*-linux*)
-               basic_machine=mips-unknown
-               os=-linux-gnu
-               ;;
-       mips3*-*)
-               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
-               ;;
-       mips3*)
-               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
-               ;;
-       monitor)
-               basic_machine=m68k-rom68k
-               os=-coff
-               ;;
-       msdos)
-               basic_machine=i386-unknown
-               os=-msdos
-               ;;
-       ncr3000)
-               basic_machine=i486-ncr
-               os=-sysv4
-               ;;
-       netbsd386)
-               basic_machine=i386-unknown
-               os=-netbsd
-               ;;
-       netwinder)
-               basic_machine=armv4l-corel
-               os=-linux
-               ;;
-       news | news700 | news800 | news900)
-               basic_machine=m68k-sony
-               os=-newsos
-               ;;
-       news1000)
-               basic_machine=m68030-sony
-               os=-newsos
-               ;;
-       news-3600 | risc-news)
-               basic_machine=mips-sony
-               os=-newsos
-               ;;
-       necv70)
-               basic_machine=v70-nec
-               os=-sysv
-               ;;
-       next | m*-next )
-               basic_machine=m68k-next
-               case $os in
-                   -nextstep* )
-                       ;;
-                   -ns2*)
-                     os=-nextstep2
-                       ;;
-                   *)
-                     os=-nextstep3
-                       ;;
-               esac
-               ;;
-       nh3000)
-               basic_machine=m68k-harris
-               os=-cxux
-               ;;
-       nh[45]000)
-               basic_machine=m88k-harris
-               os=-cxux
-               ;;
-       nindy960)
-               basic_machine=i960-intel
-               os=-nindy
-               ;;
-       mon960)
-               basic_machine=i960-intel
-               os=-mon960
-               ;;
-       np1)
-               basic_machine=np1-gould
-               ;;
-       op50n-* | op60c-*)
-               basic_machine=hppa1.1-oki
-               os=-proelf
-               ;;
-       OSE68000 | ose68000)
-               basic_machine=m68000-ericsson
-               os=-ose
-               ;;
-       os68k)
-               basic_machine=m68k-none
-               os=-os68k
-               ;;
-       pa-hitachi)
-               basic_machine=hppa1.1-hitachi
-               os=-hiuxwe2
-               ;;
-       paragon)
-               basic_machine=i860-intel
-               os=-osf
-               ;;
-       pbd)
-               basic_machine=sparc-tti
-               ;;
-       pbb)
-               basic_machine=m68k-tti
-               ;;
-        pc532 | pc532-*)
-               basic_machine=ns32k-pc532
-               ;;
-       pentium | p5 | k5 | k6 | nexen)
-               basic_machine=i586-pc
-               ;;
-       pentiumpro | p6 | 6x86)
-               basic_machine=i686-pc
-               ;;
-       pentiumii | pentium2)
-               basic_machine=i786-pc
-               ;;
-       pentium-* | p5-* | k5-* | k6-* | nexen-*)
-               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
-               ;;
-       pentiumpro-* | p6-* | 6x86-*)
-               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
-               ;;
-       pentiumii-* | pentium2-*)
-               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
-               ;;
-       pn)
-               basic_machine=pn-gould
-               ;;
-       power)  basic_machine=rs6000-ibm
-               ;;
-       ppc)    basic_machine=powerpc-unknown
-               ;;
-       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
-               ;;
-       ppcle | powerpclittle | ppc-le | powerpc-little)
-               basic_machine=powerpcle-unknown
-               ;;
-       ppcle-* | powerpclittle-*)
-               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
-               ;;
-       ps2)
-               basic_machine=i386-ibm
-               ;;
-       rom68k)
-               basic_machine=m68k-rom68k
-               os=-coff
-               ;;
-       rm[46]00)
-               basic_machine=mips-siemens
-               ;;
-       rtpc | rtpc-*)
-               basic_machine=romp-ibm
-               ;;
-       sa29200)
-               basic_machine=a29k-amd
-               os=-udi
-               ;;
-       sequent)
-               basic_machine=i386-sequent
-               ;;
-       sh)
-               basic_machine=sh-hitachi
-               os=-hms
-               ;;
-       sparclite-wrs)
-               basic_machine=sparclite-wrs
-               os=-vxworks
-               ;;
-       sps7)
-               basic_machine=m68k-bull
-               os=-sysv2
-               ;;
-       spur)
-               basic_machine=spur-unknown
-               ;;
-       st2000)
-               basic_machine=m68k-tandem
-               ;;
-       stratus)
-               basic_machine=i860-stratus
-               os=-sysv4
-               ;;
-       sun2)
-               basic_machine=m68000-sun
-               ;;
-       sun2os3)
-               basic_machine=m68000-sun
-               os=-sunos3
-               ;;
-       sun2os4)
-               basic_machine=m68000-sun
-               os=-sunos4
-               ;;
-       sun3os3)
-               basic_machine=m68k-sun
-               os=-sunos3
-               ;;
-       sun3os4)
-               basic_machine=m68k-sun
-               os=-sunos4
-               ;;
-       sun4os3)
-               basic_machine=sparc-sun
-               os=-sunos3
-               ;;
-       sun4os4)
-               basic_machine=sparc-sun
-               os=-sunos4
-               ;;
-       sun4sol2)
-               basic_machine=sparc-sun
-               os=-solaris2
-               ;;
-       sun3 | sun3-*)
-               basic_machine=m68k-sun
-               ;;
-       sun4)
-               basic_machine=sparc-sun
-               ;;
-       sun386 | sun386i | roadrunner)
-               basic_machine=i386-sun
-               ;;
-       symmetry)
-               basic_machine=i386-sequent
-               os=-dynix
-               ;;
-       t3e)
-               basic_machine=t3e-cray
-               os=-unicos
-               ;;
-       tx39)
-               basic_machine=mipstx39-unknown
-               ;;
-       tx39el)
-               basic_machine=mipstx39el-unknown
-               ;;
-       tower | tower-32)
-               basic_machine=m68k-ncr
-               ;;
-       udi29k)
-               basic_machine=a29k-amd
-               os=-udi
-               ;;
-       ultra3)
-               basic_machine=a29k-nyu
-               os=-sym1
-               ;;
-       v810 | necv810)
-               basic_machine=v810-nec
-               os=-none
-               ;;
-       vaxv)
-               basic_machine=vax-dec
-               os=-sysv
-               ;;
-       vms)
-               basic_machine=vax-dec
-               os=-vms
-               ;;
-       vpp*|vx|vx-*)
-               basic_machine=f301-fujitsu
-               ;;
-       vxworks960)
-               basic_machine=i960-wrs
-               os=-vxworks
-               ;;
-       vxworks68)
-               basic_machine=m68k-wrs
-               os=-vxworks
-               ;;
-       vxworks29k)
-               basic_machine=a29k-wrs
-               os=-vxworks
-               ;;
-       w65*)
-               basic_machine=w65-wdc
-               os=-none
-               ;;
-       w89k-*)
-               basic_machine=hppa1.1-winbond
-               os=-proelf
-               ;;
-       xmp)
-               basic_machine=xmp-cray
-               os=-unicos
-               ;;
-        xps | xps100)
-               basic_machine=xps100-honeywell
-               ;;
-       z8k-*-coff)
-               basic_machine=z8k-unknown
-               os=-sim
-               ;;
-       none)
-               basic_machine=none-none
-               os=-none
-               ;;
-
-# Here we handle the default manufacturer of certain CPU types.  It is in
-# some cases the only manufacturer, in others, it is the most popular.
-       w89k)
-               basic_machine=hppa1.1-winbond
-               ;;
-       op50n)
-               basic_machine=hppa1.1-oki
-               ;;
-       op60c)
-               basic_machine=hppa1.1-oki
-               ;;
-       mips)
-               if [ x$os = x-linux-gnu ]; then
-                       basic_machine=mips-unknown
-               else
-                       basic_machine=mips-mips
-               fi
-               ;;
-       romp)
-               basic_machine=romp-ibm
-               ;;
-       rs6000)
-               basic_machine=rs6000-ibm
-               ;;
-       vax)
-               basic_machine=vax-dec
-               ;;
-       pdp11)
-               basic_machine=pdp11-dec
-               ;;
-       we32k)
-               basic_machine=we32k-att
-               ;;
-       sparc | sparcv9)
-               basic_machine=sparc-sun
-               ;;
-        cydra)
-               basic_machine=cydra-cydrome
-               ;;
-       orion)
-               basic_machine=orion-highlevel
-               ;;
-       orion105)
-               basic_machine=clipper-highlevel
-               ;;
-       mac | mpw | mac-mpw)
-               basic_machine=m68k-apple
-               ;;
-       pmac | pmac-mpw)
-               basic_machine=powerpc-apple
-               ;;
-       c4x*)
-               basic_machine=c4x-none
-               os=-coff
-               ;;
-       *)
-               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
-               exit 1
-               ;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
-       *-digital*)
-               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
-               ;;
-       *-commodore*)
-               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
-               ;;
-       *)
-               ;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if [ x"$os" != x"" ]
-then
-case $os in
-        # First match some system type aliases
-        # that might get confused with valid system types.
-       # -solaris* is a basic system type, with this one exception.
-       -solaris1 | -solaris1.*)
-               os=`echo $os | sed -e 's|solaris1|sunos4|'`
-               ;;
-       -solaris)
-               os=-solaris2
-               ;;
-       -svr4*)
-               os=-sysv4
-               ;;
-       -unixware*)
-               os=-sysv4.2uw
-               ;;
-       -gnu/linux*)
-               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
-               ;;
-       # First accept the basic system types.
-       # The portable systems comes first.
-       # Each alternative MUST END IN A *, to match a version number.
-       # -sysv* is not here because it comes later, after sysvr4.
-       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
-             | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
-             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
-             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
-             | -aos* \
-             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
-             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-             | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
-             | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
-             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
-             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-             | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
-             | -interix* | -uwin* | -rhapsody* | -openstep* | -oskit*)
-       # Remember, each alternative MUST END IN *, to match a version number.
-               ;;
-       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
-             | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
-             | -macos* | -mpw* | -magic* | -mon960* | -lnews*)
-               ;;
-       -mac*)
-               os=`echo $os | sed -e 's|mac|macos|'`
-               ;;
-       -linux*)
-               os=`echo $os | sed -e 's|linux|linux-gnu|'`
-               ;;
-       -sunos5*)
-               os=`echo $os | sed -e 's|sunos5|solaris2|'`
-               ;;
-       -sunos6*)
-               os=`echo $os | sed -e 's|sunos6|solaris3|'`
-               ;;
-       -osfrose*)
-               os=-osfrose
-               ;;
-       -osf*)
-               os=-osf
-               ;;
-       -utek*)
-               os=-bsd
-               ;;
-       -dynix*)
-               os=-bsd
-               ;;
-       -acis*)
-               os=-aos
-               ;;
-       -386bsd)
-               os=-bsd
-               ;;
-       -ctix* | -uts*)
-               os=-sysv
-               ;;
-       -ns2 )
-               os=-nextstep2
-               ;;
-       # Preserve the version number of sinix5.
-       -sinix5.*)
-               os=`echo $os | sed -e 's|sinix|sysv|'`
-               ;;
-       -sinix*)
-               os=-sysv4
-               ;;
-       -triton*)
-               os=-sysv3
-               ;;
-       -oss*)
-               os=-sysv3
-               ;;
-       -svr4)
-               os=-sysv4
-               ;;
-       -svr3)
-               os=-sysv3
-               ;;
-       -sysvr4)
-               os=-sysv4
-               ;;
-       # This must come after -sysvr4.
-       -sysv*)
-               ;;
-       -ose*)
-               os=-ose
-               ;;
-       -es1800*)
-               os=-ose
-               ;;
-       -xenix)
-               os=-xenix
-               ;;
-        -*mint | -*MiNT)
-               os=-mint
-               ;;
-       -none)
-               ;;
-       *)
-               # Get rid of the `-' at the beginning of $os.
-               os=`echo $os | sed 's/[^-]*-//'`
-               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
-               exit 1
-               ;;
-esac
-else
-
-# Here we handle the default operating systems that come with various machines.
-# The value should be what the vendor currently ships out the door with their
-# machine or put another way, the most popular os provided with the machine.
-
-# Note that if you're going to try to match "-MANUFACTURER" here (say,
-# "-sun"), then you have to tell the case statement up towards the top
-# that MANUFACTURER isn't an operating system.  Otherwise, code above
-# will signal an error saying that MANUFACTURER isn't an operating
-# system, and we'll never get to this point.
-
-case $basic_machine in
-       *-acorn)
-               os=-riscix1.2
-               ;;
-       arm*-corel)
-               os=-linux
-               ;;
-       arm*-semi)
-               os=-aout
-               ;;
-        pdp11-*)
-               os=-none
-               ;;
-       *-dec | vax-*)
-               os=-ultrix4.2
-               ;;
-       m68*-apollo)
-               os=-domain
-               ;;
-       i386-sun)
-               os=-sunos4.0.2
-               ;;
-       m68000-sun)
-               os=-sunos3
-               # This also exists in the configure program, but was not the
-               # default.
-               # os=-sunos4
-               ;;
-       m68*-cisco)
-               os=-aout
-               ;;
-       mips*-cisco)
-               os=-elf
-               ;;
-       mips*-*)
-               os=-elf
-               ;;
-       *-tti)  # must be before sparc entry or we get the wrong os.
-               os=-sysv3
-               ;;
-       sparc-* | *-sun)
-               os=-sunos4.1.1
-               ;;
-       *-be)
-               os=-beos
-               ;;
-       *-ibm)
-               os=-aix
-               ;;
-       *-wec)
-               os=-proelf
-               ;;
-       *-winbond)
-               os=-proelf
-               ;;
-       *-oki)
-               os=-proelf
-               ;;
-       *-hp)
-               os=-hpux
-               ;;
-       *-hitachi)
-               os=-hiux
-               ;;
-       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
-               os=-sysv
-               ;;
-       *-cbm)
-               os=-amigaos
-               ;;
-       *-dg)
-               os=-dgux
-               ;;
-       *-dolphin)
-               os=-sysv3
-               ;;
-       m68k-ccur)
-               os=-rtu
-               ;;
-       m88k-omron*)
-               os=-luna
-               ;;
-       *-next )
-               os=-nextstep
-               ;;
-       *-sequent)
-               os=-ptx
-               ;;
-       *-crds)
-               os=-unos
-               ;;
-       *-ns)
-               os=-genix
-               ;;
-       i370-*)
-               os=-mvs
-               ;;
-       *-next)
-               os=-nextstep3
-               ;;
-        *-gould)
-               os=-sysv
-               ;;
-        *-highlevel)
-               os=-bsd
-               ;;
-       *-encore)
-               os=-bsd
-               ;;
-        *-sgi)
-               os=-irix
-               ;;
-        *-siemens)
-               os=-sysv4
-               ;;
-       *-masscomp)
-               os=-rtu
-               ;;
-       f301-fujitsu)
-               os=-uxpv
-               ;;
-       *-rom68k)
-               os=-coff
-               ;;
-       *-*bug)
-               os=-coff
-               ;;
-       *-apple)
-               os=-macos
-               ;;
-       *-atari*)
-               os=-mint
-               ;;
-       *)
-               os=-none
-               ;;
-esac
-fi
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer.  We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
-       *-unknown)
-               case $os in
-                       -riscix*)
-                               vendor=acorn
-                               ;;
-                       -sunos*)
-                               vendor=sun
-                               ;;
-                       -aix*)
-                               vendor=ibm
-                               ;;
-                       -beos*)
-                               vendor=be
-                               ;;
-                       -hpux*)
-                               vendor=hp
-                               ;;
-                       -mpeix*)
-                               vendor=hp
-                               ;;
-                       -hiux*)
-                               vendor=hitachi
-                               ;;
-                       -unos*)
-                               vendor=crds
-                               ;;
-                       -dgux*)
-                               vendor=dg
-                               ;;
-                       -luna*)
-                               vendor=omron
-                               ;;
-                       -genix*)
-                               vendor=ns
-                               ;;
-                       -mvs*)
-                               vendor=ibm
-                               ;;
-                       -ptx*)
-                               vendor=sequent
-                               ;;
-                       -vxsim* | -vxworks*)
-                               vendor=wrs
-                               ;;
-                       -aux*)
-                               vendor=apple
-                               ;;
-                       -hms*)
-                               vendor=hitachi
-                               ;;
-                       -mpw* | -macos*)
-                               vendor=apple
-                               ;;
-                       -*mint | -*MiNT)
-                               vendor=atari
-                               ;;
-               esac
-               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
-               ;;
-esac
-
-echo $basic_machine$os
diff --git a/config/install-sh b/config/install-sh
deleted file mode 100755 (executable)
index e9de238..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-#!/bin/sh
-#
-# install - install a program, script, or datafile
-# This comes from X11R5 (mit/util/scripts/install.sh).
-#
-# Copyright 1991 by the Massachusetts Institute of Technology
-#
-# Permission to use, copy, modify, distribute, and sell this software and its
-# documentation for any purpose is hereby granted without fee, provided that
-# the above copyright notice appear in all copies and that both that
-# copyright notice and this permission notice appear in supporting
-# documentation, and that the name of M.I.T. not be used in advertising or
-# publicity pertaining to distribution of the software without specific,
-# written prior permission.  M.I.T. makes no representations about the
-# suitability of this software for any purpose.  It is provided "as is"
-# without express or implied warranty.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch.  It can only install one file at a time, a restriction
-# shared with many OS's install programs.
-
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-transformbasename=""
-transform_arg=""
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
-    case $1 in
-       -c) instcmd="$cpprog"
-           shift
-           continue;;
-
-       -d) dir_arg=true
-           shift
-           continue;;
-
-       -m) chmodcmd="$chmodprog $2"
-           shift
-           shift
-           continue;;
-
-       -o) chowncmd="$chownprog $2"
-           shift
-           shift
-           continue;;
-
-       -g) chgrpcmd="$chgrpprog $2"
-           shift
-           shift
-           continue;;
-
-       -s) stripcmd="$stripprog"
-           shift
-           continue;;
-
-       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
-           shift
-           continue;;
-
-       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
-           shift
-           continue;;
-
-       *)  if [ x"$src" = x ]
-           then
-               src=$1
-           else
-               # this colon is to work around a 386BSD /bin/sh bug
-               :
-               dst=$1
-           fi
-           shift
-           continue;;
-    esac
-done
-
-if [ x"$src" = x ]
-then
-       echo "install:  no input file specified"
-       exit 1
-else
-       true
-fi
-
-if [ x"$dir_arg" != x ]; then
-       dst=$src
-       src=""
-       
-       if [ -d $dst ]; then
-               instcmd=:
-               chmodcmd=""
-       else
-               instcmd=mkdir
-       fi
-else
-
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad 
-# if $src (and thus $dsttmp) contains '*'.
-
-       if [ -f $src -o -d $src ]
-       then
-               true
-       else
-               echo "install:  $src does not exist"
-               exit 1
-       fi
-       
-       if [ x"$dst" = x ]
-       then
-               echo "install:  no destination specified"
-               exit 1
-       else
-               true
-       fi
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
-       if [ -d $dst ]
-       then
-               dst="$dst"/`basename $src`
-       else
-               true
-       fi
-fi
-
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
-
-# Make sure that the destination directory exists.
-#  this part is taken from Noah Friedman's mkinstalldirs script
-
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='   
-'
-IFS="${IFS-${defaultIFS}}"
-
-oIFS="${IFS}"
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS="${oIFS}"
-
-pathcomp=''
-
-while [ $# -ne 0 ] ; do
-       pathcomp="${pathcomp}${1}"
-       shift
-
-       if [ ! -d "${pathcomp}" ] ;
-        then
-               $mkdirprog "${pathcomp}"
-       else
-               true
-       fi
-
-       pathcomp="${pathcomp}/"
-done
-fi
-
-if [ x"$dir_arg" != x ]
-then
-       $doit $instcmd $dst &&
-
-       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
-       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
-       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
-       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
-
-# If we're going to rename the final executable, determine the name now.
-
-       if [ x"$transformarg" = x ] 
-       then
-               dstfile=`basename $dst`
-       else
-               dstfile=`basename $dst $transformbasename | 
-                       sed $transformarg`$transformbasename
-       fi
-
-# don't allow the sed command to completely eliminate the filename
-
-       if [ x"$dstfile" = x ] 
-       then
-               dstfile=`basename $dst`
-       else
-               true
-       fi
-
-# Make a temp file name in the proper directory.
-
-       dsttmp=$dstdir/#inst.$$#
-
-# Move or copy the file name to the temp name
-
-       $doit $instcmd $src $dsttmp &&
-
-       trap "rm -f ${dsttmp}" 0 &&
-
-# and set any options; do chmod last to preserve setuid bits
-
-# If any of these fail, we abort the whole thing.  If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
-
-       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
-       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
-       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
-       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
-
-# Now rename the file to the real destination.
-
-       $doit $rmcmd -f $dstdir/$dstfile &&
-       $doit $mvcmd $dsttmp $dstdir/$dstfile 
-
-fi &&
-
-
-exit 0
diff --git a/config/ltconfig b/config/ltconfig
deleted file mode 100755 (executable)
index 3857247..0000000
+++ /dev/null
@@ -1,3017 +0,0 @@
-#! /bin/sh
-
-# ltconfig - Create a system-specific libtool.
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# A lot of this script is taken from autoconf-2.10.
-
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-echo=echo
-if test "X$1" = X--no-reexec; then
-  # Discard the --no-reexec flag, and continue.
-  shift
-elif test "X$1" = X--fallback-echo; then
-  # Avoid inline document here, it may be left over
-  :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
-  # Yippee, $echo works!
-  :
-else
-  # Restart under the correct shell.
-  exec "$SHELL" "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
-  # used as fallback echo
-  shift
-  cat <<EOF
-$*
-EOF
-  exit 0
-fi
-
-# Find the correct PATH separator.  Usually this is `:', but
-# DJGPP uses `;' like DOS.
-if test "X${PATH_SEPARATOR+set}" != "Xset"; then
-  UNAME=${UNAME-`uname 2>/dev/null`}
-  case X$UNAME in
-    *-DOS) PATH_SEPARATOR=';' ;;
-    *)     PATH_SEPARATOR=':' ;;
-  esac
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi
-
-if test "X${echo_test_string+set}" != "Xset"; then
-  # find a string as large as possible, as long as the shell can cope with it
-  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
-    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
-    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
-       echo_test_string="`eval $cmd`" &&
-       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then
-      break
-    fi
-  done
-fi
-
-if test "X`($echo '\t') 2>/dev/null`" != 'X\t' ||
-   test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then
-  # The Solaris, AIX, and Digital Unix default echo programs unquote
-  # backslashes.  This makes it impossible to quote backslashes using
-  #   echo "$something" | sed 's/\\/\\\\/g'
-  #
-  # So, first we look for a working echo in the user's PATH.
-
-  IFS="${IFS=  }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-  for dir in $PATH /usr/ucb; do
-    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
-       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
-       test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-      echo="$dir/echo"
-      break
-    fi
-  done
-  IFS="$save_ifs"
-
-  if test "X$echo" = Xecho; then
-    # We didn't find a better echo, so look for alternatives.
-    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
-       test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-      # This shell has a builtin print -r that does the trick.
-      echo='print -r'
-    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
-        test "X$CONFIG_SHELL" != X/bin/ksh; then
-      # If we have ksh, try running ltconfig again with it.
-      ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}"
-      export ORIGINAL_CONFIG_SHELL
-      CONFIG_SHELL=/bin/ksh
-      export CONFIG_SHELL
-      exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"}
-    else
-      # Try using printf.
-      echo='printf "%s\n"'
-      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
-        test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-       # Cool, printf works
-       :
-      elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
-          test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-       CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL"
-       export CONFIG_SHELL
-       SHELL="$CONFIG_SHELL"
-       export SHELL
-       echo="$CONFIG_SHELL $0 --fallback-echo"
-      elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
-          test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-       echo="$CONFIG_SHELL $0 --fallback-echo"
-      else
-       # maybe with a smaller string...
-       prev=:
-
-       for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
-         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then
-           break
-         fi
-         prev="$cmd"
-       done
-
-       if test "$prev" != 'sed 50q "$0"'; then
-         echo_test_string=`eval $prev`
-         export echo_test_string
-         exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"}
-       else
-         # Oops.  We lost completely, so just stick with echo.
-         echo=echo
-       fi
-      fi
-    fi
-  fi
-fi
-
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e s/^X//'
-sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# The name of this program.
-progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'`
-
-# Constants:
-PROGRAM=ltconfig
-PACKAGE=libtool
-VERSION=1.3.3
-TIMESTAMP=" (1.385.2.181 1999/07/02 15:49:11)"
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5'
-rm="rm -f"
-
-help="Try \`$progname --help' for more information."
-
-# Global variables:
-default_ofile=libtool
-can_build_shared=yes
-enable_shared=yes
-# All known linkers require a `.a' archive for static linking (except M$VC,
-# which needs '.lib').
-enable_static=yes
-enable_fast_install=yes
-enable_dlopen=unknown
-enable_win32_dll=no
-ltmain=
-silent=
-srcdir=
-ac_config_guess=
-ac_config_sub=
-host=
-nonopt=
-ofile="$default_ofile"
-verify_host=yes
-with_gcc=no
-with_gnu_ld=no
-need_locks=yes
-ac_ext=c
-objext=o
-libext=a
-exeext=
-cache_file=
-
-old_AR="$AR"
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-old_CPPFLAGS="$CPPFLAGS"
-old_LDFLAGS="$LDFLAGS"
-old_LD="$LD"
-old_LN_S="$LN_S"
-old_LIBS="$LIBS"
-old_NM="$NM"
-old_RANLIB="$RANLIB"
-old_DLLTOOL="$DLLTOOL"
-old_OBJDUMP="$OBJDUMP"
-old_AS="$AS"
-
-# Parse the command line options.
-args=
-prev=
-for option
-do
-  case "$option" in
-  -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
-  *) optarg= ;;
-  esac
-
-  # If the previous option needs an argument, assign it.
-  if test -n "$prev"; then
-    eval "$prev=\$option"
-    prev=
-    continue
-  fi
-
-  case "$option" in
-  --help) cat <<EOM
-Usage: $progname [OPTION]... [HOST [LTMAIN]]
-
-Generate a system-specific libtool script.
-
-    --debug                enable verbose shell tracing
-    --disable-shared       do not build shared libraries
-    --disable-static       do not build static libraries
-    --disable-fast-install do not optimize for fast installation
-    --enable-dlopen        enable dlopen support
-    --enable-win32-dll     enable building dlls on win32 hosts
-    --help                 display this help and exit
-    --no-verify            do not verify that HOST is a valid host type
--o, --output=FILE          specify the output file [default=$default_ofile]
-    --quiet                same as \`--silent'
-    --silent               do not print informational messages
-    --srcdir=DIR           find \`config.guess' in DIR
-    --version              output version information and exit
-    --with-gcc             assume that the GNU C compiler will be used
-    --with-gnu-ld          assume that the C compiler uses the GNU linker
-    --disable-lock         disable file locking
-    --cache-file=FILE      configure cache file
-
-LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program
-that provides basic libtool functionality.
-
-HOST is the canonical host system name [default=guessed].
-EOM
-  exit 0
-  ;;
-
-  --debug)
-    echo "$progname: enabling shell trace mode"
-    set -x
-    ;;
-
-  --disable-shared) enable_shared=no ;;
-
-  --disable-static) enable_static=no ;;
-
-  --disable-fast-install) enable_fast_install=no ;;
-
-  --enable-dlopen) enable_dlopen=yes ;;
-
-  --enable-win32-dll) enable_win32_dll=yes ;;
-
-  --quiet | --silent) silent=yes ;;
-
-  --srcdir) prev=srcdir ;;
-  --srcdir=*) srcdir="$optarg" ;;
-
-  --no-verify) verify_host=no ;;
-
-  --output | -o) prev=ofile ;;
-  --output=*) ofile="$optarg" ;;
-
-  --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;;
-
-  --with-gcc) with_gcc=yes ;;
-  --with-gnu-ld) with_gnu_ld=yes ;;
-
-  --disable-lock) need_locks=no ;;
-
-  --cache-file=*) cache_file="$optarg" ;;
-
-  -*)
-    echo "$progname: unrecognized option \`$option'" 1>&2
-    echo "$help" 1>&2
-    exit 1
-    ;;
-
-  *)
-    if test -z "$ltmain"; then
-      ltmain="$option"
-    elif test -z "$host"; then
-# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
-#      if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
-#        echo "$progname: warning \`$option' is not a valid host type" 1>&2
-#      fi
-      host="$option"
-    else
-      echo "$progname: too many arguments" 1>&2
-      echo "$help" 1>&2
-      exit 1
-    fi ;;
-  esac
-done
-
-if test -z "$ltmain"; then
-  echo "$progname: you must specify a LTMAIN file" 1>&2
-  echo "$help" 1>&2
-  exit 1
-fi
-
-if test ! -f "$ltmain"; then
-  echo "$progname: \`$ltmain' does not exist" 1>&2
-  echo "$help" 1>&2
-  exit 1
-fi
-
-# Quote any args containing shell metacharacters.
-ltconfig_args=
-for arg
-do
-  case "$arg" in
-  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
-  ltconfig_args="$ltconfig_args '$arg'" ;;
-  *) ltconfig_args="$ltconfig_args $arg" ;;
-  esac
-done
-
-# A relevant subset of AC_INIT.
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 5 compiler messages saved in config.log
-# 6 checking for... messages and results
-if test "$silent" = yes; then
-  exec 6>/dev/null
-else
-  exec 6>&1
-fi
-exec 5>>./config.log
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
-
-if test -n "$cache_file" && test -r "$cache_file"; then
-  echo "loading cache $cache_file within ltconfig"
-  . $cache_file
-fi
-
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
-  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
-  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
-    ac_n= ac_c='
-' ac_t='       '
-  else
-    ac_n=-n ac_c= ac_t=
-  fi
-else
-  ac_n= ac_c='\c' ac_t=
-fi
-
-if test -z "$srcdir"; then
-  # Assume the source directory is the same one as the path to LTMAIN.
-  srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'`
-  test "$srcdir" = "$ltmain" && srcdir=.
-fi
-
-trap "$rm conftest*; exit 1" 1 2 15
-if test "$verify_host" = yes; then
-  # Check for config.guess and config.sub.
-  ac_aux_dir=
-  for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
-    if test -f $ac_dir/config.guess; then
-      ac_aux_dir=$ac_dir
-      break
-    fi
-  done
-  if test -z "$ac_aux_dir"; then
-    echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
-    echo "$help" 1>&2
-    exit 1
-  fi
-  ac_config_guess=$ac_aux_dir/config.guess
-  ac_config_sub=$ac_aux_dir/config.sub
-
-  # Make sure we can run config.sub.
-  if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then :
-  else
-    echo "$progname: cannot run $ac_config_sub" 1>&2
-    echo "$help" 1>&2
-    exit 1
-  fi
-
-  echo $ac_n "checking host system type""... $ac_c" 1>&6
-
-  host_alias=$host
-  case "$host_alias" in
-  "")
-    if host_alias=`$SHELL $ac_config_guess`; then :
-    else
-      echo "$progname: cannot guess host type; you must specify one" 1>&2
-      echo "$help" 1>&2
-      exit 1
-    fi ;;
-  esac
-  host=`$SHELL $ac_config_sub $host_alias`
-  echo "$ac_t$host" 1>&6
-
-  # Make sure the host verified.
-  test -z "$host" && exit 1
-
-elif test -z "$host"; then
-  echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
-  echo "$help" 1>&2
-  exit 1
-else
-  host_alias=$host
-fi
-
-# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
-case "$host_os" in
-linux-gnu*) ;;
-linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
-esac
-
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-
-case "$host_os" in
-aix3*)
-  # AIX sometimes has problems with the GCC collect2 program.  For some
-  # reason, if we set the COLLECT_NAMES environment variable, the problems
-  # vanish in a puff of smoke.
-  if test "${COLLECT_NAMES+set}" != set; then
-    COLLECT_NAMES=
-    export COLLECT_NAMES
-  fi
-  ;;
-esac
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR cru $oldlib$oldobjs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-# Set a sane default for `AR'.
-test -z "$AR" && AR=ar
-
-# Set a sane default for `OBJDUMP'.
-test -z "$OBJDUMP" && OBJDUMP=objdump
-
-# If RANLIB is not set, then run the test.
-if test "${RANLIB+set}" != "set"; then
-  result=no
-
-  echo $ac_n "checking for ranlib... $ac_c" 1>&6
-  IFS="${IFS=  }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-  for dir in $PATH; do
-    test -z "$dir" && dir=.
-    if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then
-      RANLIB="ranlib"
-      result="ranlib"
-      break
-    fi
-  done
-  IFS="$save_ifs"
-
-  echo "$ac_t$result" 1>&6
-fi
-
-if test -n "$RANLIB"; then
-  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
-  old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
-fi
-
-# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin.
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-test -z "$OBJDUMP" && OBJDUMP=objdump
-test -z "$AS" && AS=as
-
-# Check to see if we are using GCC.
-if test "$with_gcc" != yes || test -z "$CC"; then
-  # If CC is not set, then try to find GCC or a usable CC.
-  if test -z "$CC"; then
-    echo $ac_n "checking for gcc... $ac_c" 1>&6
-    IFS="${IFS=        }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    for dir in $PATH; do
-      test -z "$dir" && dir=.
-      if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then
-       CC="gcc"
-       break
-      fi
-    done
-    IFS="$save_ifs"
-
-    if test -n "$CC"; then
-      echo "$ac_t$CC" 1>&6
-    else
-      echo "$ac_t"no 1>&6
-    fi
-  fi
-
-  # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
-  if test -z "$CC"; then
-    echo $ac_n "checking for cc... $ac_c" 1>&6
-    IFS="${IFS=        }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    cc_rejected=no
-    for dir in $PATH; do
-      test -z "$dir" && dir=.
-      if test -f $dir/cc || test -f $dir/cc$ac_exeext; then
-       if test "$dir/cc" = "/usr/ucb/cc"; then
-         cc_rejected=yes
-         continue
-       fi
-       CC="cc"
-       break
-      fi
-    done
-    IFS="$save_ifs"
-    if test $cc_rejected = yes; then
-      # We found a bogon in the path, so make sure we never use it.
-      set dummy $CC
-      shift
-      if test $# -gt 0; then
-       # We chose a different compiler from the bogus one.
-       # However, it has the same name, so the bogon will be chosen
-       # first if we set CC to just the name; use the full file name.
-       shift
-       set dummy "$dir/cc" "$@"
-       shift
-       CC="$@"
-      fi
-    fi
-
-    if test -n "$CC"; then
-      echo "$ac_t$CC" 1>&6
-    else
-      echo "$ac_t"no 1>&6
-    fi
-
-    if test -z "$CC"; then
-      echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
-      exit 1
-    fi
-  fi
-
-  # Now see if the compiler is really GCC.
-  with_gcc=no
-  echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
-  echo "$progname:581: checking whether we are using GNU C" >&5
-
-  $rm conftest.c
-  cat > conftest.c <<EOF
-#ifdef __GNUC__
-  yes;
-#endif
-EOF
-  if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
-    with_gcc=yes
-  fi
-  $rm conftest.c
-  echo "$ac_t$with_gcc" 1>&6
-fi
-
-# Allow CC to be a program name with arguments.
-set dummy $CC
-compiler="$2"
-
-echo $ac_n "checking for object suffix... $ac_c" 1>&6
-$rm conftest*
-echo 'int i = 1;' > conftest.c
-echo "$progname:603: checking for object suffix" >& 5
-if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then
-  # Append any warnings to the config.log.
-  cat conftest.err 1>&5
-
-  for ac_file in conftest.*; do
-    case $ac_file in
-    *.c) ;;
-    *) objext=`echo $ac_file | sed -e s/conftest.//` ;;
-    esac
-  done
-else
-  cat conftest.err 1>&5
-  echo "$progname: failed program was:" >&5
-  cat conftest.c >&5
-fi
-$rm conftest*
-echo "$ac_t$objext" 1>&6
-
-echo $ac_n "checking for executable suffix... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_cv_exeext="no"
-  $rm conftest*
-  echo 'main () { return 0; }' > conftest.c
-  echo "$progname:629: checking for executable suffix" >& 5
-  if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then
-    # Append any warnings to the config.log.
-    cat conftest.err 1>&5
-
-    for ac_file in conftest.*; do
-      case $ac_file in
-      *.c | *.err | *.$objext ) ;;
-      *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;;
-      esac
-    done
-  else
-    cat conftest.err 1>&5
-    echo "$progname: failed program was:" >&5
-    cat conftest.c >&5
-  fi
-  $rm conftest*
-fi
-if test "X$ac_cv_exeext" = Xno; then
-  exeext=""
-else
-  exeext="$ac_cv_exeext"
-fi
-echo "$ac_t$ac_cv_exeext" 1>&6
-
-echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
-pic_flag=
-special_shlib_compile_flags=
-wl=
-link_static_flag=
-no_builtin_flag=
-
-if test "$with_gcc" = yes; then
-  wl='-Wl,'
-  link_static_flag='-static'
-
-  case "$host_os" in
-  beos* | irix5* | irix6* | osf3* | osf4* | bsdi3* )
-    # PIC is the default for these OSes.
-    ;;
-  aix*)
-    # Below there is a dirty hack to force normal static linking with -ldl
-    # The problem is because libdl dynamically linked with both libc and
-    # libC (AIX C++ library), which obviously doesn't included in libraries
-    # list by gcc. This cause undefined symbols with -static flags.
-    # This hack allows C programs to be linked with "-static -ldl", but
-    # we not sure about C++ programs.
-    link_static_flag="$link_static_flag ${wl}-lC"
-    ;;
-  cygwin* | mingw* | os2*)
-    # We can build DLLs from non-PIC.
-    ;;
-  amigaos*)
-    # FIXME: we need at least 68020 code to build shared libraries, but
-    # adding the `-m68020' flag to GCC prevents building anything better,
-    # like `-m68040'.
-    pic_flag='-m68020 -resident32 -malways-restore-a4'
-    ;;
-  sysv4*MP*)
-    if test -d /usr/nec; then
-       pic_flag=-Kconform_pic
-    fi
-    ;;
-  *)
-    pic_flag='-fPIC'
-    ;;
-  esac
-else
-  # PORTME Check for PIC flags for the system compiler.
-  case "$host_os" in
-  aix3* | aix4*)
-    # All AIX code is PIC.
-    link_static_flag='-bnso -bI:/lib/syscalls.exp'
-    ;;
-
-  hpux9* | hpux10* | hpux11*)
-    # Is there a better link_static_flag that works with the bundled CC?
-    wl='-Wl,'
-    link_static_flag="${wl}-a ${wl}archive"
-    pic_flag='+Z'
-    ;;
-
-  irix5* | irix6*)
-    wl='-Wl,'
-    link_static_flag='-non_shared'
-    # PIC (with -KPIC) is the default.
-    ;;
-
-  cygwin* | mingw* | os2*)
-    # We can build DLLs from non-PIC.
-    ;;
-
-  osf3* | osf4*)
-    # All OSF/1 code is PIC.
-    wl='-Wl,'
-    link_static_flag='-non_shared'
-    ;;
-
-  sco3.2v5*)
-    pic_flag='-Kpic'
-    link_static_flag='-dn'
-    special_shlib_compile_flags='-belf'
-    ;;
-
-  solaris*)
-    pic_flag='-KPIC'
-    link_static_flag='-Bstatic'
-    wl='-Wl,'
-    ;;
-
-  sunos4*)
-    pic_flag='-PIC'
-    link_static_flag='-Bstatic'
-    wl='-Qoption ld '
-    ;;
-
-  sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
-    pic_flag='-KPIC'
-    link_static_flag='-Bstatic'
-    wl='-Wl,'
-    ;;
-
-  uts4*)
-    pic_flag='-pic'
-    link_static_flag='-Bstatic'
-    ;;
-  sysv4*MP*)
-    if test -d /usr/nec ;then
-      pic_flag='-Kconform_pic'
-      link_static_flag='-Bstatic'
-    fi
-    ;;
-  *)
-    can_build_shared=no
-    ;;
-  esac
-fi
-
-if test -n "$pic_flag"; then
-  echo "$ac_t$pic_flag" 1>&6
-
-  # Check to make sure the pic_flag actually works.
-  echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
-  $rm conftest*
-  echo "int some_variable = 0;" > conftest.c
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS $pic_flag -DPIC"
-  echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5
-  if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
-    # Append any warnings to the config.log.
-    cat conftest.err 1>&5
-    
-    case "$host_os" in
-    hpux9* | hpux10* | hpux11*)
-      # On HP-UX, both CC and GCC only warn that PIC is supported... then they
-      # create non-PIC objects.  So, if there were any warnings, we assume that
-      # PIC is not supported.
-      if test -s conftest.err; then
-       echo "$ac_t"no 1>&6
-       can_build_shared=no
-       pic_flag=
-      else
-       echo "$ac_t"yes 1>&6
-       pic_flag=" $pic_flag"
-      fi
-      ;;
-    *)
-      echo "$ac_t"yes 1>&6
-      pic_flag=" $pic_flag"
-      ;;
-    esac
-  else
-    # Append any errors to the config.log.
-    cat conftest.err 1>&5
-    can_build_shared=no
-    pic_flag=
-    echo "$ac_t"no 1>&6
-  fi
-  CFLAGS="$save_CFLAGS"
-  $rm conftest*
-else
-  echo "$ac_t"none 1>&6
-fi
-
-# Check to see if options -o and -c are simultaneously supported by compiler
-echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6
-$rm -r conftest 2>/dev/null
-mkdir conftest
-cd conftest
-$rm conftest*
-echo "int some_variable = 0;" > conftest.c
-mkdir out
-# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
-# that will create temporary files in the current directory regardless of
-# the output directory.  Thus, making CWD read-only will cause this test
-# to fail, enabling locking or at least warning the user not to do parallel
-# builds.
-chmod -w .
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -o out/conftest2.o"
-echo "$progname:829: checking if $compiler supports -c -o file.o" >&5
-if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then
-
-  # The compiler can only warn and ignore the option if not recognized
-  # So say no if there are warnings
-    if test -s out/conftest.err; then
-      echo "$ac_t"no 1>&6
-      compiler_c_o=no
-    else
-      echo "$ac_t"yes 1>&6
-      compiler_c_o=yes
-    fi
-else
-  # Append any errors to the config.log.
-  cat out/conftest.err 1>&5
-  compiler_c_o=no
-  echo "$ac_t"no 1>&6
-fi
-CFLAGS="$save_CFLAGS"
-chmod u+w .
-$rm conftest* out/*
-rmdir out
-cd ..
-rmdir conftest
-$rm -r conftest 2>/dev/null
-
-if test x"$compiler_c_o" = x"yes"; then
-  # Check to see if we can write to a .lo
-  echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6
-  $rm conftest*
-  echo "int some_variable = 0;" > conftest.c
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -c -o conftest.lo"
-  echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5
-if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then
-
-    # The compiler can only warn and ignore the option if not recognized
-    # So say no if there are warnings
-      if test -s conftest.err; then
-       echo "$ac_t"no 1>&6
-       compiler_o_lo=no
-      else
-       echo "$ac_t"yes 1>&6
-       compiler_o_lo=yes
-      fi
-  else
-    # Append any errors to the config.log.
-    cat conftest.err 1>&5
-    compiler_o_lo=no
-    echo "$ac_t"no 1>&6
-  fi
-  CFLAGS="$save_CFLAGS"
-  $rm conftest*
-else
-  compiler_o_lo=no
-fi
-
-# Check to see if we can do hard links to lock some files if needed
-hard_links="nottested"
-if test "$compiler_c_o" = no && test "$need_locks" != no; then
-  # do not overwrite the value of need_locks provided by the user
-  echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6
-  hard_links=yes
-  $rm conftest*
-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  touch conftest.a
-  ln conftest.a conftest.b 2>&5 || hard_links=no
-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  echo "$ac_t$hard_links" 1>&6
-  $rm conftest*
-  if test "$hard_links" = no; then
-    echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2
-    need_locks=warn
-  fi
-else
-  need_locks=no
-fi
-
-if test "$with_gcc" = yes; then
-  # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
-  echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6
-  $rm conftest*
-  echo "int some_variable = 0;" > conftest.c
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c"
-  echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
-  if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
-
-    # The compiler can only warn and ignore the option if not recognized
-    # So say no if there are warnings
-      if test -s conftest.err; then
-       echo "$ac_t"no 1>&6
-       compiler_rtti_exceptions=no
-      else
-       echo "$ac_t"yes 1>&6
-       compiler_rtti_exceptions=yes
-      fi
-  else
-    # Append any errors to the config.log.
-    cat conftest.err 1>&5
-    compiler_rtti_exceptions=no
-    echo "$ac_t"no 1>&6
-  fi
-  CFLAGS="$save_CFLAGS"
-  $rm conftest*
-
-  if test "$compiler_rtti_exceptions" = "yes"; then
-    no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
-  else
-    no_builtin_flag=' -fno-builtin'
-  fi
-  
-fi
-
-# Check for any special shared library compilation flags.
-if test -n "$special_shlib_compile_flags"; then
-  echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
-  if echo "$old_CC $old_CFLAGS " | egrep -e "[         ]$special_shlib_compile_flags[  ]" >/dev/null; then :
-  else
-    echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
-    can_build_shared=no
-  fi
-fi
-
-echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
-$rm conftest*
-echo 'main(){return(0);}' > conftest.c
-save_LDFLAGS="$LDFLAGS"
-LDFLAGS="$LDFLAGS $link_static_flag"
-echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5
-if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
-  echo "$ac_t$link_static_flag" 1>&6
-else
-  echo "$ac_t"none 1>&6
-  link_static_flag=
-fi
-LDFLAGS="$save_LDFLAGS"
-$rm conftest*
-
-if test -z "$LN_S"; then
-  # Check to see if we can use ln -s, or we need hard links.
-  echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
-  $rm conftest.dat
-  if ln -s X conftest.dat 2>/dev/null; then
-    $rm conftest.dat
-    LN_S="ln -s"
-  else
-    LN_S=ln
-  fi
-  if test "$LN_S" = "ln -s"; then
-    echo "$ac_t"yes 1>&6
-  else
-    echo "$ac_t"no 1>&6
-  fi
-fi
-
-# Make sure LD is an absolute path.
-if test -z "$LD"; then
-  ac_prog=ld
-  if test "$with_gcc" = yes; then
-    # Check if gcc -print-prog-name=ld gives a path.
-    echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
-    echo "$progname:991: checking for ld used by GCC" >&5
-    ac_prog=`($CC -print-prog-name=ld) 2>&5`
-    case "$ac_prog" in
-    # Accept absolute paths.
-    [\\/]* | [A-Za-z]:[\\/]*)
-      re_direlt='/[^/][^/]*/\.\./'
-      # Canonicalize the path of ld
-      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
-      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
-       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
-      done
-      test -z "$LD" && LD="$ac_prog"
-      ;;
-    "")
-      # If it fails, then pretend we are not using GCC.
-      ac_prog=ld
-      ;;
-    *)
-      # If it is relative, then search for the first ld in PATH.
-      with_gnu_ld=unknown
-      ;;
-    esac
-  elif test "$with_gnu_ld" = yes; then
-    echo $ac_n "checking for GNU ld... $ac_c" 1>&6
-    echo "$progname:1015: checking for GNU ld" >&5
-  else
-    echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
-    echo "$progname:1018: checking for non-GNU ld" >&5
-  fi
-
-  if test -z "$LD"; then
-    IFS="${IFS=        }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    for ac_dir in $PATH; do
-      test -z "$ac_dir" && ac_dir=.
-      if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
-       LD="$ac_dir/$ac_prog"
-       # Check to see if the program is GNU ld.  I'd rather use --version,
-       # but apparently some GNU ld's only accept -v.
-       # Break only if it was the GNU/non-GNU ld that we prefer.
-       if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
-         test "$with_gnu_ld" != no && break
-       else
-         test "$with_gnu_ld" != yes && break
-       fi
-      fi
-    done
-    IFS="$ac_save_ifs"
-  fi
-
-  if test -n "$LD"; then
-    echo "$ac_t$LD" 1>&6
-  else
-    echo "$ac_t"no 1>&6
-  fi
-
-  if test -z "$LD"; then
-    echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
-    exit 1
-  fi
-fi
-
-# Check to see if it really is or is not GNU ld.
-echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
-# I'd rather use --version here, but apparently some GNU ld's only accept -v.
-if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
-  with_gnu_ld=yes
-else
-  with_gnu_ld=no
-fi
-echo "$ac_t$with_gnu_ld" 1>&6
-
-# See if the linker supports building shared libraries.
-echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
-
-allow_undefined_flag=
-no_undefined_flag=
-need_lib_prefix=unknown
-need_version=unknown
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-archive_cmds=
-archive_expsym_cmds=
-old_archive_from_new_cmds=
-export_dynamic_flag_spec=
-whole_archive_flag_spec=
-thread_safe_flag_spec=
-hardcode_libdir_flag_spec=
-hardcode_libdir_separator=
-hardcode_direct=no
-hardcode_minus_L=no
-hardcode_shlibpath_var=unsupported
-runpath_var=
-always_export_symbols=no
-export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
-# include_expsyms should be a list of space-separated symbols to be *always*
-# included in the symbol list
-include_expsyms=
-# exclude_expsyms can be an egrep regular expression of symbols to exclude
-# it will be wrapped by ` (' and `)$', so one must not match beginning or
-# end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
-# as well as any symbol that contains `d'.
-exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
-# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
-# platforms (ab)use it in PIC code, but their linkers get confused if
-# the symbol is explicitly referenced.  Since portable code cannot
-# rely on this symbol name, it's probably fine to never include it in
-# preloaded symbol tables.
-
-case "$host_os" in
-cygwin* | mingw*)
-  # FIXME: the MSVC++ port hasn't been tested in a loooong time
-  # When not using gcc, we currently assume that we are using
-  # Microsoft Visual C++.
-  if test "$with_gcc" != yes; then
-    with_gnu_ld=no
-  fi
-  ;;
-
-esac
-
-ld_shlibs=yes
-if test "$with_gnu_ld" = yes; then
-  # If archive_cmds runs LD, not CC, wlarc should be empty
-  wlarc='${wl}'
-
-  # See if GNU ld supports shared libraries.
-  case "$host_os" in
-  aix3* | aix4*)
-    # On AIX, the GNU linker is very broken
-    ld_shlibs=no
-    cat <<EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support.  If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-EOF
-    ;;
-
-  amigaos*)
-    archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-
-    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
-    # that the semantics of dynamic libraries on AmigaOS, at least up
-    # to version 4, is to share data among multiple programs linked
-    # with the same dynamic library.  Since this doesn't match the
-    # behavior of shared libraries on other platforms, we can use
-    # them.
-    ld_shlibs=no
-    ;;
-
-  beos*)
-    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      allow_undefined_flag=unsupported
-      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
-      # support --undefined.  This deserves some investigation.  FIXME
-      archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-    else
-      ld_shlibs=no
-    fi
-    ;;
-
-  cygwin* | mingw*)
-    # hardcode_libdir_flag_spec is actually meaningless, as there is
-    # no search path for DLLs.
-    hardcode_libdir_flag_spec='-L$libdir'
-    allow_undefined_flag=unsupported
-    always_export_symbols=yes
-
-    # Extract the symbol export list from an `--export-all' def file,
-    # then regenerate the def file from the symbol export list, so that
-    # the compiled dll only exports the symbol export list.
-    export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
-      test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
-      $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def  $objdir/$soname-ltdll.$objext $libobjs $convenience~
-      sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]* ; *//" < $objdir/$soname-def > $export_symbols'
-
-    archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~
-      _lt_hint=1;
-      for symbol in `cat $export_symbols`; do
-       echo "  \$symbol @ \$_lt_hint ; " >> $objdir/$soname-def;
-       _lt_hint=`expr 1 + \$_lt_hint`;
-      done~
-      test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
-      test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
-      $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
-      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
-      $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
-      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
-      $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts'
-
-      old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' 
-    ;;
-
-  netbsd*)
-    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    else
-      archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib'
-      # can we support soname and/or expsyms with a.out? -oliva
-    fi
-    ;;
-
-  solaris*)
-    if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
-      ld_shlibs=no
-      cat <<EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems.  Therefore, libtool
-*** is disabling shared libraries support.  We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer.  Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-EOF
-    elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    else
-      ld_shlibs=no
-    fi
-    ;;      
-
-  sunos4*)
-    archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts'
-    wlarc=
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  *)
-    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    else
-      ld_shlibs=no
-    fi
-    ;;
-  esac
-
-  if test "$ld_shlibs" = yes; then
-    runpath_var=LD_RUN_PATH
-    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
-    export_dynamic_flag_spec='${wl}--export-dynamic'
-    case $host_os in
-    cygwin* | mingw*)
-      # dlltool doesn't understand --whole-archive et. al.
-      whole_archive_flag_spec=
-      ;;
-    *)
-      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
-      ;;
-    esac
-  fi
-else
-  # PORTME fill in a description of your system's linker (not GNU ld)
-  case "$host_os" in
-  aix3*)
-    allow_undefined_flag=unsupported
-    always_export_symbols=yes
-    archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname'
-    # Note: this linker hardcodes the directories in LIBPATH if there
-    # are no directories specified by -L.
-    hardcode_minus_L=yes
-    if test "$with_gcc" = yes && test -z "$link_static_flag"; then
-      # Neither direct hardcoding nor static linking is supported with a
-      # broken collect2.
-      hardcode_direct=unsupported
-    fi
-    ;;
-
-  aix4*)
-    hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib'
-    hardcode_libdir_separator=':'
-    if test "$with_gcc" = yes; then
-      collect2name=`${CC} -print-prog-name=collect2`
-      if test -f "$collect2name" && \
-        strings "$collect2name" | grep resolve_lib_name >/dev/null
-      then
-       # We have reworked collect2
-       hardcode_direct=yes
-      else
-       # We have old collect2
-       hardcode_direct=unsupported
-       # It fails to find uninstalled libraries when the uninstalled
-       # path is not listed in the libpath.  Setting hardcode_minus_L
-       # to unsupported forces relinking
-       hardcode_minus_L=yes
-       hardcode_libdir_flag_spec='-L$libdir'
-       hardcode_libdir_separator=
-      fi
-      shared_flag='-shared'
-    else
-      shared_flag='${wl}-bM:SRE'
-      hardcode_direct=yes
-    fi
-    allow_undefined_flag=' ${wl}-berok'
-    archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
-    archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
-    case "$host_os" in aix4.[01]|aix4.[01].*)
-      # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
-      always_export_symbols=yes ;;
-    esac
-   ;;
-
-  amigaos*)
-    archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-    # see comment about different semantics on the GNU ld section
-    ld_shlibs=no
-    ;;
-
-  cygwin* | mingw*)
-    # When not using gcc, we currently assume that we are using
-    # Microsoft Visual C++.
-    # hardcode_libdir_flag_spec is actually meaningless, as there is
-    # no search path for DLLs.
-    hardcode_libdir_flag_spec=' '
-    allow_undefined_flag=unsupported
-    # Tell ltmain to make .lib files, not .a files.
-    libext=lib
-    # FIXME: Setting linknames here is a bad hack.
-    archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
-    # The linker will automatically build a .lib file if we build a DLL.
-    old_archive_from_new_cmds='true'
-    # FIXME: Should let the user specify the lib program.
-    old_archive_cmds='lib /OUT:$oldlib$oldobjs'
-    fix_srcfile_path='`cygpath -w $srcfile`'
-    ;;
-
-  freebsd1*)
-    ld_shlibs=no
-    ;;
-
-  # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
-  # support.  Future versions do this automatically, but an explicit c++rt0.o
-  # does not break anything, and helps significantly (at the cost of a little
-  # extra space).
-  freebsd2.2*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  # Unfortunately, older versions of FreeBSD 2 do not have this feature.
-  freebsd2*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
-    hardcode_direct=yes
-    hardcode_minus_L=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-  freebsd*)
-    archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  hpux9* | hpux10* | hpux11*)
-    case "$host_os" in
-    hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;;
-    *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;;
-    esac
-    hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
-    hardcode_libdir_separator=:
-    hardcode_direct=yes
-    hardcode_minus_L=yes # Not in the search PATH, but as the default
-                        # location of the library.
-    export_dynamic_flag_spec='${wl}-E'
-    ;;
-
-  irix5* | irix6*)
-    if test "$with_gcc" = yes; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
-    else
-      archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
-    fi
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    hardcode_libdir_separator=:
-    ;;
-
-  netbsd*)
-    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
-      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'  # a.out
-    else
-      archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts'      # ELF
-    fi
-    hardcode_libdir_flag_spec='${wl}-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  openbsd*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  os2*)
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-    allow_undefined_flag=unsupported
-    archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def'
-    old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
-    ;;
-
-  osf3* | osf4*)
-    if test "$with_gcc" = yes; then
-      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
-      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
-    else
-      allow_undefined_flag=' -expect_unresolved \*'
-      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
-    fi
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    hardcode_libdir_separator=:
-    ;;
-
-  sco3.2v5*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_shlibpath_var=no
-    runpath_var=LD_RUN_PATH
-    hardcode_runpath_var=yes
-    ;;
-
-  solaris*)
-    no_undefined_flag=' -z text'
-    # $CC -shared without GNU ld will not create a library from C++
-    # object files and a static libstdc++, better avoid it by now
-    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
-    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
-               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_shlibpath_var=no
-    case "$host_os" in
-    solaris2.[0-5] | solaris2.[0-5].*) ;;
-    *) # Supported since Solaris 2.6 (maybe 2.5.1?)
-      whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
-    esac
-    ;;
-
-  sunos4*)
-    archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_direct=yes
-    hardcode_minus_L=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  sysv4)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    runpath_var='LD_RUN_PATH'
-    hardcode_shlibpath_var=no
-    hardcode_direct=no #Motorola manual says yes, but my tests say they lie 
-    ;;  
-
-  sysv4.3*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_shlibpath_var=no
-    export_dynamic_flag_spec='-Bexport'
-    ;;
-
-  uts4*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_shlibpath_var=no
-    ;;
-
-  dgux*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_shlibpath_var=no
-    ;;
-
-  sysv4*MP*)
-    if test -d /usr/nec ;then
-    # archive_cmds='$LD -G -z text -h $soname -o $lib$libobjs$deplibs'
-    archive_cmds='$LD -G -h $soname -o $lib$libobjs$deplibs'
-    hardcode_shlibpath_var=no
-    runpath_var=LD_RUN_PATH
-    hardcode_runpath_var=yes
-    ld_shlibs=yes
-    fi
-    ;;
-
-  *)
-    ld_shlibs=no
-    ;;
-  esac
-fi
-echo "$ac_t$ld_shlibs" 1>&6
-test "$ld_shlibs" = no && can_build_shared=no
-
-if test -z "$NM"; then
-  echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
-  case "$NM" in
-  [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path.
-  *)
-    IFS="${IFS=        }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do
-      test -z "$ac_dir" && ac_dir=.
-      if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then
-       # Check to see if the nm accepts a BSD-compat flag.
-       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
-       #   nm: unknown option "B" ignored
-       if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-         NM="$ac_dir/nm -B"
-         break
-       elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-         NM="$ac_dir/nm -p"
-         break
-       else
-         NM=${NM="$ac_dir/nm"} # keep the first match, but
-         continue # so that we can try to find one that supports BSD flags
-       fi
-      fi
-    done
-    IFS="$ac_save_ifs"
-    test -z "$NM" && NM=nm
-    ;;
-  esac
-  echo "$ac_t$NM" 1>&6
-fi
-
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
-
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[BCDEGRST]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
-
-# Transform the above into a raw symbol and a C symbol.
-symxfrm='\1 \2\3 \3'
-
-# Transform an extracted symbol line into a proper C declaration
-global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
-
-# Define system-specific variables.
-case "$host_os" in
-aix*)
-  symcode='[BCDT]'
-  ;;
-cygwin* | mingw*)
-  symcode='[ABCDGISTW]'
-  ;;
-hpux*) # Its linker distinguishes data from code symbols
-  global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
-  ;;
-irix*)
-  symcode='[BCDEGRST]'
-  ;;
-solaris*)
-  symcode='[BDT]'
-  ;;
-sysv4)
-  symcode='[DFNSTU]'
-  ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
-  symcode='[ABCDGISTW]'
-fi
-
-# Try without a prefix undercore, then with it.
-for ac_symprfx in "" "_"; do
-
-  # Write the raw and C identifiers.
-  global_symbol_pipe="sed -n -e 's/^.*[        ]\($symcode\)[  ][      ]*\($ac_symprfx\)$sympat$/$symxfrm/p'"
-
-  # Check to see that the pipe works correctly.
-  pipe_works=no
-  $rm conftest*
-  cat > conftest.c <<EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(){}
-#ifdef __cplusplus
-}
-#endif
-main(){nm_test_var='a';nm_test_func();return(0);}
-EOF
-
-  echo "$progname:1592: checking if global_symbol_pipe works" >&5
-  if { (eval echo $progname:1593: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then
-    # Now try to grab the symbols.
-    nlist=conftest.nm
-    if { echo "$progname:1596: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
-
-      # Try sorting and uniquifying the output.
-      if sort "$nlist" | uniq > "$nlist"T; then
-       mv -f "$nlist"T "$nlist"
-      else
-       rm -f "$nlist"T
-      fi
-
-      # Make sure that we snagged all the symbols we need.
-      if egrep ' nm_test_var$' "$nlist" >/dev/null; then
-       if egrep ' nm_test_func$' "$nlist" >/dev/null; then
-         cat <<EOF > conftest.c
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-EOF
-         # Now generate the symbol file.
-         eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c'
-
-         cat <<EOF >> conftest.c
-#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
-#else
-# define lt_ptr_t char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
-  const char *name;
-  lt_ptr_t address;
-}
-lt_preloaded_symbols[] =
-{
-EOF
-         sed 's/^. \(.*\) \(.*\)$/  {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c
-         cat <<\EOF >> conftest.c
-  {0, (lt_ptr_t) 0}
-};
-
-#ifdef __cplusplus
-}
-#endif
-EOF
-         # Now try linking the two files.
-         mv conftest.$objext conftstm.$objext
-         save_LIBS="$LIBS"
-         save_CFLAGS="$CFLAGS"
-         LIBS="conftstm.$objext"
-         CFLAGS="$CFLAGS$no_builtin_flag"
-         if { (eval echo $progname:1648: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
-           pipe_works=yes
-         else
-           echo "$progname: failed program was:" >&5
-           cat conftest.c >&5
-         fi
-         LIBS="$save_LIBS"
-       else
-         echo "cannot find nm_test_func in $nlist" >&5
-       fi
-      else
-       echo "cannot find nm_test_var in $nlist" >&5
-      fi
-    else
-      echo "cannot run $global_symbol_pipe" >&5
-    fi
-  else
-    echo "$progname: failed program was:" >&5
-    cat conftest.c >&5
-  fi
-  $rm conftest* conftst*
-
-  # Do not use the global_symbol_pipe unless it works.
-  if test "$pipe_works" = yes; then
-    break
-  else
-    global_symbol_pipe=
-  fi
-done
-if test "$pipe_works" = yes; then
-  echo "${ac_t}ok" 1>&6
-else
-  echo "${ac_t}failed" 1>&6
-fi
-
-if test -z "$global_symbol_pipe"; then
-  global_symbol_to_cdecl=
-fi
-
-# Check hardcoding attributes.
-echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
-hardcode_action=
-if test -n "$hardcode_libdir_flag_spec" || \
-   test -n "$runpath_var"; then
-
-  # We can hardcode non-existant directories.
-  if test "$hardcode_direct" != no &&
-     # If the only mechanism to avoid hardcoding is shlibpath_var, we
-     # have to relink, otherwise we might link with an installed library
-     # when we should be linking with a yet-to-be-installed one
-     ## test "$hardcode_shlibpath_var" != no &&
-     test "$hardcode_minus_L" != no; then
-    # Linking always hardcodes the temporary library directory.
-    hardcode_action=relink
-  else
-    # We can link without hardcoding, and we can hardcode nonexisting dirs.
-    hardcode_action=immediate
-  fi
-else
-  # We cannot hardcode anything, or else we can only hardcode existing
-  # directories.
-  hardcode_action=unsupported
-fi
-echo "$ac_t$hardcode_action" 1>&6
-
-
-reload_flag=
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
-# PORTME Some linkers may need a different reload flag.
-reload_flag='-r'
-echo "$ac_t$reload_flag" 1>&6
-test -n "$reload_flag" && reload_flag=" $reload_flag"
-
-# PORTME Fill in your ld.so characteristics
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-file_magic_cmd=
-file_magic_test_file=
-deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [regex]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given egrep regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
-case "$host_os" in
-aix3*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix $libname.a'
-  shlibpath_var=LIBPATH
-
-  # AIX has no versioning support, so we append a major version to the name.
-  soname_spec='${libname}${release}.so$major'
-  ;;
-
-aix4*)
-  version_type=linux
-  # AIX has no versioning support, so currently we can not hardcode correct
-  # soname into executable. Probably we can add versioning support to
-  # collect2, so additional links can be useful in future.
-  # We preserve .a as extension for shared libraries though AIX4.2
-  # and later linker supports .so
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a'
-  shlibpath_var=LIBPATH
-  deplibs_check_method=pass_all
-  ;;
-
-amigaos*)
-  library_names_spec='$libname.ixlibrary $libname.a'
-  # Create ${libname}_ixlibrary.a entries in /sys/libs.
-  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
-  ;;
-
-beos*)
-  library_names_spec='${libname}.so'
-  dynamic_linker="$host_os ld.so"
-  shlibpath_var=LIBRARY_PATH
-  deplibs_check_method=pass_all
-  lt_cv_dlopen="load_add_on"
-  lt_cv_dlopen_libs=
-  lt_cv_dlopen_self=yes
-  ;;
-
-bsdi4*)
-  version_type=linux
-  library_names_spec='${libname}.so$major ${libname}.so'
-  soname_spec='${libname}.so'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=/shlib/libc.so
-  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
-  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
-  # the default ld.so.conf also contains /usr/contrib/lib and
-  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
-  # libtool to hard-code these into programs
-  ;;
-
-cygwin* | mingw*)
-  version_type=windows
-  need_version=no
-  need_lib_prefix=no
-  if test "$with_gcc" = yes; then
-    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a'
-  else
-    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
-  fi
-  dynamic_linker='Win32 ld.exe'
-  deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
-  file_magic_cmd='${OBJDUMP} -f'
-  # FIXME: first we should search . and the directory the executable is in
-  shlibpath_var=PATH
-  lt_cv_dlopen="LoadLibrary"
-  lt_cv_dlopen_libs=
-  ;;
-
-freebsd1*)
-  dynamic_linker=no
-  ;;
-  
-freebsd*)
-  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
-  version_type=freebsd-$objformat
-  case "$version_type" in
-    freebsd-elf*)
-      deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
-      file_magic_cmd=/usr/bin/file
-      file_magic_test_file=`echo /usr/lib/libc.so*`
-      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
-      need_version=no
-      need_lib_prefix=no
-      ;;
-    freebsd-*)
-      deplibs_check_method=unknown
-      library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
-      need_version=yes
-      ;;
-  esac
-  finish_cmds='PATH="\$PATH:/sbin" OBJFORMAT="'"$objformat"'" ldconfig -m $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  case "$host_os" in
-  freebsd2* | freebsd3.[01]*)
-    shlibpath_overrides_runpath=yes
-    ;;
-  *) # from 3.2 on
-    shlibpath_overrides_runpath=no
-    ;;
-  esac
-  ;;
-
-gnu*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-hpux9* | hpux10* | hpux11*)
-  # Give a soname corresponding to the major version so that dld.sl refuses to
-  # link against other versions.
-  dynamic_linker="$host_os dld.sl"
-  version_type=sunos
-  need_lib_prefix=no
-  need_version=no
-  shlibpath_var=SHLIB_PATH
-  shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
-  library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
-  soname_spec='${libname}${release}.sl$major'
-  # HP-UX runs *really* slowly unless shared libraries are mode 555.
-  postinstall_cmds='chmod 555 $lib'
-  ;;
-
-irix5* | irix6*)
-  version_type=irix
-  need_lib_prefix=no
-  need_version=no
-  soname_spec='${libname}${release}.so.$major'
-  library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so'
-  case "$host_os" in
-  irix5*)
-    libsuff= shlibsuff=
-    # this will be overridden with pass_all, but let us keep it just in case
-    deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
-    ;;
-  *)
-    case "$LD" in # libtool.m4 will add one of these switches to LD
-    *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
-    *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
-    *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
-    *) libsuff= shlibsuff= libmagic=never-match;;
-    esac
-    # this will be overridden with pass_all, but let us keep it just in case
-    deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1"
-    ;;
-  esac
-  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
-  shlibpath_overrides_runpath=no
-  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
-  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=`echo /lib${libsuff}/libc.so*`
-  deplibs_check_method='pass_all'
-  ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
-  dynamic_linker=no
-  ;;
-
-# This must be Linux ELF.
-linux-gnu*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
-
-  if test -f /lib/ld.so.1; then
-    dynamic_linker='GNU ld.so'
-  else
-    # Only the GNU ld.so supports shared libraries on MkLinux.
-    case "$host_cpu" in
-    powerpc*) dynamic_linker=no ;;
-    *) dynamic_linker='Linux ld.so' ;;
-    esac
-  fi
-  ;;
-
-netbsd*)
-  version_type=sunos
-  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
-    library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
-    dynamic_linker='NetBSD (a.out) ld.so'
-  else
-    library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
-    soname_spec='${libname}${release}.so$major'
-    dynamic_linker='NetBSD ld.elf_so'
-  fi
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-openbsd*)
-  version_type=sunos
-  if test "$with_gnu_ld" = yes; then
-    need_lib_prefix=no
-    need_version=no
-  fi
-  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-os2*)
-  libname_spec='$name'
-  need_lib_prefix=no
-  library_names_spec='$libname.dll $libname.a'
-  dynamic_linker='OS/2 ld.exe'
-  shlibpath_var=LIBPATH
-  ;;
-
-osf3* | osf4*)
-  version_type=osf
-  need_version=no
-  soname_spec='${libname}${release}.so'
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
-  shlibpath_var=LD_LIBRARY_PATH
-  # this will be overridden with pass_all, but let us keep it just in case
-  deplibs_check_method='file_magic COFF format alpha shared library'
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=/shlib/libc.so
-  deplibs_check_method='pass_all'
-  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
-  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
-  ;;
-
-sco3.2v5*)
-  version_type=osf
-  soname_spec='${libname}${release}.so$major'
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-solaris*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  # ldd complains unless libraries are executable
-  postinstall_cmds='chmod +x $lib'
-  deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib"
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=/lib/libc.so
-  ;;
-
-sunos4*)
-  version_type=sunos
-  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  if test "$with_gnu_ld" = yes; then
-    need_lib_prefix=no
-  fi
-  need_version=yes
-  ;;
-
-sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  case "$host_vendor" in
-    ncr)
-      deplibs_check_method='pass_all'
-      ;;
-    motorola)
-      need_lib_prefix=no
-      need_version=no
-      shlibpath_overrides_runpath=no
-      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
-      deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
-      file_magic_cmd=/usr/bin/file
-      file_magic_test_file=`echo /usr/lib/libc.so*`
-      ;;
-  esac
-  ;;
-
-uts4*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-dgux*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-sysv4*MP*)
-  if test -d /usr/nec ;then
-    version_type=linux
-    library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
-    soname_spec='$libname.so.$major'
-    shlibpath_var=LD_LIBRARY_PATH
-  fi
-  ;;
-
-*)
-  dynamic_linker=no
-  ;;
-esac
-echo "$ac_t$dynamic_linker" 1>&6
-test "$dynamic_linker" = no && can_build_shared=no
-
-# Report the final consequences.
-echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
-
-# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in
-# configure.in, otherwise build static only libraries.
-case "$host_os" in
-cygwin* | mingw* | os2*)
-  if test x$can_build_shared = xyes; then
-    test x$enable_win32_dll = xno && can_build_shared=no
-    echo "checking if package supports dlls... $can_build_shared" 1>&6
-  fi
-;;
-esac
-
-if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then
-  case "$deplibs_check_method" in
-  "file_magic "*)
-    file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
-    if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
-       egrep "$file_magic_regex" > /dev/null; then
-      :
-    else
-      cat <<EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such.  This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem.  Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-EOF
-    fi ;;
-  esac
-fi
-
-echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
-test "$can_build_shared" = "no" && enable_shared=no
-
-# On AIX, shared libraries and static libraries use the same namespace, and
-# are all built from PIC.
-case "$host_os" in
-aix3*)
-  test "$enable_shared" = yes && enable_static=no
-  if test -n "$RANLIB"; then
-    archive_cmds="$archive_cmds~\$RANLIB \$lib"
-    postinstall_cmds='$RANLIB $lib'
-  fi
-  ;;
-
-aix4*)
-  test "$enable_shared" = yes && enable_static=no
-  ;;
-esac
-
-echo "$ac_t$enable_shared" 1>&6
-
-# Make sure either enable_shared or enable_static is yes.
-test "$enable_shared" = yes || enable_static=yes
-
-echo "checking whether to build static libraries... $enable_static" 1>&6
-
-if test "$hardcode_action" = relink; then
-  # Fast installation is not supported
-  enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
-     test "$enable_shared" = no; then
-  # Fast installation is not necessary
-  enable_fast_install=needless
-fi
-
-echo $ac_n "checking for objdir... $ac_c" 1>&6
-rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
-  objdir=.libs
-else
-  # MS-DOS does not allow filenames that begin with a dot.
-  objdir=_libs
-fi
-rmdir .libs 2>/dev/null
-echo "$ac_t$objdir" 1>&6
-
-if test "x$enable_dlopen" != xyes; then
-  enable_dlopen=unknown
-  enable_dlopen_self=unknown
-  enable_dlopen_self_static=unknown
-else
-if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then
-  lt_cv_dlopen=no lt_cv_dlopen_libs=
-echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "$progname:2170: checking for dlopen in -ldl" >&5
-ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_save_LIBS="$LIBS"
-LIBS="-ldl  $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2178 "ltconfig"
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-char dlopen();
-
-int main() {
-dlopen()
-; return 0; }
-EOF
-if { (eval echo $progname:2188: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for dlopen""... $ac_c" 1>&6
-echo "$progname:2207: checking for dlopen" >&5
-if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  cat > conftest.$ac_ext <<EOF
-#line 2212 "ltconfig"
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char dlopen(); below.  */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-char dlopen();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined (__stub_dlopen) || defined (__stub___dlopen)
-choke me
-#else
-dlopen();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo $progname:2234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_func_dlopen=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_func_dlopen=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="dlopen"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
-echo "$progname:2251: checking for dld_link in -ldld" >&5
-ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_save_LIBS="$LIBS"
-LIBS="-ldld  $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2259 "ltconfig"
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-char dld_link();
-
-int main() {
-dld_link()
-; return 0; }
-EOF
-if { (eval echo $progname:2269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for shl_load""... $ac_c" 1>&6
-echo "$progname:2288: checking for shl_load" >&5
-if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  cat > conftest.$ac_ext <<EOF
-#line 2293 "ltconfig"
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char shl_load(); below.  */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-char shl_load();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined (__stub_shl_load) || defined (__stub___shl_load)
-choke me
-#else
-shl_load();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo $progname:2315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_func_shl_load=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_func_shl_load=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="shl_load"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
-echo "$progname:2333: checking for shl_load in -ldld" >&5
-ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_save_LIBS="$LIBS"
-LIBS="-ldld  $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2341 "ltconfig"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-char shl_load();
-
-int main() {
-shl_load()
-; return 0; }
-EOF
-if { (eval echo $progname:2352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
-else
-  echo "$ac_t""no" 1>&6
-fi
-
-
-fi
-
-    
-fi
-
-  
-fi
-
-
-fi
-
-fi
-
-  if test "x$lt_cv_dlopen" != xno; then
-    enable_dlopen=yes
-  fi
-
-  case "$lt_cv_dlopen" in
-  dlopen)
-for ac_hdr in dlfcn.h; do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "$progname:2395: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  cat > conftest.$ac_ext <<EOF
-#line 2400 "ltconfig"
-#include <$ac_hdr>
-int fnord = 0;
-EOF
-ac_try="$ac_compile conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo $progname:2405: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
-  rm -rf conftest*
-  eval "ac_cv_header_$ac_safe=yes"
-else
-  echo "$ac_err" >&5
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-else
-  echo "$ac_t""no" 1>&6
-fi
-done
-
-    if test "x$ac_cv_header_dlfcn_h" = xyes; then
-      CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
-    fi
-    eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
-    LIBS="$lt_cv_dlopen_libs $LIBS"
-
-  echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
-echo "$progname:2433: checking whether a program can dlopen itself" >&5
-if test "${lt_cv_dlopen_self+set}" = set; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  if test "$cross_compiling" = yes; then
-    lt_cv_dlopen_self=cross
-  else
-    cat > conftest.c <<EOF
-#line 2441 "ltconfig"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LTDL_GLOBAL   RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-#  define LTDL_GLOBAL  DL_GLOBAL
-# else
-#  define LTDL_GLOBAL  0
-# endif
-#endif
-
-/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
-   find out it does not work in some platform. */
-#ifndef LTDL_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-#  define LTDL_LAZY_OR_NOW     RTLD_LAZY
-# else
-#  ifdef DL_LAZY
-#   define LTDL_LAZY_OR_NOW    DL_LAZY
-#  else
-#   ifdef RTLD_NOW
-#    define LTDL_LAZY_OR_NOW   RTLD_NOW
-#   else
-#    ifdef DL_NOW
-#     define LTDL_LAZY_OR_NOW  DL_NOW
-#    else
-#     define LTDL_LAZY_OR_NOW  0
-#    endif
-#   endif
-#  endif
-# endif
-#endif
-
-fnord() { int i=42;}
-main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
-    if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
-              if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } 
-
-EOF
-if { (eval echo $progname:2487: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
-  lt_cv_dlopen_self=yes
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -fr conftest*
-  lt_cv_dlopen_self=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$lt_cv_dlopen_self" 1>&6
-
-  if test "$lt_cv_dlopen_self" = yes; then
-    LDFLAGS="$LDFLAGS $link_static_flag"
-  echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
-echo "$progname:2506: checking whether a statically linked program can dlopen itself" >&5
-if test "${lt_cv_dlopen_self_static+set}" = set; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  if test "$cross_compiling" = yes; then
-    lt_cv_dlopen_self_static=cross
-  else
-    cat > conftest.c <<EOF
-#line 2514 "ltconfig"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LTDL_GLOBAL   RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-#  define LTDL_GLOBAL  DL_GLOBAL
-# else
-#  define LTDL_GLOBAL  0
-# endif
-#endif
-
-/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
-   find out it does not work in some platform. */
-#ifndef LTDL_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-#  define LTDL_LAZY_OR_NOW     RTLD_LAZY
-# else
-#  ifdef DL_LAZY
-#   define LTDL_LAZY_OR_NOW    DL_LAZY
-#  else
-#   ifdef RTLD_NOW
-#    define LTDL_LAZY_OR_NOW   RTLD_NOW
-#   else
-#    ifdef DL_NOW
-#     define LTDL_LAZY_OR_NOW  DL_NOW
-#    else
-#     define LTDL_LAZY_OR_NOW  0
-#    endif
-#   endif
-#  endif
-# endif
-#endif
-
-fnord() { int i=42;}
-main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
-    if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
-    if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } 
-
-EOF
-if { (eval echo $progname:2560: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
-  lt_cv_dlopen_self_static=yes
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -fr conftest*
-  lt_cv_dlopen_self_static=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
-fi
-    ;;
-  esac
-
-  case "$lt_cv_dlopen_self" in
-  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
-  *) enable_dlopen_self=unknown ;;
-  esac
-
-  case "$lt_cv_dlopen_self_static" in
-  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
-  *) enable_dlopen_self_static=unknown ;;
-  esac
-fi
-
-# Copy echo and quote the copy, instead of the original, because it is
-# used later.
-ltecho="$echo"
-if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then
-   ltecho="$CONFIG_SHELL \$0 --fallback-echo"
-fi
-LTSHELL="$SHELL"
-
-LTCONFIG_VERSION="$VERSION"
-
-# Only quote variables if we're using ltmain.sh.
-case "$ltmain" in
-*.sh)
-  # Now quote all the things that may contain metacharacters.
-  for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \
-    old_LD old_LDFLAGS old_LIBS \
-    old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \
-    AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \
-    reload_flag reload_cmds wl \
-    pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
-    thread_safe_flag_spec whole_archive_flag_spec libname_spec \
-    library_names_spec soname_spec \
-    RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
-    old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \
-    file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \
-    finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
-    hardcode_libdir_flag_spec hardcode_libdir_separator  \
-    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
-    compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
-
-    case "$var" in
-    reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
-    old_postinstall_cmds | old_postuninstall_cmds | \
-    export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
-    postinstall_cmds | postuninstall_cmds | \
-    finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
-      # Double-quote double-evaled strings.
-      eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
-      ;;
-    *)
-      eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
-      ;;
-    esac
-  done
-
-  case "$ltecho" in
-  *'\$0 --fallback-echo"')
-    ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
-    ;;
-  esac
-
-  trap "$rm \"$ofile\"; exit 1" 1 2 15
-  echo "creating $ofile"
-  $rm "$ofile"
-  cat <<EOF > "$ofile"
-#! $SHELL
-
-# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
-#
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="sed -e s/^X//"
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "\${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi
-
-### BEGIN LIBTOOL CONFIG
-EOF
-  cfgfile="$ofile"
-  ;;
-
-*)
-  # Double-quote the variables that need it (for aesthetics).
-  for var in old_CC old_CFLAGS old_CPPFLAGS \
-    old_LD old_LDFLAGS old_LIBS \
-    old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do
-    eval "$var=\\\"\$var\\\""
-  done
-
-  # Just create a config file.
-  cfgfile="$ofile.cfg"
-  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
-  echo "creating $cfgfile"
-  $rm "$cfgfile"
-  cat <<EOF > "$cfgfile"
-# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-EOF
-  ;;
-esac
-
-cat <<EOF >> "$cfgfile"
-# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\
-# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\
-# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\
-# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\
-#   $0$ltconfig_args
-#
-# Compiler and other test output produced by $progname, useful for
-# debugging $progname, is in ./config.log if it exists.
-
-# The version of $progname that generated this script.
-LTCONFIG_VERSION=$LTCONFIG_VERSION
-
-# Shell to use when invoking shell scripts.
-SHELL=$LTSHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-
-# An echo program that does not interpret backslashes.
-echo=$ltecho
-
-# The archiver.
-AR=$AR
-
-# The default C compiler.
-CC=$CC
-
-# The linker used to build libraries.
-LD=$LD
-
-# Whether we need hard or soft links.
-LN_S=$LN_S
-
-# A BSD-compatible nm program.
-NM=$NM
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$reload_flag
-reload_cmds=$reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$wl
-
-# Object file suffix (normally "o").
-objext="$objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$pic_flag
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$compiler_c_o
-
-# Can we write directly to a .lo ?
-compiler_o_lo=$compiler_o_lo
-
-# Must we lock files when doing compilation ?
-need_locks=$need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$link_static_flag
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$no_builtin_flag
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$export_dynamic_flag_spec
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$whole_archive_flag_spec
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$thread_safe_flag_spec
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$libname_spec
-
-# List of archive names.  First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$RANLIB
-old_archive_cmds=$old_archive_cmds
-old_postinstall_cmds=$old_postinstall_cmds
-old_postuninstall_cmds=$old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$old_archive_from_new_cmds
-
-# Commands used to build and install a shared archive.
-archive_cmds=$archive_cmds
-archive_expsym_cmds=$archive_expsym_cmds
-postinstall_cmds=$postinstall_cmds
-postuninstall_cmds=$postuninstall_cmds
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$allow_undefined_flag
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$no_undefined_flag
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$global_symbol_to_cdecl
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$hardcode_libdir_separator
-
-# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols
-
-# The commands to list exported symbols.
-export_symbols_cmds=$export_symbols_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$exclude_expsyms
-
-# Symbols that must always be exported.
-include_expsyms=$include_expsyms
-
-EOF
-
-case "$ltmain" in
-*.sh)
-  echo '### END LIBTOOL CONFIG' >> "$ofile"
-  echo >> "$ofile"
-  case "$host_os" in
-  aix3*)
-    cat <<\EOF >> "$ofile"
-
-# AIX sometimes has problems with the GCC collect2 program.  For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "${COLLECT_NAMES+set}" != set; then
-  COLLECT_NAMES=
-  export COLLECT_NAMES
-fi
-EOF
-    ;;
-  esac
-
-  # Append the ltmain.sh script.
-  sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1)
-
-  chmod +x "$ofile"
-  ;;
-
-*)
-  # Compile the libtool program.
-  echo "FIXME: would compile $ltmain"
-  ;;
-esac
-
-test -n "$cache_file" || exit 0
-
-# AC_CACHE_SAVE
-trap '' 1 2 15
-cat > confcache <<\EOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs.  It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
-#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already.  You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
-#
-EOF
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
-  case `(ac_space=' '; set | grep ac_space) 2>&1` in
-  *ac_space=\ *)
-    # `set' does not quote correctly, so add quotes (double-quote substitution
-    # turns \\\\ into \\, and sed turns \\ into \).
-    sed -n \
-      -e "s/'/'\\\\''/g" \
-      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
-    ;;
-  *)
-    # `set' quotes correctly as required by POSIX, so do not add quotes.
-    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
-    ;;
-  esac >> confcache
-if cmp -s $cache_file confcache; then
-  :
-else
-  if test -w $cache_file; then
-    echo "updating cache $cache_file"
-    cat confcache > $cache_file
-  else
-    echo "not updating unwritable cache $cache_file"
-  fi
-fi
-rm -f confcache
-
-exit 0
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
diff --git a/config/ltmain.sh b/config/ltmain.sh
deleted file mode 100644 (file)
index ae10cad..0000000
+++ /dev/null
@@ -1,3975 +0,0 @@
-# ltmain.sh - Provide generalized library-building support services.
-# NOTE: Changing this file will not affect anything until you rerun ltconfig.
-#
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Check that we have a working $echo.
-if test "X$1" = X--no-reexec; then
-  # Discard the --no-reexec flag, and continue.
-  shift
-elif test "X$1" = X--fallback-echo; then
-  # Avoid inline document here, it may be left over
-  :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
-  # Yippee, $echo works!
-  :
-else
-  # Restart under the correct shell, and then maybe $echo will work.
-  exec $SHELL "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
-  # used as fallback echo
-  shift
-  cat <<EOF
-$*
-EOF
-  exit 0
-fi
-
-# The name of this program.
-progname=`$echo "$0" | sed 's%^.*/%%'`
-modename="$progname"
-
-# Constants.
-PROGRAM=ltmain.sh
-PACKAGE=libtool
-VERSION=1.3.3
-TIMESTAMP=" (1.385.2.181 1999/07/02 15:49:11)"
-
-default_mode=
-help="Try \`$progname --help' for more information."
-magic="%%%MAGIC variable%%%"
-mkdir="mkdir"
-mv="mv -f"
-rm="rm -f"
-
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e 1s/^X//'
-sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
-SP2NL='tr \040 \012'
-NL2SP='tr \015\012 \040\040'
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-# We save the old values to restore during execute mode.
-if test "${LC_ALL+set}" = set; then
-  save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
-fi
-if test "${LANG+set}" = set; then
-  save_LANG="$LANG"; LANG=C; export LANG
-fi
-
-if test "$LTCONFIG_VERSION" != "$VERSION"; then
-  echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
-  echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-  exit 1
-fi
-
-if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
-  echo "$modename: not configured to build any kind of library" 1>&2
-  echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-  exit 1
-fi
-
-# Global variables.
-mode=$default_mode
-nonopt=
-prev=
-prevopt=
-run=
-show="$echo"
-show_help=
-execute_dlfiles=
-lo2o="s/\\.lo\$/.${objext}/"
-o2lo="s/\\.${objext}\$/.lo/"
-
-# Parse our command line options once, thoroughly.
-while test $# -gt 0
-do
-  arg="$1"
-  shift
-
-  case "$arg" in
-  -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
-  *) optarg= ;;
-  esac
-
-  # If the previous option needs an argument, assign it.
-  if test -n "$prev"; then
-    case "$prev" in
-    execute_dlfiles)
-      eval "$prev=\"\$$prev \$arg\""
-      ;;
-    *)
-      eval "$prev=\$arg"
-      ;;
-    esac
-
-    prev=
-    prevopt=
-    continue
-  fi
-
-  # Have we seen a non-optional argument yet?
-  case "$arg" in
-  --help)
-    show_help=yes
-    ;;
-
-  --version)
-    echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
-    exit 0
-    ;;
-
-  --config)
-    sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0
-    exit 0
-    ;;
-
-  --debug)
-    echo "$progname: enabling shell trace mode"
-    set -x
-    ;;
-
-  --dry-run | -n)
-    run=:
-    ;;
-
-  --features)
-    echo "host: $host"
-    if test "$build_libtool_libs" = yes; then
-      echo "enable shared libraries"
-    else
-      echo "disable shared libraries"
-    fi
-    if test "$build_old_libs" = yes; then
-      echo "enable static libraries"
-    else
-      echo "disable static libraries"
-    fi
-    exit 0
-    ;;
-
-  --finish) mode="finish" ;;
-
-  --mode) prevopt="--mode" prev=mode ;;
-  --mode=*) mode="$optarg" ;;
-
-  --quiet | --silent)
-    show=:
-    ;;
-
-  -dlopen)
-    prevopt="-dlopen"
-    prev=execute_dlfiles
-    ;;
-
-  -*)
-    $echo "$modename: unrecognized option \`$arg'" 1>&2
-    $echo "$help" 1>&2
-    exit 1
-    ;;
-
-  *)
-    nonopt="$arg"
-    break
-    ;;
-  esac
-done
-
-if test -n "$prevopt"; then
-  $echo "$modename: option \`$prevopt' requires an argument" 1>&2
-  $echo "$help" 1>&2
-  exit 1
-fi
-
-if test -z "$show_help"; then
-
-  # Infer the operation mode.
-  if test -z "$mode"; then
-    case "$nonopt" in
-    *cc | *++ | gcc* | *-gcc*)
-      mode=link
-      for arg
-      do
-       case "$arg" in
-       -c)
-          mode=compile
-          break
-          ;;
-       esac
-      done
-      ;;
-    *db | *dbx | *strace | *truss)
-      mode=execute
-      ;;
-    *install*|cp|mv)
-      mode=install
-      ;;
-    *rm)
-      mode=uninstall
-      ;;
-    *)
-      # If we have no mode, but dlfiles were specified, then do execute mode.
-      test -n "$execute_dlfiles" && mode=execute
-
-      # Just use the default operation mode.
-      if test -z "$mode"; then
-       if test -n "$nonopt"; then
-         $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
-       else
-         $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
-       fi
-      fi
-      ;;
-    esac
-  fi
-
-  # Only execute mode is allowed to have -dlopen flags.
-  if test -n "$execute_dlfiles" && test "$mode" != execute; then
-    $echo "$modename: unrecognized option \`-dlopen'" 1>&2
-    $echo "$help" 1>&2
-    exit 1
-  fi
-
-  # Change the help message to a mode-specific one.
-  generic_help="$help"
-  help="Try \`$modename --help --mode=$mode' for more information."
-
-  # These modes are in order of execution frequency so that they run quickly.
-  case "$mode" in
-  # libtool compile mode
-  compile)
-    modename="$modename: compile"
-    # Get the compilation command and the source file.
-    base_compile=
-    lastarg=
-    srcfile="$nonopt"
-    suppress_output=
-
-    user_target=no
-    for arg
-    do
-      # Accept any command-line options.
-      case "$arg" in
-      -o)
-       if test "$user_target" != "no"; then
-         $echo "$modename: you cannot specify \`-o' more than once" 1>&2
-         exit 1
-       fi
-       user_target=next
-       ;;
-
-      -static)
-       build_old_libs=yes
-       continue
-       ;;
-      esac
-
-      case "$user_target" in
-      next)
-       # The next one is the -o target name
-       user_target=yes
-       continue
-       ;;
-      yes)
-       # We got the output file
-       user_target=set
-       libobj="$arg"
-       continue
-       ;;
-      esac
-
-      # Accept the current argument as the source file.
-      lastarg="$srcfile"
-      srcfile="$arg"
-
-      # Aesthetically quote the previous argument.
-
-      # Backslashify any backslashes, double quotes, and dollar signs.
-      # These are the only characters that are still specially
-      # interpreted inside of double-quoted scrings.
-      lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
-
-      # Double-quote args containing other shell metacharacters.
-      # Many Bourne shells cannot handle close brackets correctly in scan
-      # sets, so we specify it separately.
-      case "$lastarg" in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*)
-       lastarg="\"$lastarg\""
-       ;;
-      esac
-
-      # Add the previous argument to base_compile.
-      if test -z "$base_compile"; then
-       base_compile="$lastarg"
-      else
-       base_compile="$base_compile $lastarg"
-      fi
-    done
-
-    case "$user_target" in
-    set)
-      ;;
-    no)
-      # Get the name of the library object.
-      libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
-      ;;
-    *)
-      $echo "$modename: you must specify a target with \`-o'" 1>&2
-      exit 1
-      ;;
-    esac
-
-    # Recognize several different file suffixes.
-    # If the user specifies -o file.o, it is replaced with file.lo
-    xform='[cCFSfmso]'
-    case "$libobj" in
-    *.ada) xform=ada ;;
-    *.adb) xform=adb ;;
-    *.ads) xform=ads ;;
-    *.asm) xform=asm ;;
-    *.c++) xform=c++ ;;
-    *.cc) xform=cc ;;
-    *.cpp) xform=cpp ;;
-    *.cxx) xform=cxx ;;
-    *.f90) xform=f90 ;;
-    *.for) xform=for ;;
-    esac
-
-    libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
-
-    case "$libobj" in
-    *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
-    *)
-      $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
-      exit 1
-      ;;
-    esac
-
-    if test -z "$base_compile"; then
-      $echo "$modename: you must specify a compilation command" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    # Delete any leftover library objects.
-    if test "$build_old_libs" = yes; then
-      removelist="$obj $libobj"
-    else
-      removelist="$libobj"
-    fi
-
-    $run $rm $removelist
-    trap "$run $rm $removelist; exit 1" 1 2 15
-
-    # Calculate the filename of the output object if compiler does
-    # not support -o with -c
-    if test "$compiler_c_o" = no; then
-      output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext}
-      lockfile="$output_obj.lock"
-      removelist="$removelist $output_obj $lockfile"
-      trap "$run $rm $removelist; exit 1" 1 2 15
-    else
-      need_locks=no
-      lockfile=
-    fi
-
-    # Lock this critical section if it is needed
-    # We use this script file to make the link, it avoids creating a new file
-    if test "$need_locks" = yes; then
-      until ln "$0" "$lockfile" 2>/dev/null; do
-       $show "Waiting for $lockfile to be removed"
-       sleep 2
-      done
-    elif test "$need_locks" = warn; then
-      if test -f "$lockfile"; then
-       echo "\
-*** ERROR, $lockfile exists and contains:
-`cat $lockfile 2>/dev/null`
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together.  If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
-       $run $rm $removelist
-       exit 1
-      fi
-      echo $srcfile > "$lockfile"
-    fi
-
-    if test -n "$fix_srcfile_path"; then
-      eval srcfile=\"$fix_srcfile_path\"
-    fi
-
-    # Only build a PIC object if we are building libtool libraries.
-    if test "$build_libtool_libs" = yes; then
-      # Without this assignment, base_compile gets emptied.
-      fbsd_hideous_sh_bug=$base_compile
-
-      # All platforms use -DPIC, to notify preprocessed assembler code.
-      command="$base_compile $pic_flag -DPIC $srcfile"
-      if test "$build_old_libs" = yes; then
-       lo_libobj="$libobj"
-       dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
-       if test "X$dir" = "X$libobj"; then
-         dir="$objdir"
-       else
-         dir="$dir/$objdir"
-       fi
-       libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
-
-       if test -d "$dir"; then
-         $show "$rm $libobj"
-         $run $rm $libobj
-       else
-         $show "$mkdir $dir"
-         $run $mkdir $dir
-         status=$?
-         if test $status -ne 0 && test ! -d $dir; then
-           exit $status
-         fi
-       fi
-      fi
-      if test "$compiler_o_lo" = yes; then
-       output_obj="$libobj"
-       command="$command -o $output_obj"
-      elif test "$compiler_c_o" = yes; then
-       output_obj="$obj"
-       command="$command -o $output_obj"
-      fi
-
-      $run $rm "$output_obj"
-      $show "$command"
-      if $run eval "$command"; then :
-      else
-       test -n "$output_obj" && $run $rm $removelist
-       exit 1
-      fi
-
-      if test "$need_locks" = warn &&
-        test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
-       echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together.  If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
-       $run $rm $removelist
-       exit 1
-      fi
-
-      # Just move the object if needed, then go on to compile the next one
-      if test x"$output_obj" != x"$libobj"; then
-       $show "$mv $output_obj $libobj"
-       if $run $mv $output_obj $libobj; then :
-       else
-         error=$?
-         $run $rm $removelist
-         exit $error
-       fi
-      fi
-
-      # If we have no pic_flag, then copy the object into place and finish.
-      if test -z "$pic_flag" && test "$build_old_libs" = yes; then
-       # Rename the .lo from within objdir to obj
-       if test -f $obj; then
-         $show $rm $obj
-         $run $rm $obj
-       fi
-
-       $show "$mv $libobj $obj"
-       if $run $mv $libobj $obj; then :
-       else
-         error=$?
-         $run $rm $removelist
-         exit $error
-       fi
-
-       # Now arrange that obj and lo_libobj become the same file
-       $show "$LN_S $obj $lo_libobj"
-       if $run $LN_S $obj $lo_libobj; then
-         exit 0
-       else
-         error=$?
-         $run $rm $removelist
-         exit $error
-       fi
-      fi
-
-      # Allow error messages only from the first compilation.
-      suppress_output=' >/dev/null 2>&1'
-    fi
-
-    # Only build a position-dependent object if we build old libraries.
-    if test "$build_old_libs" = yes; then
-      command="$base_compile $srcfile"
-      if test "$compiler_c_o" = yes; then
-       command="$command -o $obj"
-       output_obj="$obj"
-      fi
-
-      # Suppress compiler output if we already did a PIC compilation.
-      command="$command$suppress_output"
-      $run $rm "$output_obj"
-      $show "$command"
-      if $run eval "$command"; then :
-      else
-       $run $rm $removelist
-       exit 1
-      fi
-
-      if test "$need_locks" = warn &&
-        test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
-       echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together.  If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
-       $run $rm $removelist
-       exit 1
-      fi
-
-      # Just move the object if needed
-      if test x"$output_obj" != x"$obj"; then
-       $show "$mv $output_obj $obj"
-       if $run $mv $output_obj $obj; then :
-       else
-         error=$?
-         $run $rm $removelist
-         exit $error
-       fi
-      fi
-
-      # Create an invalid libtool object if no PIC, so that we do not
-      # accidentally link it into a program.
-      if test "$build_libtool_libs" != yes; then
-       $show "echo timestamp > $libobj"
-       $run eval "echo timestamp > \$libobj" || exit $?
-      else
-       # Move the .lo from within objdir
-       $show "$mv $libobj $lo_libobj"
-       if $run $mv $libobj $lo_libobj; then :
-       else
-         error=$?
-         $run $rm $removelist
-         exit $error
-       fi
-      fi
-    fi
-
-    # Unlock the critical section if it was locked
-    if test "$need_locks" != no; then
-      $rm "$lockfile"
-    fi
-
-    exit 0
-    ;;
-
-  # libtool link mode
-  link)
-    modename="$modename: link"
-    C_compiler="$CC" # save it, to compile generated C sources
-    CC="$nonopt"
-    case "$host" in
-    *-*-cygwin* | *-*-mingw* | *-*-os2*)
-      # It is impossible to link a dll without this setting, and
-      # we shouldn't force the makefile maintainer to figure out
-      # which system we are compiling for in order to pass an extra
-      # flag for every libtool invokation.
-      # allow_undefined=no
-
-      # FIXME: Unfortunately, there are problems with the above when trying
-      # to make a dll which has undefined symbols, in which case not
-      # even a static library is built.  For now, we need to specify
-      # -no-undefined on the libtool link line when we can be certain
-      # that all symbols are satisfied, otherwise we get a static library.
-      allow_undefined=yes
-
-      # This is a source program that is used to create dlls on Windows
-      # Don't remove nor modify the starting and closing comments
-# /* ltdll.c starts here */
-# #define WIN32_LEAN_AND_MEAN
-# #include <windows.h>
-# #undef WIN32_LEAN_AND_MEAN
-# #include <stdio.h>
-#
-# #ifndef __CYGWIN__
-# #  ifdef __CYGWIN32__
-# #    define __CYGWIN__ __CYGWIN32__
-# #  endif
-# #endif
-#
-# #ifdef __cplusplus
-# extern "C" {
-# #endif
-# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
-# #ifdef __cplusplus
-# }
-# #endif
-#
-# #ifdef __CYGWIN__
-# #include <cygwin/cygwin_dll.h>
-# DECLARE_CYGWIN_DLL( DllMain );
-# #endif
-# HINSTANCE __hDllInstance_base;
-#
-# BOOL APIENTRY
-# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
-# {
-#   __hDllInstance_base = hInst;
-#   return TRUE;
-# }
-# /* ltdll.c ends here */
-      # This is a source program that is used to create import libraries
-      # on Windows for dlls which lack them. Don't remove nor modify the
-      # starting and closing comments
-# /* impgen.c starts here */
-# /*   Copyright (C) 1999 Free Software Foundation, Inc.
-# 
-#  This file is part of GNU libtool.
-# 
-#  This program is free software; you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
-# 
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-# 
-#  You should have received a copy of the GNU General Public License
-#  along with this program; if not, write to the Free Software
-#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#  */
-# 
-#  #include <stdio.h>          /* for printf() */
-#  #include <unistd.h>         /* for open(), lseek(), read() */
-#  #include <fcntl.h>          /* for O_RDONLY, O_BINARY */
-#  #include <string.h>         /* for strdup() */
-# 
-#  static unsigned int
-#  pe_get16 (fd, offset)
-#       int fd;
-#       int offset;
-#  {
-#    unsigned char b[2];
-#    lseek (fd, offset, SEEK_SET);
-#    read (fd, b, 2);
-#    return b[0] + (b[1]<<8);
-#  }
-# 
-#  static unsigned int
-#  pe_get32 (fd, offset)
-#      int fd;
-#      int offset;
-#  {
-#    unsigned char b[4];
-#    lseek (fd, offset, SEEK_SET);
-#    read (fd, b, 4);
-#    return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
-#  }
-# 
-#  static unsigned int
-#  pe_as32 (ptr)
-#       void *ptr;
-#  {
-#    unsigned char *b = ptr;
-#    return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
-#  }
-# 
-#  int
-#  main (argc, argv)
-#      int argc;
-#      char *argv[];
-#  {
-#      int dll;
-#      unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
-#      unsigned long export_rva, export_size, nsections, secptr, expptr;
-#      unsigned long name_rvas, nexp;
-#      unsigned char *expdata, *erva;
-#      char *filename, *dll_name;
-# 
-#      filename = argv[1];
-# 
-#      dll = open(filename, O_RDONLY|O_BINARY);
-#      if (!dll)
-#      return 1;
-# 
-#      dll_name = filename;
-#    
-#      for (i=0; filename[i]; i++)
-#      if (filename[i] == '/' || filename[i] == '\\'  || filename[i] == ':')
-#          dll_name = filename + i +1;
-# 
-#      pe_header_offset = pe_get32 (dll, 0x3c);
-#      opthdr_ofs = pe_header_offset + 4 + 20;
-#      num_entries = pe_get32 (dll, opthdr_ofs + 92);
-# 
-#      if (num_entries < 1) /* no exports */
-#      return 1;
-# 
-#      export_rva = pe_get32 (dll, opthdr_ofs + 96);
-#      export_size = pe_get32 (dll, opthdr_ofs + 100);
-#      nsections = pe_get16 (dll, pe_header_offset + 4 +2);
-#      secptr = (pe_header_offset + 4 + 20 +
-#            pe_get16 (dll, pe_header_offset + 4 + 16));
-# 
-#      expptr = 0;
-#      for (i = 0; i < nsections; i++)
-#      {
-#      char sname[8];
-#      unsigned long secptr1 = secptr + 40 * i;
-#      unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
-#      unsigned long vsize = pe_get32 (dll, secptr1 + 16);
-#      unsigned long fptr = pe_get32 (dll, secptr1 + 20);
-#      lseek(dll, secptr1, SEEK_SET);
-#      read(dll, sname, 8);
-#      if (vaddr <= export_rva && vaddr+vsize > export_rva)
-#      {
-#          expptr = fptr + (export_rva - vaddr);
-#          if (export_rva + export_size > vaddr + vsize)
-#              export_size = vsize - (export_rva - vaddr);
-#          break;
-#      }
-#      }
-# 
-#      expdata = (unsigned char*)malloc(export_size);
-#      lseek (dll, expptr, SEEK_SET);
-#      read (dll, expdata, export_size);
-#      erva = expdata - export_rva;
-# 
-#      nexp = pe_as32 (expdata+24);
-#      name_rvas = pe_as32 (expdata+32);
-# 
-#      printf ("EXPORTS\n");
-#      for (i = 0; i<nexp; i++)
-#      {
-#      unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
-#      printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
-#      }
-# 
-#      return 0;
-#  }
-# /* impgen.c ends here */
-      ;;
-    *)
-      allow_undefined=yes
-      ;;
-    esac
-    compile_command="$CC"
-    finalize_command="$CC"
-
-    compile_rpath=
-    finalize_rpath=
-    compile_shlibpath=
-    finalize_shlibpath=
-    convenience=
-    old_convenience=
-    deplibs=
-    linkopts=
-
-    if test -n "$shlibpath_var"; then
-      # get the directories listed in $shlibpath_var
-      eval lib_search_path=\`\$echo \"X \${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
-    else
-      lib_search_path=
-    fi
-    # now prepend the system-specific ones
-    eval lib_search_path=\"$sys_lib_search_path_spec\$lib_search_path\"
-    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
-    
-    avoid_version=no
-    dlfiles=
-    dlprefiles=
-    dlself=no
-    export_dynamic=no
-    export_symbols=
-    export_symbols_regex=
-    generated=
-    libobjs=
-    link_against_libtool_libs=
-    ltlibs=
-    module=no
-    objs=
-    prefer_static_libs=no
-    preload=no
-    prev=
-    prevarg=
-    release=
-    rpath=
-    xrpath=
-    perm_rpath=
-    temp_rpath=
-    thread_safe=no
-    vinfo=
-
-    # We need to know -static, to get the right output filenames.
-    for arg
-    do
-      case "$arg" in
-      -all-static | -static)
-       if test "X$arg" = "X-all-static"; then
-         if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
-           $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
-         fi
-         if test -n "$link_static_flag"; then
-           dlopen_self=$dlopen_self_static
-         fi
-       else
-         if test -z "$pic_flag" && test -n "$link_static_flag"; then
-           dlopen_self=$dlopen_self_static
-         fi
-       fi
-       build_libtool_libs=no
-       build_old_libs=yes
-       prefer_static_libs=yes
-       break
-       ;;
-      esac
-    done
-
-    # See if our shared archives depend on static archives.
-    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
-
-    # Go through the arguments, transforming them on the way.
-    while test $# -gt 0; do
-      arg="$1"
-      shift
-
-      # If the previous option needs an argument, assign it.
-      if test -n "$prev"; then
-       case "$prev" in
-       output)
-         compile_command="$compile_command @OUTPUT@"
-         finalize_command="$finalize_command @OUTPUT@"
-         ;;
-       esac
-
-       case "$prev" in
-       dlfiles|dlprefiles)
-         if test "$preload" = no; then
-           # Add the symbol object into the linking commands.
-           compile_command="$compile_command @SYMFILE@"
-           finalize_command="$finalize_command @SYMFILE@"
-           preload=yes
-         fi
-         case "$arg" in
-         *.la | *.lo) ;;  # We handle these cases below.
-         force)
-           if test "$dlself" = no; then
-             dlself=needless
-             export_dynamic=yes
-           fi
-           prev=
-           continue
-           ;;
-         self)
-           if test "$prev" = dlprefiles; then
-             dlself=yes
-           elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
-             dlself=yes
-           else
-             dlself=needless
-             export_dynamic=yes
-           fi
-           prev=
-           continue
-           ;;
-         *)
-           if test "$prev" = dlfiles; then
-             dlfiles="$dlfiles $arg"
-           else
-             dlprefiles="$dlprefiles $arg"
-           fi
-           prev=
-           ;;
-         esac
-         ;;
-       expsyms)
-         export_symbols="$arg"
-         if test ! -f "$arg"; then
-           $echo "$modename: symbol file \`$arg' does not exist"
-           exit 1
-         fi
-         prev=
-         continue
-         ;;
-       expsyms_regex)
-         export_symbols_regex="$arg"
-         prev=
-         continue
-         ;;
-       release)
-         release="-$arg"
-         prev=
-         continue
-         ;;
-       rpath | xrpath)
-         # We need an absolute path.
-         case "$arg" in
-         [\\/]* | [A-Za-z]:[\\/]*) ;;
-         *)
-           $echo "$modename: only absolute run-paths are allowed" 1>&2
-           exit 1
-           ;;
-         esac
-         if test "$prev" = rpath; then
-           case "$rpath " in
-           *" $arg "*) ;;
-           *) rpath="$rpath $arg" ;;
-           esac
-         else
-           case "$xrpath " in
-           *" $arg "*) ;;
-           *) xrpath="$xrpath $arg" ;;
-           esac
-         fi
-         prev=
-         continue
-         ;;
-       *)
-         eval "$prev=\"\$arg\""
-         prev=
-         continue
-         ;;
-       esac
-      fi
-
-      prevarg="$arg"
-
-      case "$arg" in
-      -all-static)
-       if test -n "$link_static_flag"; then
-         compile_command="$compile_command $link_static_flag"
-         finalize_command="$finalize_command $link_static_flag"
-       fi
-       continue
-       ;;
-
-      -allow-undefined)
-       # FIXME: remove this flag sometime in the future.
-       $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
-       continue
-       ;;
-
-      -avoid-version)
-       avoid_version=yes
-       continue
-       ;;
-
-      -dlopen)
-       prev=dlfiles
-       continue
-       ;;
-
-      -dlpreopen)
-       prev=dlprefiles
-       continue
-       ;;
-
-      -export-dynamic)
-       export_dynamic=yes
-       continue
-       ;;
-
-      -export-symbols | -export-symbols-regex)
-       if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
-         $echo "$modename: not more than one -exported-symbols argument allowed"
-         exit 1
-       fi
-       if test "X$arg" = "X-export-symbols"; then
-         prev=expsyms
-       else
-         prev=expsyms_regex
-       fi
-       continue
-       ;;
-
-      -L*)
-       dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
-       # We need an absolute path.
-       case "$dir" in
-       [\\/]* | [A-Za-z]:[\\/]*) ;;
-       *)
-         absdir=`cd "$dir" && pwd`
-         if test -z "$absdir"; then
-           $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
-           $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
-           absdir="$dir"
-         fi
-         dir="$absdir"
-         ;;
-       esac
-       case " $deplibs " in
-       *" $arg "*) ;;
-       *) deplibs="$deplibs $arg";;
-       esac
-       case " $lib_search_path " in
-       *" $dir "*) ;;
-       *) lib_search_path="$lib_search_path $dir";;
-       esac
-       case "$host" in
-       *-*-cygwin* | *-*-mingw* | *-*-os2*)
-         dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
-         case ":$dllsearchpath:" in
-         ::) dllsearchpath="$dllsearchdir";;
-         *":$dllsearchdir:"*) ;;
-         *) dllsearchpath="$dllsearchpath:$dllsearchdir";;
-         esac
-         ;;
-       esac
-       ;;
-
-      -l*)
-       if test "$arg" = "-lc"; then
-         case "$host" in
-         *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
-           # These systems don't actually have c library (as such)
-           continue
-           ;;
-         esac
-       elif test "$arg" = "-lm"; then
-         case "$host" in
-         *-*-cygwin* | *-*-beos*)
-           # These systems don't actually have math library (as such)
-           continue
-           ;;
-         esac
-       fi
-       deplibs="$deplibs $arg"
-       ;;
-
-      -module)
-       module=yes
-       continue
-       ;;
-
-      -no-undefined)
-       allow_undefined=no
-       continue
-       ;;
-
-      -o) prev=output ;;
-
-      -release)
-       prev=release
-       continue
-       ;;
-
-      -rpath)
-       prev=rpath
-       continue
-       ;;
-
-      -R)
-       prev=xrpath
-       continue
-       ;;
-
-      -R*)
-       dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
-       # We need an absolute path.
-       case "$dir" in
-       [\\/]* | [A-Za-z]:[\\/]*) ;;
-       *)
-         $echo "$modename: only absolute run-paths are allowed" 1>&2
-         exit 1
-         ;;
-       esac
-       case "$xrpath " in
-       *" $dir "*) ;;
-       *) xrpath="$xrpath $dir" ;;
-       esac
-       continue
-       ;;
-
-      -static)
-       # If we have no pic_flag, then this is the same as -all-static.
-       if test -z "$pic_flag" && test -n "$link_static_flag"; then
-         compile_command="$compile_command $link_static_flag"
-         finalize_command="$finalize_command $link_static_flag"
-       fi
-       continue
-       ;;
-
-      -thread-safe)
-       thread_safe=yes
-       continue
-       ;;
-
-      -version-info)
-       prev=vinfo
-       continue
-       ;;
-
-      # Some other compiler flag.
-      -* | +*)
-       # Unknown arguments in both finalize_command and compile_command need
-       # to be aesthetically quoted because they are evaled later.
-       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-       case "$arg" in
-       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*)
-         arg="\"$arg\""
-         ;;
-       esac
-       ;;
-
-      *.o | *.obj | *.a | *.lib)
-       # A standard object.
-       objs="$objs $arg"
-       ;;
-
-      *.lo)
-       # A library object.
-       if test "$prev" = dlfiles; then
-         dlfiles="$dlfiles $arg"
-         if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then
-           prev=
-           continue
-         else
-           # If libtool objects are unsupported, then we need to preload.
-           prev=dlprefiles
-         fi
-       fi
-
-       if test "$prev" = dlprefiles; then
-         # Preload the old-style object.
-         dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
-         prev=
-       fi
-       libobjs="$libobjs $arg"
-       ;;
-
-      *.la)
-       # A libtool-controlled library.
-
-       dlname=
-       libdir=
-       library_names=
-       old_library=
-
-       # Check to see that this really is a libtool archive.
-       if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-       else
-         $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2
-         exit 1
-       fi
-
-       # If the library was installed with an old release of libtool,
-       # it will not redefine variable installed.
-       installed=yes
-
-       # Read the .la file
-       # If there is no directory component, then add one.
-       case "$arg" in
-       */* | *\\*) . $arg ;;
-       *) . ./$arg ;;
-       esac
-
-       # Get the name of the library we link against.
-       linklib=
-       for l in $old_library $library_names; do
-         linklib="$l"
-       done
-
-       if test -z "$linklib"; then
-         $echo "$modename: cannot find name of link library for \`$arg'" 1>&2
-         exit 1
-       fi
-
-       # Find the relevant object directory and library name.
-       name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
-
-       if test "X$installed" = Xyes; then
-         dir="$libdir"
-       else
-         dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
-         if test "X$dir" = "X$arg"; then
-           dir="$objdir"
-         else
-           dir="$dir/$objdir"
-         fi
-       fi
-
-       if test -n "$dependency_libs"; then
-         # Extract -R and -L from dependency_libs
-         temp_deplibs=
-         for deplib in $dependency_libs; do
-           case "$deplib" in
-           -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
-                case " $rpath $xrpath " in
-                *" $temp_xrpath "*) ;;
-                *) xrpath="$xrpath $temp_xrpath";;
-                esac;;
-           -L*) case "$compile_command $temp_deplibs " in
-                *" $deplib "*) ;;
-                *) temp_deplibs="$temp_deplibs $deplib";;
-                esac
-                temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'`
-                case " $lib_search_path " in
-                *" $temp_dir "*) ;;
-                *) lib_search_path="$lib_search_path $temp_dir";;
-                esac
-                ;;
-           *) temp_deplibs="$temp_deplibs $deplib";;
-           esac
-         done
-         dependency_libs="$temp_deplibs"
-       fi
-
-       if test -z "$libdir"; then
-         # It is a libtool convenience library, so add in its objects.
-         convenience="$convenience $dir/$old_library"
-         old_convenience="$old_convenience $dir/$old_library"
-         deplibs="$deplibs$dependency_libs"
-         compile_command="$compile_command $dir/$old_library$dependency_libs"
-         finalize_command="$finalize_command $dir/$old_library$dependency_libs"
-         continue
-       fi
-
-       # This library was specified with -dlopen.
-       if test "$prev" = dlfiles; then
-         dlfiles="$dlfiles $arg"
-         if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then
-           # If there is no dlname, no dlopen support or we're linking statically,
-           # we need to preload.
-           prev=dlprefiles
-         else
-           # We should not create a dependency on this library, but we
-           # may need any libraries it requires.
-           compile_command="$compile_command$dependency_libs"
-           finalize_command="$finalize_command$dependency_libs"
-           prev=
-           continue
-         fi
-       fi
-
-       # The library was specified with -dlpreopen.
-       if test "$prev" = dlprefiles; then
-         # Prefer using a static library (so that no silly _DYNAMIC symbols
-         # are required to link).
-         if test -n "$old_library"; then
-           dlprefiles="$dlprefiles $dir/$old_library"
-         else
-           dlprefiles="$dlprefiles $dir/$linklib"
-         fi
-         prev=
-       fi
-
-       if test -n "$library_names" &&
-          { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
-         link_against_libtool_libs="$link_against_libtool_libs $arg"
-         if test -n "$shlibpath_var"; then
-           # Make sure the rpath contains only unique directories.
-           case "$temp_rpath " in
-           *" $dir "*) ;;
-           *) temp_rpath="$temp_rpath $dir" ;;
-           esac
-         fi
-
-         # We need an absolute path.
-         case "$dir" in
-         [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;;
-         *)
-           absdir=`cd "$dir" && pwd`
-           if test -z "$absdir"; then
-             $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
-             $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
-             absdir="$dir"
-           fi
-           ;;
-         esac
-         
-         # This is the magic to use -rpath.
-         # Skip directories that are in the system default run-time
-         # search path, unless they have been requested with -R.
-         case " $sys_lib_dlsearch_path " in
-         *" $absdir "*) ;;
-         *)
-           case "$compile_rpath " in
-           *" $absdir "*) ;;
-           *) compile_rpath="$compile_rpath $absdir" 
-           esac
-           ;;
-         esac
-
-         case " $sys_lib_dlsearch_path " in
-         *" $libdir "*) ;;
-         *)
-           case "$finalize_rpath " in
-           *" $libdir "*) ;;
-           *) finalize_rpath="$finalize_rpath $libdir"
-           esac
-           ;;
-         esac
-
-         lib_linked=yes
-         case "$hardcode_action" in
-         immediate | unsupported)
-           if test "$hardcode_direct" = no; then
-             compile_command="$compile_command $dir/$linklib"
-             deplibs="$deplibs $dir/$linklib"
-             case "$host" in
-             *-*-cygwin* | *-*-mingw* | *-*-os2*)
-               dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
-               if test -n "$dllsearchpath"; then
-                 dllsearchpath="$dllsearchpath:$dllsearchdir"
-               else
-                 dllsearchpath="$dllsearchdir"
-               fi
-               ;;
-             esac
-           elif test "$hardcode_minus_L" = no; then
-             case "$host" in
-             *-*-sunos*)
-               compile_shlibpath="$compile_shlibpath$dir:"
-               ;;
-             esac
-             case "$compile_command " in
-             *" -L$dir "*) ;;
-             *) compile_command="$compile_command -L$dir";;
-             esac
-             compile_command="$compile_command -l$name"
-             deplibs="$deplibs -L$dir -l$name"
-           elif test "$hardcode_shlibpath_var" = no; then
-             case ":$compile_shlibpath:" in
-             *":$dir:"*) ;;
-             *) compile_shlibpath="$compile_shlibpath$dir:";;
-             esac
-             compile_command="$compile_command -l$name"
-             deplibs="$deplibs -l$name"
-           else
-             lib_linked=no
-           fi
-           ;;
-
-         relink)
-           if test "$hardcode_direct" = yes; then
-             compile_command="$compile_command $absdir/$linklib"
-             deplibs="$deplibs $absdir/$linklib"
-           elif test "$hardcode_minus_L" = yes; then
-             case "$compile_command " in
-             *" -L$absdir "*) ;;
-             *) compile_command="$compile_command -L$absdir";;
-             esac
-             compile_command="$compile_command -l$name"
-             deplibs="$deplibs -L$absdir -l$name"
-           elif test "$hardcode_shlibpath_var" = yes; then
-             case ":$compile_shlibpath:" in
-             *":$absdir:"*) ;;
-             *) compile_shlibpath="$compile_shlibpath$absdir:";;
-             esac
-             compile_command="$compile_command -l$name"
-             deplibs="$deplibs -l$name"
-           else
-             lib_linked=no
-           fi
-           ;;
-
-         *)
-           lib_linked=no
-           ;;
-         esac
-
-         if test "$lib_linked" != yes; then
-           $echo "$modename: configuration error: unsupported hardcode properties"
-           exit 1
-         fi
-
-         # Finalize command for both is simple: just hardcode it.
-         if test "$hardcode_direct" = yes; then
-           finalize_command="$finalize_command $libdir/$linklib"
-         elif test "$hardcode_minus_L" = yes; then
-           case "$finalize_command " in
-           *" -L$libdir "*) ;;
-           *) finalize_command="$finalize_command -L$libdir";;
-           esac
-           finalize_command="$finalize_command -l$name"
-         elif test "$hardcode_shlibpath_var" = yes; then
-           case ":$finalize_shlibpath:" in
-           *":$libdir:"*) ;;
-           *) finalize_shlibpath="$finalize_shlibpath$libdir:";;
-           esac
-           finalize_command="$finalize_command -l$name"
-         else
-           # We cannot seem to hardcode it, guess we'll fake it.
-           case "$finalize_command " in
-           *" -L$dir "*) ;;
-           *) finalize_command="$finalize_command -L$libdir";;
-           esac
-           finalize_command="$finalize_command -l$name"
-         fi
-       else
-         # Transform directly to old archives if we don't build new libraries.
-         if test -n "$pic_flag" && test -z "$old_library"; then
-           $echo "$modename: cannot find static library for \`$arg'" 1>&2
-           exit 1
-         fi
-
-         # Here we assume that one of hardcode_direct or hardcode_minus_L
-         # is not unsupported.  This is valid on all known static and
-         # shared platforms.
-         if test "$hardcode_direct" != unsupported; then
-           test -n "$old_library" && linklib="$old_library"
-           compile_command="$compile_command $dir/$linklib"
-           finalize_command="$finalize_command $dir/$linklib"
-         else
-           case "$compile_command " in
-           *" -L$dir "*) ;;
-           *) compile_command="$compile_command -L$dir";;
-           esac
-           compile_command="$compile_command -l$name"
-           case "$finalize_command " in
-           *" -L$dir "*) ;;
-           *) finalize_command="$finalize_command -L$dir";;
-           esac
-           finalize_command="$finalize_command -l$name"
-         fi
-       fi
-
-       # Add in any libraries that this one depends upon.
-       compile_command="$compile_command$dependency_libs"
-       finalize_command="$finalize_command$dependency_libs"
-       continue
-       ;;
-
-      # Some other compiler argument.
-      *)
-       # Unknown arguments in both finalize_command and compile_command need
-       # to be aesthetically quoted because they are evaled later.
-       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-       case "$arg" in
-       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \   ]*|*]*)
-         arg="\"$arg\""
-         ;;
-       esac
-       ;;
-      esac
-
-      # Now actually substitute the argument into the commands.
-      if test -n "$arg"; then
-       compile_command="$compile_command $arg"
-       finalize_command="$finalize_command $arg"
-      fi
-    done
-
-    if test -n "$prev"; then
-      $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
-      eval arg=\"$export_dynamic_flag_spec\"
-      compile_command="$compile_command $arg"
-      finalize_command="$finalize_command $arg"
-    fi
-
-    oldlibs=
-    # calculate the name of the file, without its directory
-    outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
-    libobjs_save="$libobjs"
-
-    case "$output" in
-    "")
-      $echo "$modename: you must specify an output file" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-      ;;
-
-    *.a | *.lib)
-      if test -n "$link_against_libtool_libs"; then
-       $echo "$modename: error: cannot link libtool libraries into archives" 1>&2
-       exit 1
-      fi
-
-      if test -n "$deplibs"; then
-       $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
-      fi
-
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-       $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$rpath"; then
-       $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$xrpath"; then
-       $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$vinfo"; then
-       $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$release"; then
-       $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
-       $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
-      fi
-
-      # Now set the variables for building old libraries.
-      build_libtool_libs=no
-      oldlibs="$output"
-      ;;
-
-    *.la)
-      # Make sure we only generate libraries of the form `libNAME.la'.
-      case "$outputname" in
-      lib*)
-       name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
-       eval libname=\"$libname_spec\"
-       ;;
-      *)
-       if test "$module" = no; then
-         $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
-         $echo "$help" 1>&2
-         exit 1
-       fi
-       if test "$need_lib_prefix" != no; then
-         # Add the "lib" prefix for modules if required
-         name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
-         eval libname=\"$libname_spec\"
-       else
-         libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
-       fi
-       ;;
-      esac
-
-      output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
-      if test "X$output_objdir" = "X$output"; then
-       output_objdir="$objdir"
-      else
-       output_objdir="$output_objdir/$objdir"
-      fi
-
-      if test -n "$objs"; then
-       $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
-       exit 1
-      fi
-
-      # How the heck are we supposed to write a wrapper for a shared library?
-      if test -n "$link_against_libtool_libs"; then
-        $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2
-        exit 1
-      fi
-
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-       $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2
-      fi
-
-      set dummy $rpath
-      if test $# -gt 2; then
-       $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
-      fi
-      install_libdir="$2"
-
-      oldlibs=
-      if test -z "$rpath"; then
-       if test "$build_libtool_libs" = yes; then
-         # Building a libtool convenience library.
-         libext=al
-         oldlibs="$output_objdir/$libname.$libext $oldlibs"
-         build_libtool_libs=convenience
-         build_old_libs=yes
-       fi
-       dependency_libs="$deplibs"
-
-       if test -n "$vinfo"; then
-         $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
-       fi
-
-       if test -n "$release"; then
-         $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
-       fi
-      else
-
-       # Parse the version information argument.
-       IFS="${IFS=     }"; save_ifs="$IFS"; IFS=':'
-       set dummy $vinfo 0 0 0
-       IFS="$save_ifs"
-
-       if test -n "$8"; then
-         $echo "$modename: too many parameters to \`-version-info'" 1>&2
-         $echo "$help" 1>&2
-         exit 1
-       fi
-
-       current="$2"
-       revision="$3"
-       age="$4"
-
-       # Check that each of the things are valid numbers.
-       case "$current" in
-       0 | [1-9] | [1-9][0-9]*) ;;
-       *)
-         $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
-         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-         exit 1
-         ;;
-       esac
-
-       case "$revision" in
-       0 | [1-9] | [1-9][0-9]*) ;;
-       *)
-         $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
-         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-         exit 1
-         ;;
-       esac
-
-       case "$age" in
-       0 | [1-9] | [1-9][0-9]*) ;;
-       *)
-         $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
-         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-         exit 1
-         ;;
-       esac
-
-       if test $age -gt $current; then
-         $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
-         $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-         exit 1
-       fi
-
-       # Calculate the version variables.
-       major=
-       versuffix=
-       verstring=
-       case "$version_type" in
-       none) ;;
-
-       irix)
-         major=`expr $current - $age + 1`
-         versuffix="$major.$revision"
-         verstring="sgi$major.$revision"
-
-         # Add in all the interfaces that we are compatible with.
-         loop=$revision
-         while test $loop != 0; do
-           iface=`expr $revision - $loop`
-           loop=`expr $loop - 1`
-           verstring="sgi$major.$iface:$verstring"
-         done
-         ;;
-
-       linux)
-         major=.`expr $current - $age`
-         versuffix="$major.$age.$revision"
-         ;;
-
-       osf)
-         major=`expr $current - $age`
-         versuffix=".$current.$age.$revision"
-         verstring="$current.$age.$revision"
-
-         # Add in all the interfaces that we are compatible with.
-         loop=$age
-         while test $loop != 0; do
-           iface=`expr $current - $loop`
-           loop=`expr $loop - 1`
-           verstring="$verstring:${iface}.0"
-         done
-
-         # Make executables depend on our current version.
-         verstring="$verstring:${current}.0"
-         ;;
-
-       sunos)
-         major=".$current"
-         versuffix=".$current.$revision"
-         ;;
-
-       freebsd-aout)
-         major=".$current"
-         versuffix=".$current.$revision";
-         ;;
-
-       freebsd-elf)
-         major=".$current"
-         versuffix=".$current";
-         ;;
-
-       windows)
-         # Like Linux, but with '-' rather than '.', since we only
-         # want one extension on Windows 95.
-         major=`expr $current - $age`
-         versuffix="-$major-$age-$revision"
-         ;;
-
-       *)
-         $echo "$modename: unknown library version type \`$version_type'" 1>&2
-         echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-         exit 1
-         ;;
-       esac
-
-       # Clear the version info if we defaulted, and they specified a release.
-       if test -z "$vinfo" && test -n "$release"; then
-         major=
-         verstring="0.0"
-         if test "$need_version" = no; then
-           versuffix=
-         else
-           versuffix=".0.0"
-         fi
-       fi
-
-       # Remove version info from name if versioning should be avoided
-       if test "$avoid_version" = yes && test "$need_version" = no; then
-         major=
-         versuffix=
-         verstring=""
-       fi
-       
-       # Check to see if the archive will have undefined symbols.
-       if test "$allow_undefined" = yes; then
-         if test "$allow_undefined_flag" = unsupported; then
-           $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
-           build_libtool_libs=no
-           build_old_libs=yes
-         fi
-       else
-         # Don't allow undefined symbols.
-         allow_undefined_flag="$no_undefined_flag"
-       fi
-
-       dependency_libs="$deplibs"
-       case "$host" in
-       *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
-         # these systems don't actually have a c library (as such)!
-         ;;
-       *)
-         # Add libc to deplibs on all other systems.
-         deplibs="$deplibs -lc"
-         ;;
-       esac
-      fi
-
-      # Create the output directory, or remove our outputs if we need to.
-      if test -d $output_objdir; then
-       $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
-       $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
-      else
-       $show "$mkdir $output_objdir"
-       $run $mkdir $output_objdir
-       status=$?
-       if test $status -ne 0 && test ! -d $output_objdir; then
-         exit $status
-       fi
-      fi
-
-      # Now set the variables for building old libraries.
-      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
-       oldlibs="$oldlibs $output_objdir/$libname.$libext"
-
-       # Transform .lo files to .o files.
-       oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
-      fi
-
-      if test "$build_libtool_libs" = yes; then
-       # Transform deplibs into only deplibs that can be linked in shared.
-       name_save=$name
-       libname_save=$libname
-       release_save=$release
-       versuffix_save=$versuffix
-       major_save=$major
-       # I'm not sure if I'm treating the release correctly.  I think
-       # release should show up in the -l (ie -lgmp5) so we don't want to
-       # add it in twice.  Is that correct?
-       release=""
-       versuffix=""
-       major=""
-       newdeplibs=
-       droppeddeps=no
-       case "$deplibs_check_method" in
-       pass_all)
-         # Don't check for shared/static.  Everything works.
-         # This might be a little naive.  We might want to check
-         # whether the library exists or not.  But this is on
-         # osf3 & osf4 and I'm not really sure... Just
-         # implementing what was already the behaviour.
-         newdeplibs=$deplibs
-         ;;
-       test_compile)
-         # This code stresses the "libraries are programs" paradigm to its
-         # limits. Maybe even breaks it.  We compile a program, linking it
-         # against the deplibs as a proxy for the library.  Then we can check
-         # whether they linked in statically or dynamically with ldd.
-         $rm conftest.c
-         cat > conftest.c <<EOF
-         int main() { return 0; }
-EOF
-         $rm conftest
-         $C_compiler -o conftest conftest.c $deplibs
-         if test $? -eq 0 ; then
-           ldd_output=`ldd conftest`
-           for i in $deplibs; do
-             name="`expr $i : '-l\(.*\)'`"
-             # If $name is empty we are operating on a -L argument.
-             if test "$name" != "" ; then
-               libname=`eval \\$echo \"$libname_spec\"`
-               deplib_matches=`eval \\$echo \"$library_names_spec\"`
-               set dummy $deplib_matches
-               deplib_match=$2
-               if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-                 newdeplibs="$newdeplibs $i"
-               else
-                 droppeddeps=yes
-                 echo
-                 echo "*** Warning: This library needs some functionality provided by $i."
-                 echo "*** I have the capability to make that library automatically link in when"
-                 echo "*** you link to this library.  But I can only do this if you have a"
-                 echo "*** shared version of the library, which you do not appear to have."
-               fi
-             else
-               newdeplibs="$newdeplibs $i"
-             fi
-           done
-         else
-           # Error occured in the first compile.  Let's try to salvage the situation:
-           # Compile a seperate program for each library.
-           for i in $deplibs; do
-             name="`expr $i : '-l\(.*\)'`"
-            # If $name is empty we are operating on a -L argument.
-             if test "$name" != "" ; then
-               $rm conftest
-               $C_compiler -o conftest conftest.c $i
-               # Did it work?
-               if test $? -eq 0 ; then
-                 ldd_output=`ldd conftest`
-                 libname=`eval \\$echo \"$libname_spec\"`
-                 deplib_matches=`eval \\$echo \"$library_names_spec\"`
-                 set dummy $deplib_matches
-                 deplib_match=$2
-                 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-                   newdeplibs="$newdeplibs $i"
-                 else
-                   droppeddeps=yes
-                   echo
-                   echo "*** Warning: This library needs some functionality provided by $i."
-                   echo "*** I have the capability to make that library automatically link in when"
-                   echo "*** you link to this library.  But I can only do this if you have a"
-                   echo "*** shared version of the library, which you do not appear to have."
-                 fi
-               else
-                 droppeddeps=yes
-                 echo
-                 echo "*** Warning!  Library $i is needed by this library but I was not able to"
-                 echo "***  make it link in!  You will probably need to install it or some"
-                 echo "*** library that it depends on before this library will be fully"
-                 echo "*** functional.  Installing it before continuing would be even better."
-               fi
-             else
-               newdeplibs="$newdeplibs $i"
-             fi
-           done
-         fi
-         ;;
-       file_magic*)
-         set dummy $deplibs_check_method
-         file_magic_regex="`expr \"$deplibs_check_method\" : \"$2 \(.*\)\"`"
-         for a_deplib in $deplibs; do
-           name="`expr $a_deplib : '-l\(.*\)'`"
-           # If $name is empty we are operating on a -L argument.
-           if test "$name" != "" ; then
-             libname=`eval \\$echo \"$libname_spec\"`
-             for i in $lib_search_path; do
-                   potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
-                   for potent_lib in $potential_libs; do
-                     # Follow soft links.
-                     if ls -lLd "$potent_lib" 2>/dev/null \
-                        | grep " -> " >/dev/null; then
-                       continue 
-                     fi
-                     # The statement above tries to avoid entering an
-                     # endless loop below, in case of cyclic links.
-                     # We might still enter an endless loop, since a link
-                     # loop can be closed while we follow links,
-                     # but so what?
-                     potlib="$potent_lib"
-                     while test -h "$potlib" 2>/dev/null; do
-                       potliblink=`ls -ld $potlib | sed 's/.* -> //'`
-                       case "$potliblink" in
-                       [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
-                       *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
-                       esac
-                     done
-                     if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
-                        | sed 10q \
-                        | egrep "$file_magic_regex" > /dev/null; then
-                       newdeplibs="$newdeplibs $a_deplib"
-                       a_deplib=""
-                       break 2
-                     fi
-                   done
-             done
-             if test -n "$a_deplib" ; then
-               droppeddeps=yes
-               echo
-               echo "*** Warning: This library needs some functionality provided by $a_deplib."
-               echo "*** I have the capability to make that library automatically link in when"
-               echo "*** you link to this library.  But I can only do this if you have a"
-               echo "*** shared version of the library, which you do not appear to have."
-             fi
-           else
-             # Add a -L argument.
-             newdeplibs="$newdeplibs $a_deplib"
-           fi
-         done # Gone through all deplibs.
-         ;;
-       none | unknown | *)
-         newdeplibs=""
-         if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
-              -e 's/ -[LR][^ ]*//g' -e 's/[    ]//g' |
-            grep . >/dev/null; then
-           echo
-           if test "X$deplibs_check_method" = "Xnone"; then
-             echo "*** Warning: inter-library dependencies are not supported in this platform."
-           else
-             echo "*** Warning: inter-library dependencies are not known to be supported."
-           fi
-           echo "*** All declared inter-library dependencies are being dropped."
-           droppeddeps=yes
-         fi
-         ;;
-       esac
-       versuffix=$versuffix_save
-       major=$major_save
-       release=$release_save
-       libname=$libname_save
-       name=$name_save
-
-       if test "$droppeddeps" = yes; then
-         if test "$module" = yes; then
-           echo
-           echo "*** Warning: libtool could not satisfy all declared inter-library"
-           echo "*** dependencies of module $libname.  Therefore, libtool will create"
-           echo "*** a static module, that should work as long as the dlopening"
-           echo "*** application is linked with the -dlopen flag."
-           if test -z "$global_symbol_pipe"; then
-             echo
-             echo "*** However, this would only work if libtool was able to extract symbol"
-             echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
-             echo "*** not find such a program.  So, this module is probably useless."
-             echo "*** \`nm' from GNU binutils and a full rebuild may help."
-           fi
-           if test "$build_old_libs" = no; then
-             oldlibs="$output_objdir/$libname.$libext"
-             build_libtool_libs=module
-             build_old_libs=yes
-           else
-             build_libtool_libs=no
-           fi
-         else
-           echo "*** The inter-library dependencies that have been dropped here will be"
-           echo "*** automatically added whenever a program is linked with this library"
-           echo "*** or is declared to -dlopen it."
-         fi
-       fi
-       # Done checking deplibs!
-       deplibs=$newdeplibs
-      fi
-
-      # All the library-specific variables (install_libdir is set above).
-      library_names=
-      old_library=
-      dlname=
-      
-      # Test again, we may have decided not to build it any more
-      if test "$build_libtool_libs" = yes; then
-       # Get the real and link names of the library.
-       eval library_names=\"$library_names_spec\"
-       set dummy $library_names
-       realname="$2"
-       shift; shift
-
-       if test -n "$soname_spec"; then
-         eval soname=\"$soname_spec\"
-       else
-         soname="$realname"
-       fi
-
-       lib="$output_objdir/$realname"
-       for link
-       do
-         linknames="$linknames $link"
-       done
-
-       # Ensure that we have .o objects for linkers which dislike .lo
-       # (e.g. aix) incase we are running --disable-static
-       for obj in $libobjs; do
-         oldobj=`$echo "X$obj" | $Xsed -e "$lo2o"`
-         if test ! -f $oldobj; then
-           $show "${LN_S} $obj $oldobj"
-           $run ${LN_S} $obj $oldobj || exit $?
-         fi
-       done
-
-       # Use standard objects if they are pic
-       test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-
-       # Prepare the list of exported symbols
-       if test -z "$export_symbols"; then
-         if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
-           $show "generating symbol list for \`$libname.la'"
-           export_symbols="$output_objdir/$libname.exp"
-           $run $rm $export_symbols
-           eval cmds=\"$export_symbols_cmds\"
-           IFS="${IFS=         }"; save_ifs="$IFS"; IFS='~'
-           for cmd in $cmds; do
-             IFS="$save_ifs"
-             $show "$cmd"
-             $run eval "$cmd" || exit $?
-           done
-           IFS="$save_ifs"
-           if test -n "$export_symbols_regex"; then
-             $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
-             $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
-             $show "$mv \"${export_symbols}T\" \"$export_symbols\""
-             $run eval '$mv "${export_symbols}T" "$export_symbols"'
-           fi
-         fi
-       fi
-
-       if test -n "$export_symbols" && test -n "$include_expsyms"; then
-         $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
-       fi
-
-       if test -n "$convenience"; then
-         if test -n "$whole_archive_flag_spec"; then
-           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
-         else
-           gentop="$output_objdir/${outputname}x"
-           $show "${rm}r $gentop"
-           $run ${rm}r "$gentop"
-           $show "mkdir $gentop"
-           $run mkdir "$gentop"
-           status=$?
-           if test $status -ne 0 && test ! -d "$gentop"; then
-             exit $status
-           fi
-           generated="$generated $gentop"
-
-           for xlib in $convenience; do
-             # Extract the objects.
-             case "$xlib" in
-             [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-             *) xabs=`pwd`"/$xlib" ;;
-             esac
-             xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-             xdir="$gentop/$xlib"
-
-             $show "${rm}r $xdir"
-             $run ${rm}r "$xdir"
-             $show "mkdir $xdir"
-             $run mkdir "$xdir"
-             status=$?
-             if test $status -ne 0 && test ! -d "$xdir"; then
-               exit $status
-             fi
-             $show "(cd $xdir && $AR x $xabs)"
-             $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
-             libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
-           done
-         fi
-       fi
-
-       if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
-         eval flag=\"$thread_safe_flag_spec\"
-         linkopts="$linkopts $flag"
-       fi
-
-       # Do each of the archive commands.
-       if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
-         eval cmds=\"$archive_expsym_cmds\"
-       else
-         eval cmds=\"$archive_cmds\"
-       fi
-       IFS="${IFS=     }"; save_ifs="$IFS"; IFS='~'
-       for cmd in $cmds; do
-         IFS="$save_ifs"
-         $show "$cmd"
-         $run eval "$cmd" || exit $?
-       done
-       IFS="$save_ifs"
-
-       # Create links to the real library.
-       for linkname in $linknames; do
-         if test "$realname" != "$linkname"; then
-           $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
-           $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
-         fi
-       done
-
-       # If -module or -export-dynamic was specified, set the dlname.
-       if test "$module" = yes || test "$export_dynamic" = yes; then
-         # On all known operating systems, these are identical.
-         dlname="$soname"
-       fi
-      fi
-      ;;
-
-    *.lo | *.o | *.obj)
-      if test -n "$link_against_libtool_libs"; then
-       $echo "$modename: error: cannot link libtool libraries into objects" 1>&2
-       exit 1
-      fi
-
-      if test -n "$deplibs"; then
-       $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
-      fi
-
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-       $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$rpath"; then
-       $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$xrpath"; then
-       $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$vinfo"; then
-       $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$release"; then
-       $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
-      fi
-
-      case "$output" in
-      *.lo)
-       if test -n "$objs"; then
-         $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
-         exit 1
-       fi
-       libobj="$output"
-       obj=`$echo "X$output" | $Xsed -e "$lo2o"`
-       ;;
-      *)
-       libobj=
-       obj="$output"
-       ;;
-      esac
-
-      # Delete the old objects.
-      $run $rm $obj $libobj
-
-      # Objects from convenience libraries.  This assumes
-      # single-version convenience libraries.  Whenever we create
-      # different ones for PIC/non-PIC, this we'll have to duplicate
-      # the extraction.
-      reload_conv_objs=
-      gentop=
-      # reload_cmds runs $LD directly, so let us get rid of
-      # -Wl from whole_archive_flag_spec
-      wl= 
-
-      if test -n "$convenience"; then
-       if test -n "$whole_archive_flag_spec"; then
-         eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
-       else
-         gentop="$output_objdir/${obj}x"
-         $show "${rm}r $gentop"
-         $run ${rm}r "$gentop"
-         $show "mkdir $gentop"
-         $run mkdir "$gentop"
-         status=$?
-         if test $status -ne 0 && test ! -d "$gentop"; then
-           exit $status
-         fi
-         generated="$generated $gentop"
-
-         for xlib in $convenience; do
-           # Extract the objects.
-           case "$xlib" in
-           [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-           *) xabs=`pwd`"/$xlib" ;;
-           esac
-           xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-           xdir="$gentop/$xlib"
-
-           $show "${rm}r $xdir"
-           $run ${rm}r "$xdir"
-           $show "mkdir $xdir"
-           $run mkdir "$xdir"
-           status=$?
-           if test $status -ne 0 && test ! -d "$xdir"; then
-             exit $status
-           fi
-           $show "(cd $xdir && $AR x $xabs)"
-           $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
-           reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
-         done
-       fi
-      fi
-
-      # Create the old-style object.
-      reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs"
-
-      output="$obj"
-      eval cmds=\"$reload_cmds\"
-      IFS="${IFS=      }"; save_ifs="$IFS"; IFS='~'
-      for cmd in $cmds; do
-       IFS="$save_ifs"
-       $show "$cmd"
-       $run eval "$cmd" || exit $?
-      done
-      IFS="$save_ifs"
-
-      # Exit if we aren't doing a library object file.
-      if test -z "$libobj"; then
-       if test -n "$gentop"; then
-         $show "${rm}r $gentop"
-         $run ${rm}r $gentop
-       fi
-
-       exit 0
-      fi
-
-      if test "$build_libtool_libs" != yes; then
-       if test -n "$gentop"; then
-         $show "${rm}r $gentop"
-         $run ${rm}r $gentop
-       fi
-
-       # Create an invalid libtool object if no PIC, so that we don't
-       # accidentally link it into a program.
-       $show "echo timestamp > $libobj"
-       $run eval "echo timestamp > $libobj" || exit $?
-       exit 0
-      fi
-
-      if test -n "$pic_flag"; then
-       # Only do commands if we really have different PIC objects.
-       reload_objs="$libobjs $reload_conv_objs"
-       output="$libobj"
-       eval cmds=\"$reload_cmds\"
-       IFS="${IFS=     }"; save_ifs="$IFS"; IFS='~'
-       for cmd in $cmds; do
-         IFS="$save_ifs"
-         $show "$cmd"
-         $run eval "$cmd" || exit $?
-       done
-       IFS="$save_ifs"
-      else
-       # Just create a symlink.
-       $show $rm $libobj
-       $run $rm $libobj
-       $show "$LN_S $obj $libobj"
-       $run $LN_S $obj $libobj || exit $?
-      fi
-
-      if test -n "$gentop"; then
-       $show "${rm}r $gentop"
-       $run ${rm}r $gentop
-      fi
-
-      exit 0
-      ;;
-
-    # Anything else should be a program.
-    *)
-      if test -n "$vinfo"; then
-       $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
-      fi
-
-      if test -n "$release"; then
-       $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
-      fi
-
-      if test "$preload" = yes; then
-       if test "$dlopen" = unknown && test "$dlopen_self" = unknown &&
-          test "$dlopen_self_static" = unknown; then
-         $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
-       fi 
-      fi
-    
-      if test -n "$rpath$xrpath"; then
-       # If the user specified any rpath flags, then add them.
-       for libdir in $rpath $xrpath; do
-         # This is the magic to use -rpath.
-         case "$compile_rpath " in
-         *" $libdir "*) ;;
-         *) compile_rpath="$compile_rpath $libdir" ;;
-         esac
-         case "$finalize_rpath " in
-         *" $libdir "*) ;;
-         *) finalize_rpath="$finalize_rpath $libdir" ;;
-         esac
-       done
-      fi
-
-      # Now hardcode the library paths
-      rpath=
-      hardcode_libdirs=
-      for libdir in $compile_rpath $finalize_rpath; do
-       if test -n "$hardcode_libdir_flag_spec"; then
-         if test -n "$hardcode_libdir_separator"; then
-           if test -z "$hardcode_libdirs"; then
-             hardcode_libdirs="$libdir"
-           else
-             # Just accumulate the unique libdirs.
-             case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
-             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
-               ;;
-             *)
-               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
-               ;;
-             esac
-           fi
-         else
-           eval flag=\"$hardcode_libdir_flag_spec\"
-           rpath="$rpath $flag"
-         fi
-       elif test -n "$runpath_var"; then
-         case "$perm_rpath " in
-         *" $libdir "*) ;;
-         *) perm_rpath="$perm_rpath $libdir" ;;
-         esac
-       fi
-      done
-      # Substitute the hardcoded libdirs into the rpath.
-      if test -n "$hardcode_libdir_separator" &&
-        test -n "$hardcode_libdirs"; then
-       libdir="$hardcode_libdirs"
-       eval rpath=\" $hardcode_libdir_flag_spec\"
-      fi
-      compile_rpath="$rpath"
-
-      rpath=
-      hardcode_libdirs=
-      for libdir in $finalize_rpath; do
-       if test -n "$hardcode_libdir_flag_spec"; then
-         if test -n "$hardcode_libdir_separator"; then
-           if test -z "$hardcode_libdirs"; then
-             hardcode_libdirs="$libdir"
-           else
-             # Just accumulate the unique libdirs.
-             case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
-             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
-               ;;
-             *)
-               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
-               ;;
-             esac
-           fi
-         else
-           eval flag=\"$hardcode_libdir_flag_spec\"
-           rpath="$rpath $flag"
-         fi
-       elif test -n "$runpath_var"; then
-         case "$finalize_perm_rpath " in
-         *" $libdir "*) ;;
-         *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
-         esac
-       fi
-      done
-      # Substitute the hardcoded libdirs into the rpath.
-      if test -n "$hardcode_libdir_separator" &&
-        test -n "$hardcode_libdirs"; then
-       libdir="$hardcode_libdirs"
-       eval rpath=\" $hardcode_libdir_flag_spec\"
-      fi
-      finalize_rpath="$rpath"
-
-      output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
-      if test "X$output_objdir" = "X$output"; then
-       output_objdir="$objdir"
-      else
-       output_objdir="$output_objdir/$objdir"
-      fi
-
-      # Create the binary in the object directory, then wrap it.
-      if test ! -d $output_objdir; then
-       $show "$mkdir $output_objdir"
-       $run $mkdir $output_objdir
-       status=$?
-       if test $status -ne 0 && test ! -d $output_objdir; then
-         exit $status
-       fi
-      fi
-
-      if test -n "$libobjs" && test "$build_old_libs" = yes; then
-       # Transform all the library objects into standard objects.
-       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-       finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-      fi
-
-      dlsyms=
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-       if test -n "$NM" && test -n "$global_symbol_pipe"; then
-         dlsyms="${outputname}S.c"
-       else
-         $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
-       fi
-      fi
-
-      if test -n "$dlsyms"; then
-       case "$dlsyms" in
-       "") ;;
-       *.c)
-         # Discover the nlist of each of the dlfiles.
-         nlist="$output_objdir/${outputname}.nm"
-
-         $show "$rm $nlist ${nlist}S ${nlist}T"
-         $run $rm "$nlist" "${nlist}S" "${nlist}T"
-
-         # Parse the name list into a source file.
-         $show "creating $output_objdir/$dlsyms"
-
-         test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
-/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
-/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
-
-#ifdef __cplusplus
-extern \"C\" {
-#endif
-
-/* Prevent the only kind of declaration conflicts we can make. */
-#define lt_preloaded_symbols some_other_symbol
-
-/* External symbol declarations for the compiler. */\
-"
-
-         if test "$dlself" = yes; then
-           $show "generating symbol list for \`$output'"
-
-           test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
-
-           # Add our own program objects to the symbol list.
-           progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-           for arg in $progfiles; do
-             $show "extracting global C symbols from \`$arg'"
-             $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
-           done
-
-           if test -n "$exclude_expsyms"; then
-             $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
-             $run eval '$mv "$nlist"T "$nlist"'
-           fi
-           
-           if test -n "$export_symbols_regex"; then
-             $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
-             $run eval '$mv "$nlist"T "$nlist"'
-           fi
-
-           # Prepare the list of exported symbols
-           if test -z "$export_symbols"; then
-             export_symbols="$output_objdir/$output.exp"
-             $run $rm $export_symbols
-             $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
-           else
-             $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
-             $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
-             $run eval 'mv "$nlist"T "$nlist"'
-           fi
-         fi
-
-         for arg in $dlprefiles; do
-           $show "extracting global C symbols from \`$arg'"
-           name=`echo "$arg" | sed -e 's%^.*/%%'`
-           $run eval 'echo ": $name " >> "$nlist"'
-           $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
-         done
-
-         if test -z "$run"; then
-           # Make sure we have at least an empty file.
-           test -f "$nlist" || : > "$nlist"
-
-           if test -n "$exclude_expsyms"; then
-             egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
-             $mv "$nlist"T "$nlist"
-           fi
-
-           # Try sorting and uniquifying the output.
-           if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
-             :
-           else
-             grep -v "^: " < "$nlist" > "$nlist"S
-           fi
-
-           if test -f "$nlist"S; then
-             eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
-           else
-             echo '/* NONE */' >> "$output_objdir/$dlsyms"
-           fi
-
-           $echo >> "$output_objdir/$dlsyms" "\
-
-#undef lt_preloaded_symbols
-
-#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
-#else
-# define lt_ptr_t char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
-  const char *name;
-  lt_ptr_t address;
-}
-lt_preloaded_symbols[] =
-{\
-"
-
-           sed -n -e 's/^: \([^ ]*\) $/  {\"\1\", (lt_ptr_t) 0},/p' \
-               -e 's/^. \([^ ]*\) \([^ ]*\)$/  {"\2", (lt_ptr_t) \&\2},/p' \
-                 < "$nlist" >> "$output_objdir/$dlsyms"
-
-           $echo >> "$output_objdir/$dlsyms" "\
-  {0, (lt_ptr_t) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
-  return lt_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif\
-"
-         fi
-
-         pic_flag_for_symtable=
-         case "$host" in
-         # compiling the symbol table file with pic_flag works around
-         # a FreeBSD bug that causes programs to crash when -lm is
-         # linked before any other PIC object.  But we must not use
-         # pic_flag when linking with -static.  The problem exists in
-         # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
-         *-*-freebsd2*|*-*-freebsd3.0*)
-           case "$compile_command " in
-           *" -static "*) ;;
-           *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
-           esac
-         esac
-
-         # Now compile the dynamic symbol file.
-         $show "(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
-         $run eval '(cd $output_objdir && $C_compiler -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
-
-         # Clean up the generated files.
-         $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
-         $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
-
-         # Transform the symbol file into the correct name.
-         compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-         finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-         ;;
-       *)
-         $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
-         exit 1
-         ;;
-       esac
-      else
-       # We keep going just in case the user didn't refer to
-       # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
-       # really was required.
-
-       # Nullify the symbol file.
-       compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
-       finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
-      fi
-
-      if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
-       # Replace the output file specification.
-       compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
-       link_command="$compile_command$compile_rpath"
-
-       # We have no uninstalled library dependencies, so finalize right now.
-       $show "$link_command"
-       $run eval "$link_command"
-       status=$?
-       
-       # Delete the generated files.
-       if test -n "$dlsyms"; then
-         $show "$rm $output_objdir/${outputname}S.${objext}"
-         $run $rm "$output_objdir/${outputname}S.${objext}"
-       fi
-
-       exit $status
-      fi
-
-      if test -n "$shlibpath_var"; then
-       # We should set the shlibpath_var
-       rpath=
-       for dir in $temp_rpath; do
-         case "$dir" in
-         [\\/]* | [A-Za-z]:[\\/]*)
-           # Absolute path.
-           rpath="$rpath$dir:"
-           ;;
-         *)
-           # Relative path: add a thisdir entry.
-           rpath="$rpath\$thisdir/$dir:"
-           ;;
-         esac
-       done
-       temp_rpath="$rpath"
-      fi
-
-      if test -n "$compile_shlibpath$finalize_shlibpath"; then
-       compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
-      fi
-      if test -n "$finalize_shlibpath"; then
-       finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
-      fi
-
-      compile_var=
-      finalize_var=
-      if test -n "$runpath_var"; then
-       if test -n "$perm_rpath"; then
-         # We should set the runpath_var.
-         rpath=
-         for dir in $perm_rpath; do
-           rpath="$rpath$dir:"
-         done
-         compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
-       fi
-       if test -n "$finalize_perm_rpath"; then
-         # We should set the runpath_var.
-         rpath=
-         for dir in $finalize_perm_rpath; do
-           rpath="$rpath$dir:"
-         done
-         finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
-       fi
-      fi
-
-      if test "$hardcode_action" = relink; then
-       # Fast installation is not supported
-       link_command="$compile_var$compile_command$compile_rpath"
-       relink_command="$finalize_var$finalize_command$finalize_rpath"
-       
-       $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
-       $echo "$modename: \`$output' will be relinked during installation" 1>&2
-      else
-       if test "$fast_install" != no; then
-         link_command="$finalize_var$compile_command$finalize_rpath"
-         if test "$fast_install" = yes; then
-           relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
-         else
-           # fast_install is set to needless
-           relink_command=
-         fi
-       else
-         link_command="$compile_var$compile_command$compile_rpath"
-         relink_command="$finalize_var$finalize_command$finalize_rpath"
-       fi
-      fi
-
-      # Replace the output file specification.
-      link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
-      
-      # Delete the old output files.
-      $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
-
-      $show "$link_command"
-      $run eval "$link_command" || exit $?
-
-      # Now create the wrapper script.
-      $show "creating $output"
-
-      # Quote the relink command for shipping.
-      if test -n "$relink_command"; then
-       relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
-      fi
-
-      # Quote $echo for shipping.
-      if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
-       case "$0" in
-       [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
-       *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
-       esac
-       qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
-      else
-       qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
-      fi
-
-      # Only actually do things if our run command is non-null.
-      if test -z "$run"; then
-       # win32 will think the script is a binary if it has
-       # a .exe suffix, so we strip it off here.
-       case $output in
-         *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
-       esac
-       $rm $output
-       trap "$rm $output; exit 1" 1 2 15
-
-       $echo > $output "\
-#! $SHELL
-
-# $output - temporary wrapper script for $objdir/$outputname
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# The $output program cannot be directly executed until all the libtool
-# libraries that it depends on are installed.
-#
-# This wrapper script should never be moved out of the build directory.
-# If it is, it will not operate correctly.
-
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e 1s/^X//'
-sed_quote_subst='$sed_quote_subst'
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi
-
-relink_command=\"$relink_command\"
-
-# This environment variable determines our operation mode.
-if test \"\$libtool_install_magic\" = \"$magic\"; then
-  # install mode needs the following variable:
-  link_against_libtool_libs='$link_against_libtool_libs'
-else
-  # When we are sourced in execute mode, \$file and \$echo are already set.
-  if test \"\$libtool_execute_magic\" != \"$magic\"; then
-    echo=\"$qecho\"
-    file=\"\$0\"
-    # Make sure echo works.
-    if test \"X\$1\" = X--no-reexec; then
-      # Discard the --no-reexec flag, and continue.
-      shift
-    elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
-      # Yippee, \$echo works!
-      :
-    else
-      # Restart under the correct shell, and then maybe \$echo will work.
-      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
-    fi
-  fi\
-"
-       $echo >> $output "\
-
-  # Find the directory that this script lives in.
-  thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
-  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
-
-  # Follow symbolic links until we get to the real thisdir.
-  file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
-  while test -n \"\$file\"; do
-    destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
-
-    # If there was a directory component, then change thisdir.
-    if test \"x\$destdir\" != \"x\$file\"; then
-      case \"\$destdir\" in
-      [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;;
-      *) thisdir=\"\$thisdir/\$destdir\" ;;
-      esac
-    fi
-
-    file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
-    file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
-  done
-
-  # Try to get the absolute directory name.
-  absdir=\`cd \"\$thisdir\" && pwd\`
-  test -n \"\$absdir\" && thisdir=\"\$absdir\"
-"
-
-       if test "$fast_install" = yes; then
-         echo >> $output "\
-  program=lt-'$outputname'
-  progdir=\"\$thisdir/$objdir\"
-  
-  if test ! -f \"\$progdir/\$program\" || \\
-     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
-       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
-
-    file=\"\$\$-\$program\"
-
-    if test ! -d \"\$progdir\"; then
-      $mkdir \"\$progdir\"
-    else
-      $rm \"\$progdir/\$file\"
-    fi"
-
-         echo >> $output "\
-
-    # relink executable if necessary
-    if test -n \"\$relink_command\"; then
-      if (cd \"\$thisdir\" && eval \$relink_command); then :
-      else
-       $rm \"\$progdir/\$file\"
-       exit 1
-      fi
-    fi
-
-    $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
-    { $rm \"\$progdir/\$program\";
-      $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
-    $rm \"\$progdir/\$file\"
-  fi"
-       else
-         echo >> $output "\
-  program='$outputname$exeext'
-  progdir=\"\$thisdir/$objdir\"
-"
-       fi
-
-       echo >> $output "\
-
-  if test -f \"\$progdir/\$program\"; then"
-
-       # Export our shlibpath_var if we have one.
-       if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
-         $echo >> $output "\
-    # Add our own library path to $shlibpath_var
-    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
-
-    # Some systems cannot cope with colon-terminated $shlibpath_var
-    # The second colon is a workaround for a bug in BeOS R4 sed
-    $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
-
-    export $shlibpath_var
-"
-       fi
-
-       # fixup the dll searchpath if we need to.
-       if test -n "$dllsearchpath"; then
-         $echo >> $output "\
-    # Add the dll search path components to the executable PATH
-    PATH=$dllsearchpath:\$PATH
-"
-       fi
-
-       $echo >> $output "\
-    if test \"\$libtool_execute_magic\" != \"$magic\"; then
-      # Run the actual program with our arguments.
-"
-       case $host in
-       *-*-cygwin* | *-*-mingw | *-*-os2*)
-         # win32 systems need to use the prog path for dll
-         # lookup to work
-         $echo >> $output "\
-      exec \$progdir\\\\\$program \${1+\"\$@\"}
-"
-         ;;
-       *)
-         $echo >> $output "\
-      # Export the path to the program.
-      PATH=\"\$progdir:\$PATH\"
-      export PATH
-
-      exec \$program \${1+\"\$@\"}
-"
-         ;;
-       esac
-       $echo >> $output "\
-      \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
-      exit 1
-    fi
-  else
-    # The program doesn't exist.
-    \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
-    \$echo \"This script is just a wrapper for \$program.\" 1>&2
-    echo \"See the $PACKAGE documentation for more information.\" 1>&2
-    exit 1
-  fi
-fi\
-"
-       chmod +x $output
-      fi
-      exit 0
-      ;;
-    esac
-
-    # See if we need to build an old-fashioned archive.
-    for oldlib in $oldlibs; do
-
-      if test "$build_libtool_libs" = convenience; then
-       oldobjs="$libobjs_save"
-       addlibs="$convenience"
-       build_libtool_libs=no
-      else
-       if test "$build_libtool_libs" = module; then
-         oldobjs="$libobjs_save"
-         build_libtool_libs=no
-       else
-         oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
-       fi
-       addlibs="$old_convenience"
-      fi
-
-      if test -n "$addlibs"; then
-       gentop="$output_objdir/${outputname}x"
-       $show "${rm}r $gentop"
-       $run ${rm}r "$gentop"
-       $show "mkdir $gentop"
-       $run mkdir "$gentop"
-       status=$?
-       if test $status -ne 0 && test ! -d "$gentop"; then
-         exit $status
-       fi
-       generated="$generated $gentop"
-         
-       # Add in members from convenience archives.
-       for xlib in $addlibs; do
-         # Extract the objects.
-         case "$xlib" in
-         [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-         *) xabs=`pwd`"/$xlib" ;;
-         esac
-         xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-         xdir="$gentop/$xlib"
-
-         $show "${rm}r $xdir"
-         $run ${rm}r "$xdir"
-         $show "mkdir $xdir"
-         $run mkdir "$xdir"
-         status=$?
-         if test $status -ne 0 && test ! -d "$xdir"; then
-           exit $status
-         fi
-         $show "(cd $xdir && $AR x $xabs)"
-         $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-
-         oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
-       done
-      fi
-
-      # Do each command in the archive commands.
-      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
-       eval cmds=\"$old_archive_from_new_cmds\"
-      else
-       # Ensure that we have .o objects in place incase we decided
-       # not to build a shared library, and have fallen back to building
-       # static libs even though --disable-static was passed!
-       for oldobj in $oldobjs; do
-         if test ! -f $oldobj; then
-           obj=`$echo "X$oldobj" | $Xsed -e "$o2lo"`
-           $show "${LN_S} $obj $oldobj"
-           $run ${LN_S} $obj $oldobj || exit $?
-         fi
-       done
-
-       eval cmds=\"$old_archive_cmds\"
-      fi
-      IFS="${IFS=      }"; save_ifs="$IFS"; IFS='~'
-      for cmd in $cmds; do
-       IFS="$save_ifs"
-       $show "$cmd"
-       $run eval "$cmd" || exit $?
-      done
-      IFS="$save_ifs"
-    done
-
-    if test -n "$generated"; then
-      $show "${rm}r$generated"
-      $run ${rm}r$generated
-    fi
-
-    # Now create the libtool archive.
-    case "$output" in
-    *.la)
-      old_library=
-      test "$build_old_libs" = yes && old_library="$libname.$libext"
-      $show "creating $output"
-
-      if test -n "$xrpath"; then
-       temp_xrpath=
-       for libdir in $xrpath; do
-         temp_xrpath="$temp_xrpath -R$libdir"
-       done
-       dependency_libs="$temp_xrpath $dependency_libs"
-      fi
-
-      # Only create the output if not a dry run.
-      if test -z "$run"; then
-       for installed in no yes; do
-         if test "$installed" = yes; then
-           if test -z "$install_libdir"; then
-             break
-           fi
-           output="$output_objdir/$outputname"i
-         fi
-         $rm $output
-         $echo > $output "\
-# $outputname - a libtool library file
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# The name that we can dlopen(3).
-dlname='$dlname'
-
-# Names of this library.
-library_names='$library_names'
-
-# The name of the static archive.
-old_library='$old_library'
-
-# Libraries that this one depends upon.
-dependency_libs='$dependency_libs'
-
-# Version information for $libname.
-current=$current
-age=$age
-revision=$revision
-
-# Is this an already installed library?
-installed=$installed
-
-# Directory that this library needs to be installed in:
-libdir='$install_libdir'\
-"
-       done
-      fi
-
-      # Do a symbolic link so that the libtool archive can be found in
-      # LD_LIBRARY_PATH before the program is installed.
-      $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
-      $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $?
-      ;;
-    esac
-    exit 0
-    ;;
-
-  # libtool install mode
-  install)
-    modename="$modename: install"
-
-    # There may be an optional sh(1) argument at the beginning of
-    # install_prog (especially on Windows NT).
-    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then
-      # Aesthetically quote it.
-      arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
-      case "$arg" in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*)
-       arg="\"$arg\""
-       ;;
-      esac
-      install_prog="$arg "
-      arg="$1"
-      shift
-    else
-      install_prog=
-      arg="$nonopt"
-    fi
-
-    # The real first argument should be the name of the installation program.
-    # Aesthetically quote it.
-    arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-    case "$arg" in
-    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \      ]*|*]*)
-      arg="\"$arg\""
-      ;;
-    esac
-    install_prog="$install_prog$arg"
-
-    # We need to accept at least all the BSD install flags.
-    dest=
-    files=
-    opts=
-    prev=
-    install_type=
-    isdir=no
-    stripme=
-    for arg
-    do
-      if test -n "$dest"; then
-       files="$files $dest"
-       dest="$arg"
-       continue
-      fi
-
-      case "$arg" in
-      -d) isdir=yes ;;
-      -f) prev="-f" ;;
-      -g) prev="-g" ;;
-      -m) prev="-m" ;;
-      -o) prev="-o" ;;
-      -s)
-       stripme=" -s"
-       continue
-       ;;
-      -*) ;;
-
-      *)
-       # If the previous option needed an argument, then skip it.
-       if test -n "$prev"; then
-         prev=
-       else
-         dest="$arg"
-         continue
-       fi
-       ;;
-      esac
-
-      # Aesthetically quote the argument.
-      arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-      case "$arg" in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*)
-       arg="\"$arg\""
-       ;;
-      esac
-      install_prog="$install_prog $arg"
-    done
-
-    if test -z "$install_prog"; then
-      $echo "$modename: you must specify an install program" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    if test -n "$prev"; then
-      $echo "$modename: the \`$prev' option requires an argument" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    if test -z "$files"; then
-      if test -z "$dest"; then
-       $echo "$modename: no file or destination specified" 1>&2
-      else
-       $echo "$modename: you must specify a destination" 1>&2
-      fi
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    # Strip any trailing slash from the destination.
-    dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
-
-    # Check to see that the destination is a directory.
-    test -d "$dest" && isdir=yes
-    if test "$isdir" = yes; then
-      destdir="$dest"
-      destname=
-    else
-      destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
-      test "X$destdir" = "X$dest" && destdir=.
-      destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
-
-      # Not a directory, so check to see that there is only one file specified.
-      set dummy $files
-      if test $# -gt 2; then
-       $echo "$modename: \`$dest' is not a directory" 1>&2
-       $echo "$help" 1>&2
-       exit 1
-      fi
-    fi
-    case "$destdir" in
-    [\\/]* | [A-Za-z]:[\\/]*) ;;
-    *)
-      for file in $files; do
-       case "$file" in
-       *.lo) ;;
-       *)
-         $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
-         $echo "$help" 1>&2
-         exit 1
-         ;;
-       esac
-      done
-      ;;
-    esac
-
-    # This variable tells wrapper scripts just to set variables rather
-    # than running their programs.
-    libtool_install_magic="$magic"
-
-    staticlibs=
-    future_libdirs=
-    current_libdirs=
-    for file in $files; do
-
-      # Do each installation.
-      case "$file" in
-      *.a | *.lib)
-       # Do the static libraries later.
-       staticlibs="$staticlibs $file"
-       ;;
-
-      *.la)
-       # Check to see that this really is a libtool archive.
-       if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-       else
-         $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
-         $echo "$help" 1>&2
-         exit 1
-       fi
-
-       library_names=
-       old_library=
-       # If there is no directory component, then add one.
-       case "$file" in
-       */* | *\\*) . $file ;;
-       *) . ./$file ;;
-       esac
-
-       # Add the libdir to current_libdirs if it is the destination.
-       if test "X$destdir" = "X$libdir"; then
-         case "$current_libdirs " in
-         *" $libdir "*) ;;
-         *) current_libdirs="$current_libdirs $libdir" ;;
-         esac
-       else
-         # Note the libdir as a future libdir.
-         case "$future_libdirs " in
-         *" $libdir "*) ;;
-         *) future_libdirs="$future_libdirs $libdir" ;;
-         esac
-       fi
-
-       dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/"
-       test "X$dir" = "X$file/" && dir=
-       dir="$dir$objdir"
-
-       # See the names of the shared library.
-       set dummy $library_names
-       if test -n "$2"; then
-         realname="$2"
-         shift
-         shift
-
-         # Install the shared library and build the symlinks.
-         $show "$install_prog $dir/$realname $destdir/$realname"
-         $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
-
-         if test $# -gt 0; then
-           # Delete the old symlinks, and create new ones.
-           for linkname
-           do
-             if test "$linkname" != "$realname"; then
-               $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
-               $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
-             fi
-           done
-         fi
-
-         # Do each command in the postinstall commands.
-         lib="$destdir/$realname"
-         eval cmds=\"$postinstall_cmds\"
-         IFS="${IFS=   }"; save_ifs="$IFS"; IFS='~'
-         for cmd in $cmds; do
-           IFS="$save_ifs"
-           $show "$cmd"
-           $run eval "$cmd" || exit $?
-         done
-         IFS="$save_ifs"
-       fi
-
-       # Install the pseudo-library for information purposes.
-       name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-       instname="$dir/$name"i
-       $show "$install_prog $instname $destdir/$name"
-       $run eval "$install_prog $instname $destdir/$name" || exit $?
-
-       # Maybe install the static library, too.
-       test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
-       ;;
-
-      *.lo)
-       # Install (i.e. copy) a libtool object.
-
-       # Figure out destination file name, if it wasn't already specified.
-       if test -n "$destname"; then
-         destfile="$destdir/$destname"
-       else
-         destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-         destfile="$destdir/$destfile"
-       fi
-
-       # Deduce the name of the destination old-style object file.
-       case "$destfile" in
-       *.lo)
-         staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
-         ;;
-       *.o | *.obj)
-         staticdest="$destfile"
-         destfile=
-         ;;
-       *)
-         $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
-         $echo "$help" 1>&2
-         exit 1
-         ;;
-       esac
-
-       # Install the libtool object if requested.
-       if test -n "$destfile"; then
-         $show "$install_prog $file $destfile"
-         $run eval "$install_prog $file $destfile" || exit $?
-       fi
-
-       # Install the old object if enabled.
-       if test "$build_old_libs" = yes; then
-         # Deduce the name of the old-style object file.
-         staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
-
-         $show "$install_prog $staticobj $staticdest"
-         $run eval "$install_prog \$staticobj \$staticdest" || exit $?
-       fi
-       exit 0
-       ;;
-
-      *)
-       # Figure out destination file name, if it wasn't already specified.
-       if test -n "$destname"; then
-         destfile="$destdir/$destname"
-       else
-         destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-         destfile="$destdir/$destfile"
-       fi
-
-       # Do a test to see if this is really a libtool program.
-       if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-         link_against_libtool_libs=
-         relink_command=
-
-         # If there is no directory component, then add one.
-         case "$file" in
-         */* | *\\*) . $file ;;
-         *) . ./$file ;;
-         esac
-
-         # Check the variables that should have been set.
-         if test -z "$link_against_libtool_libs"; then
-           $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
-           exit 1
-         fi
-
-         finalize=yes
-         for lib in $link_against_libtool_libs; do
-           # Check to see that each library is installed.
-           libdir=
-           if test -f "$lib"; then
-             # If there is no directory component, then add one.
-             case "$lib" in
-             */* | *\\*) . $lib ;;
-             *) . ./$lib ;;
-             esac
-           fi
-           libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`"
-           if test -n "$libdir" && test ! -f "$libfile"; then
-             $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
-             finalize=no
-           fi
-         done
-
-         outputname=
-         if test "$fast_install" = no && test -n "$relink_command"; then
-           if test "$finalize" = yes && test -z "$run"; then
-             tmpdir="/tmp"
-             test -n "$TMPDIR" && tmpdir="$TMPDIR"
-             tmpdir="$tmpdir/libtool-$$"
-             if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
-             else
-               $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
-               continue
-             fi
-             outputname="$tmpdir/$file"
-             # Replace the output file specification.
-             relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
-
-             $show "$relink_command"
-             if $run eval "$relink_command"; then :
-             else
-               $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
-               ${rm}r "$tmpdir"
-               continue
-             fi
-             file="$outputname"
-           else
-             $echo "$modename: warning: cannot relink \`$file'" 1>&2
-           fi
-         else
-           # Install the binary that we compiled earlier.
-           file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
-         fi
-       fi
-
-       $show "$install_prog$stripme $file $destfile"
-       $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
-       test -n "$outputname" && ${rm}r "$tmpdir"
-       ;;
-      esac
-    done
-
-    for file in $staticlibs; do
-      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-
-      # Set up the ranlib parameters.
-      oldlib="$destdir/$name"
-
-      $show "$install_prog $file $oldlib"
-      $run eval "$install_prog \$file \$oldlib" || exit $?
-
-      # Do each command in the postinstall commands.
-      eval cmds=\"$old_postinstall_cmds\"
-      IFS="${IFS=      }"; save_ifs="$IFS"; IFS='~'
-      for cmd in $cmds; do
-       IFS="$save_ifs"
-       $show "$cmd"
-       $run eval "$cmd" || exit $?
-      done
-      IFS="$save_ifs"
-    done
-
-    if test -n "$future_libdirs"; then
-      $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
-    fi
-
-    if test -n "$current_libdirs"; then
-      # Maybe just do a dry run.
-      test -n "$run" && current_libdirs=" -n$current_libdirs"
-      exec $SHELL $0 --finish$current_libdirs
-      exit 1
-    fi
-
-    exit 0
-    ;;
-
-  # libtool finish mode
-  finish)
-    modename="$modename: finish"
-    libdirs="$nonopt"
-    admincmds=
-
-    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
-      for dir
-      do
-       libdirs="$libdirs $dir"
-      done
-
-      for libdir in $libdirs; do
-       if test -n "$finish_cmds"; then
-         # Do each command in the finish commands.
-         eval cmds=\"$finish_cmds\"
-         IFS="${IFS=   }"; save_ifs="$IFS"; IFS='~'
-         for cmd in $cmds; do
-           IFS="$save_ifs"
-           $show "$cmd"
-           $run eval "$cmd" || admincmds="$admincmds
-       $cmd"
-         done
-         IFS="$save_ifs"
-       fi
-       if test -n "$finish_eval"; then
-         # Do the single finish_eval.
-         eval cmds=\"$finish_eval\"
-         $run eval "$cmds" || admincmds="$admincmds
-       $cmds"
-       fi
-      done
-    fi
-
-    # Exit here if they wanted silent mode.
-    test "$show" = : && exit 0
-
-    echo "----------------------------------------------------------------------"
-    echo "Libraries have been installed in:"
-    for libdir in $libdirs; do
-      echo "   $libdir"
-    done
-    echo
-    echo "If you ever happen to want to link against installed libraries"
-    echo "in a given directory, LIBDIR, you must either use libtool, and"
-    echo "specify the full pathname of the library, or use \`-LLIBDIR'"
-    echo "flag during linking and do at least one of the following:"
-    if test -n "$shlibpath_var"; then
-      echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
-      echo "     during execution"
-    fi
-    if test -n "$runpath_var"; then
-      echo "   - add LIBDIR to the \`$runpath_var' environment variable"
-      echo "     during linking"
-    fi
-    if test -n "$hardcode_libdir_flag_spec"; then
-      libdir=LIBDIR
-      eval flag=\"$hardcode_libdir_flag_spec\"
-
-      echo "   - use the \`$flag' linker flag"
-    fi
-    if test -n "$admincmds"; then
-      echo "   - have your system administrator run these commands:$admincmds"
-    fi
-    if test -f /etc/ld.so.conf; then
-      echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
-    fi
-    echo
-    echo "See any operating system documentation about shared libraries for"
-    echo "more information, such as the ld(1) and ld.so(8) manual pages."
-    echo "----------------------------------------------------------------------"
-    exit 0
-    ;;
-
-  # libtool execute mode
-  execute)
-    modename="$modename: execute"
-
-    # The first argument is the command name.
-    cmd="$nonopt"
-    if test -z "$cmd"; then
-      $echo "$modename: you must specify a COMMAND" 1>&2
-      $echo "$help"
-      exit 1
-    fi
-
-    # Handle -dlopen flags immediately.
-    for file in $execute_dlfiles; do
-      if test ! -f "$file"; then
-       $echo "$modename: \`$file' is not a file" 1>&2
-       $echo "$help" 1>&2
-       exit 1
-      fi
-
-      dir=
-      case "$file" in
-      *.la)
-       # Check to see that this really is a libtool archive.
-       if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-       else
-         $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-         $echo "$help" 1>&2
-         exit 1
-       fi
-
-       # Read the libtool library.
-       dlname=
-       library_names=
-
-       # If there is no directory component, then add one.
-       case "$file" in
-       */* | *\\*) . $file ;;
-       *) . ./$file ;;
-       esac
-
-       # Skip this library if it cannot be dlopened.
-       if test -z "$dlname"; then
-         # Warn if it was a shared library.
-         test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
-         continue
-       fi
-
-       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
-       test "X$dir" = "X$file" && dir=.
-
-       if test -f "$dir/$objdir/$dlname"; then
-         dir="$dir/$objdir"
-       else
-         $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
-         exit 1
-       fi
-       ;;
-
-      *.lo)
-       # Just add the directory containing the .lo file.
-       dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
-       test "X$dir" = "X$file" && dir=.
-       ;;
-
-      *)
-       $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
-       continue
-       ;;
-      esac
-
-      # Get the absolute pathname.
-      absdir=`cd "$dir" && pwd`
-      test -n "$absdir" && dir="$absdir"
-
-      # Now add the directory to shlibpath_var.
-      if eval "test -z \"\$$shlibpath_var\""; then
-       eval "$shlibpath_var=\"\$dir\""
-      else
-       eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
-      fi
-    done
-
-    # This variable tells wrapper scripts just to set shlibpath_var
-    # rather than running their programs.
-    libtool_execute_magic="$magic"
-
-    # Check if any of the arguments is a wrapper script.
-    args=
-    for file
-    do
-      case "$file" in
-      -*) ;;
-      *)
-       # Do a test to see if this is really a libtool program.
-       if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-         # If there is no directory component, then add one.
-         case "$file" in
-         */* | *\\*) . $file ;;
-         *) . ./$file ;;
-         esac
-
-         # Transform arg to wrapped name.
-         file="$progdir/$program"
-       fi
-       ;;
-      esac
-      # Quote arguments (to preserve shell metacharacters).
-      file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
-      args="$args \"$file\""
-    done
-
-    if test -z "$run"; then
-      # Export the shlibpath_var.
-      eval "export $shlibpath_var"
-
-      # Restore saved enviroment variables
-      if test "${save_LC_ALL+set}" = set; then
-       LC_ALL="$save_LC_ALL"; export LC_ALL
-      fi
-      if test "${save_LANG+set}" = set; then
-       LANG="$save_LANG"; export LANG
-      fi
-
-      # Now actually exec the command.
-      eval "exec \$cmd$args"
-
-      $echo "$modename: cannot exec \$cmd$args"
-      exit 1
-    else
-      # Display what would be done.
-      eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
-      $echo "export $shlibpath_var"
-      $echo "$cmd$args"
-      exit 0
-    fi
-    ;;
-
-  # libtool uninstall mode
-  uninstall)
-    modename="$modename: uninstall"
-    rm="$nonopt"
-    files=
-
-    for arg
-    do
-      case "$arg" in
-      -*) rm="$rm $arg" ;;
-      *) files="$files $arg" ;;
-      esac
-    done
-
-    if test -z "$rm"; then
-      $echo "$modename: you must specify an RM program" 1>&2
-      $echo "$help" 1>&2
-      exit 1
-    fi
-
-    for file in $files; do
-      dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
-      test "X$dir" = "X$file" && dir=.
-      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-
-      rmfiles="$file"
-
-      case "$name" in
-      *.la)
-       # Possibly a libtool archive, so verify it.
-       if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-         . $dir/$name
-
-         # Delete the libtool libraries and symlinks.
-         for n in $library_names; do
-           rmfiles="$rmfiles $dir/$n"
-         done
-         test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
-
-         $show "$rm $rmfiles"
-         $run $rm $rmfiles
-
-         if test -n "$library_names"; then
-           # Do each command in the postuninstall commands.
-           eval cmds=\"$postuninstall_cmds\"
-           IFS="${IFS=         }"; save_ifs="$IFS"; IFS='~'
-           for cmd in $cmds; do
-             IFS="$save_ifs"
-             $show "$cmd"
-             $run eval "$cmd"
-           done
-           IFS="$save_ifs"
-         fi
-
-         if test -n "$old_library"; then
-           # Do each command in the old_postuninstall commands.
-           eval cmds=\"$old_postuninstall_cmds\"
-           IFS="${IFS=         }"; save_ifs="$IFS"; IFS='~'
-           for cmd in $cmds; do
-             IFS="$save_ifs"
-             $show "$cmd"
-             $run eval "$cmd"
-           done
-           IFS="$save_ifs"
-         fi
-
-         # FIXME: should reinstall the best remaining shared library.
-       fi
-       ;;
-
-      *.lo)
-       if test "$build_old_libs" = yes; then
-         oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
-         rmfiles="$rmfiles $dir/$oldobj"
-       fi
-       $show "$rm $rmfiles"
-       $run $rm $rmfiles
-       ;;
-
-      *)
-       $show "$rm $rmfiles"
-       $run $rm $rmfiles
-       ;;
-      esac
-    done
-    exit 0
-    ;;
-
-  "")
-    $echo "$modename: you must specify a MODE" 1>&2
-    $echo "$generic_help" 1>&2
-    exit 1
-    ;;
-  esac
-
-  $echo "$modename: invalid operation mode \`$mode'" 1>&2
-  $echo "$generic_help" 1>&2
-  exit 1
-fi # test -z "$show_help"
-
-# We need to display help for each of the modes.
-case "$mode" in
-"") $echo \
-"Usage: $modename [OPTION]... [MODE-ARG]...
-
-Provide generalized library-building support services.
-
-    --config          show all configuration variables
-    --debug           enable verbose shell tracing
--n, --dry-run         display commands without modifying any files
-    --features        display basic configuration information and exit
-    --finish          same as \`--mode=finish'
-    --help            display this help message and exit
-    --mode=MODE       use operation mode MODE [default=inferred from MODE-ARGS]
-    --quiet           same as \`--silent'
-    --silent          don't print informational messages
-    --version         print version information
-
-MODE must be one of the following:
-
-      compile         compile a source file into a libtool object
-      execute         automatically set library path, then run a program
-      finish          complete the installation of libtool libraries
-      install         install libraries or executables
-      link            create a library or an executable
-      uninstall       remove libraries from an installed directory
-
-MODE-ARGS vary depending on the MODE.  Try \`$modename --help --mode=MODE' for
-a more detailed description of MODE."
-  exit 0
-  ;;
-
-compile)
-  $echo \
-"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
-
-Compile a source file into a libtool library object.
-
-This mode accepts the following additional options:
-
-  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
-  -static           always build a \`.o' file suitable for static linking
-
-COMPILE-COMMAND is a command to be used in creating a \`standard' object file
-from the given SOURCEFILE.
-
-The output file name is determined by removing the directory component from
-SOURCEFILE, then substituting the C source code suffix \`.c' with the
-library object suffix, \`.lo'."
-  ;;
-
-execute)
-  $echo \
-"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
-
-Automatically set library path, then run a program.
-
-This mode accepts the following additional options:
-
-  -dlopen FILE      add the directory containing FILE to the library path
-
-This mode sets the library path environment variable according to \`-dlopen'
-flags.
-
-If any of the ARGS are libtool executable wrappers, then they are translated
-into their corresponding uninstalled binary, and any of their required library
-directories are added to the library path.
-
-Then, COMMAND is executed, with ARGS as arguments."
-  ;;
-
-finish)
-  $echo \
-"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
-
-Complete the installation of libtool libraries.
-
-Each LIBDIR is a directory that contains libtool libraries.
-
-The commands that this mode executes may require superuser privileges.  Use
-the \`--dry-run' option if you just want to see what would be executed."
-  ;;
-
-install)
-  $echo \
-"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
-
-Install executables or libraries.
-
-INSTALL-COMMAND is the installation command.  The first component should be
-either the \`install' or \`cp' program.
-
-The rest of the components are interpreted as arguments to that command (only
-BSD-compatible install options are recognized)."
-  ;;
-
-link)
-  $echo \
-"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
-
-Link object files or libraries together to form another library, or to
-create an executable program.
-
-LINK-COMMAND is a command using the C compiler that you would use to create
-a program from several object files.
-
-The following components of LINK-COMMAND are treated specially:
-
-  -all-static       do not do any dynamic linking at all
-  -avoid-version    do not add a version suffix if possible
-  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
-  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
-  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
-  -export-symbols SYMFILE
-                   try to export only the symbols listed in SYMFILE
-  -export-symbols-regex REGEX
-                   try to export only the symbols matching REGEX
-  -LLIBDIR          search LIBDIR for required installed libraries
-  -lNAME            OUTPUT-FILE requires the installed library libNAME
-  -module           build a library that can dlopened
-  -no-undefined     declare that a library does not refer to external symbols
-  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
-  -release RELEASE  specify package release information
-  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
-  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
-  -static           do not do any dynamic linking of libtool libraries
-  -version-info CURRENT[:REVISION[:AGE]]
-                   specify library version info [each variable defaults to 0]
-
-All other options (arguments beginning with \`-') are ignored.
-
-Every other argument is treated as a filename.  Files ending in \`.la' are
-treated as uninstalled libtool libraries, other files are standard or library
-object files.
-
-If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
-only library objects (\`.lo' files) may be specified, and \`-rpath' is
-required, except when creating a convenience library.
-
-If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
-using \`ar' and \`ranlib', or on Windows using \`lib'.
-
-If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
-is created, otherwise an executable program is created."
-  ;;
-
-uninstall)
-  $echo \
-"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
-
-Remove libraries from an installation directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, all the files associated with it are deleted.
-Otherwise, only FILE itself is deleted using RM."
-  ;;
-
-*)
-  $echo "$modename: invalid operation mode \`$mode'" 1>&2
-  $echo "$help" 1>&2
-  exit 1
-  ;;
-esac
-
-echo
-$echo "Try \`$modename --help' for more information about other modes."
-
-exit 0
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
diff --git a/config/missing b/config/missing
deleted file mode 100755 (executable)
index 7789652..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-#! /bin/sh
-# Common stub for a few missing GNU programs while installing.
-# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
-# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-# 02111-1307, USA.
-
-if test $# -eq 0; then
-  echo 1>&2 "Try \`$0 --help' for more information"
-  exit 1
-fi
-
-case "$1" in
-
-  -h|--h|--he|--hel|--help)
-    echo "\
-$0 [OPTION]... PROGRAM [ARGUMENT]...
-
-Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
-error status if there is no known handling for PROGRAM.
-
-Options:
-  -h, --help      display this help and exit
-  -v, --version   output version information and exit
-
-Supported PROGRAM values:
-  aclocal      touch file \`aclocal.m4'
-  autoconf     touch file \`configure'
-  autoheader   touch file \`config.h.in'
-  automake     touch all \`Makefile.in' files
-  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
-  flex         create \`lex.yy.c', if possible, from existing .c
-  lex          create \`lex.yy.c', if possible, from existing .c
-  makeinfo     touch the output file
-  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]"
-    ;;
-
-  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
-    echo "missing - GNU libit 0.0"
-    ;;
-
-  -*)
-    echo 1>&2 "$0: Unknown \`$1' option"
-    echo 1>&2 "Try \`$0 --help' for more information"
-    exit 1
-    ;;
-
-  aclocal)
-    echo 1>&2 "\
-WARNING: \`$1' is missing on your system.  You should only need it if
-         you modified \`acinclude.m4' or \`configure.in'.  You might want
-         to install the \`Automake' and \`Perl' packages.  Grab them from
-         any GNU archive site."
-    touch aclocal.m4
-    ;;
-
-  autoconf)
-    echo 1>&2 "\
-WARNING: \`$1' is missing on your system.  You should only need it if
-         you modified \`configure.in'.  You might want to install the
-         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
-         archive site."
-    touch configure
-    ;;
-
-  autoheader)
-    echo 1>&2 "\
-WARNING: \`$1' is missing on your system.  You should only need it if
-         you modified \`acconfig.h' or \`configure.in'.  You might want
-         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
-         from any GNU archive site."
-    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
-    test -z "$files" && files="config.h"
-    touch_files=
-    for f in $files; do
-      case "$f" in
-      *:*) touch_files="$touch_files "`echo "$f" |
-                                      sed -e 's/^[^:]*://' -e 's/:.*//'`;;
-      *) touch_files="$touch_files $f.in";;
-      esac
-    done
-    touch $touch_files
-    ;;
-
-  automake)
-    echo 1>&2 "\
-WARNING: \`$1' is missing on your system.  You should only need it if
-         you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
-         You might want to install the \`Automake' and \`Perl' packages.
-         Grab them from any GNU archive site."
-    find . -type f -name Makefile.am -print |
-          sed 's/\.am$/.in/' |
-          while read f; do touch "$f"; done
-    ;;
-
-  bison|yacc)
-    echo 1>&2 "\
-WARNING: \`$1' is missing on your system.  You should only need it if
-         you modified a \`.y' file.  You may need the \`Bison' package
-         in order for those modifications to take effect.  You can get
-         \`Bison' from any GNU archive site."
-    rm -f y.tab.c y.tab.h
-    if [ $# -ne 1 ]; then
-        eval LASTARG="\${$#}"
-       case "$LASTARG" in
-       *.y)
-           SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
-           if [ -f "$SRCFILE" ]; then
-                cp "$SRCFILE" y.tab.c
-           fi
-           SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
-           if [ -f "$SRCFILE" ]; then
-                cp "$SRCFILE" y.tab.h
-           fi
-         ;;
-       esac
-    fi
-    if [ ! -f y.tab.h ]; then
-       echo >y.tab.h
-    fi
-    if [ ! -f y.tab.c ]; then
-       echo 'main() { return 0; }' >y.tab.c
-    fi
-    ;;
-
-  lex|flex)
-    echo 1>&2 "\
-WARNING: \`$1' is missing on your system.  You should only need it if
-         you modified a \`.l' file.  You may need the \`Flex' package
-         in order for those modifications to take effect.  You can get
-         \`Flex' from any GNU archive site."
-    rm -f lex.yy.c
-    if [ $# -ne 1 ]; then
-        eval LASTARG="\${$#}"
-       case "$LASTARG" in
-       *.l)
-           SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
-           if [ -f "$SRCFILE" ]; then
-                cp "$SRCFILE" lex.yy.c
-           fi
-         ;;
-       esac
-    fi
-    if [ ! -f lex.yy.c ]; then
-       echo 'main() { return 0; }' >lex.yy.c
-    fi
-    ;;
-
-  makeinfo)
-    echo 1>&2 "\
-WARNING: \`$1' is missing on your system.  You should only need it if
-         you modified a \`.texi' or \`.texinfo' file, or any other file
-         indirectly affecting the aspect of the manual.  The spurious
-         call might also be the consequence of using a buggy \`make' (AIX,
-         DU, IRIX).  You might want to install the \`Texinfo' package or
-         the \`GNU make' package.  Grab either from any GNU archive site."
-    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
-    if test -z "$file"; then
-      file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
-      file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
-    fi
-    touch $file
-    ;;
-
-  *)
-    echo 1>&2 "\
-WARNING: \`$1' is needed, and you do not seem to have it handy on your
-         system.  You might have modified some files without having the
-         proper tools for further handling them.  Check the \`README' file,
-         it often tells you about the needed prerequirements for installing
-         this package.  You may also peek at any GNU archive site, in case
-         some other package would contain this missing \`$1' program."
-    exit 1
-    ;;
-esac
-
-exit 0
diff --git a/config/mkinstalldirs b/config/mkinstalldirs
deleted file mode 100755 (executable)
index 6b3b5fc..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#! /bin/sh
-# mkinstalldirs --- make directory hierarchy
-# Author: Noah Friedman <friedman@prep.ai.mit.edu>
-# Created: 1993-05-16
-# Public domain
-
-# $Id$
-
-errstatus=0
-
-for file
-do
-   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
-   shift
-
-   pathcomp=
-   for d
-   do
-     pathcomp="$pathcomp$d"
-     case "$pathcomp" in
-       -* ) pathcomp=./$pathcomp ;;
-     esac
-
-     if test ! -d "$pathcomp"; then
-        echo "mkdir $pathcomp"
-
-        mkdir "$pathcomp" || lasterr=$?
-
-        if test ! -d "$pathcomp"; then
-         errstatus=$lasterr
-        fi
-     fi
-
-     pathcomp="$pathcomp/"
-   done
-done
-
-exit $errstatus
-
-# mkinstalldirs ends here
diff --git a/config/stamp-h b/config/stamp-h
deleted file mode 100644 (file)
index 9788f70..0000000
+++ /dev/null
@@ -1 +0,0 @@
-timestamp
diff --git a/config/stamp-h.in b/config/stamp-h.in
deleted file mode 100644 (file)
index 9788f70..0000000
+++ /dev/null
@@ -1 +0,0 @@
-timestamp
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..c21395a
--- /dev/null
@@ -0,0 +1,481 @@
+dnl RRDtool AutoConf script ... 
+dnl ---------------------------
+dnl
+dnl Created by Jeff Allen, Tobi Oetiker, Blair Zajac
+dnl
+dnl
+
+dnl tell automake the this script is for rrdtool
+AC_INIT(src/rrd_tool.c)
+AC_CONFIG_AUX_DIR(config)
+AC_CANONICAL_TARGET([])
+AM_INIT_AUTOMAKE(rrdtool, 1.1.0)
+AM_CONFIG_HEADER(config/config.h)
+
+dnl all our local stuff like install scripts and include files
+dnl is in there
+
+
+dnl determine the type of system we are running on
+
+
+AC_SUBST(VERSION)
+
+dnl where we install our stuff ...
+AC_PREFIX_DEFAULT( /usr/local/rrdtool-1.1.0 )
+
+dnl Minimum Autoconf version required.
+AC_PREREQ(2.52)
+
+dnl At the TOP of the HEADER
+
+AH_TOP([
+
+#ifndef CONFIG_H
+#define CONFIG_H
+/* IEEE can be prevented from raising signals with fpsetmask(0) */
+#undef MUST_DISABLE_FPMASK
+
+/* IEEE math only works if SIGFPE gets actively set to IGNORE */
+
+#undef MUST_DISABLE_SIGFPE
+
+/* realloc does not support NULL as argument */
+#undef NO_NULL_REALLOC
+ ])
+
+AH_BOTTOM([
+
+/* define strrchr, strchr and memcpy, memmove in terms of bsd funcs
+   make sure you are NOT using bcopy, index or rindex in the code */
+      
+#if STDC_HEADERS
+# include <string.h>
+#else
+# ifndef HAVE_STRCHR
+#  define strchr index
+#  define strrchr rindex
+# endif
+char *strchr (), *strrchr ();
+# ifndef HAVE_MEMMOVE
+#  define memcpy(d, s, n) bcopy ((s), (d), (n))
+#  define memmove(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+
+#if NO_NULL_REALLOC
+# define rrd_realloc(a,b) ( (a) == NULL ? malloc( (b) ) : realloc( (a) , (b) ))
+#else
+# define rrd_realloc(a,b) realloc((a), (b))
+#endif      
+
+#if HAVE_MATH_H
+#  include <math.h>
+#endif
+
+#if HAVE_FLOAT_H
+#  include <float.h>
+#endif
+
+#if HAVE_IEEEFP_H
+#  include <ieeefp.h>
+#endif
+
+#if HAVE_FP_CLASS_H
+#  include <fp_class.h>
+#endif
+
+/* for Solaris */
+#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASS))
+#  define HAVE_ISINF 1
+#  define isinf(a) (fpclass(a) == FP_NINF || fpclass(a) == FP_PINF)
+#endif
+
+/* for OSF1 Digital Unix */
+#if (! defined(HAVE_ISINF) && defined(HAVE_FP_CLASS) && defined(HAVE_FP_CLASS_H))
+#  define HAVE_ISINF 1
+#  define isinf(a) (fp_class(a) == FP_NEG_INF || fp_class(a) == FP_POS_INF)
+#endif
+
+#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASSIFY) && defined(FP_PLUS_INF) && defined(FP_MINUS_INF))
+#  define HAVE_ISINF 1
+#  define isinf(a) (fpclassify(a) == FP_MINUS_INF || fpclassify(a) == FP_PLUS_INF)
+#endif
+
+#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASSIFY) && defined(FP_INFINITE))
+#  define HAVE_ISINF 1
+#  define isinf(a) (fpclassify(a) == FP_INFINITE)
+#endif
+
+/* for AIX */
+#if (! defined(HAVE_ISINF) && defined(HAVE_CLASS))
+#  define HAVE_ISINF 1
+#  define isinf(a) (class(a) == FP_MINUS_INF || class(a) == FP_PLUS_INF)
+#endif
+
+#if (! defined (HAVE_FINITE) && defined (HAVE_ISFINITE))
+#  define HAVE_FINITE 1
+#  define finite(a) isfinite(a)
+#endif
+
+#if (! defined(HAVE_FINITE) && defined(HAVE_ISNAN) && defined(HAVE_ISINF))
+#  define HAVE_FINITE 1
+#  define finite(a) (! isnan(a) && ! isinf(a))
+#endif
+
+#ifndef HAVE_FINITE
+#error "Can't compile without finite function"
+#endif
+
+#ifndef HAVE_ISINF
+#error "Can't compile without isinf function"
+#endif
+
+#endif /* CONFIG_H */
+])
+
+
+dnl Define library subdirectory names here.
+CGI_LIB_DIR=libraries/cgilib-0.4
+FREETYPE_LIB_DIR=libraries/freetype-2.0.5
+ART_LIB_DIR=libraries/libart_lgpl-2.3.7
+PNG_LIB_DIR=libraries/libpng-1.2.0
+ZLIB_LIB_DIR=libraries/zlib-1.1.3
+
+dnl substitute them in all the files listed in AC_OUTPUT
+AC_SUBST(CGI_LIB_DIR)
+AC_SUBST(ART_LIB_DIR)
+AC_SUBST(PNG_LIB_DIR)
+AC_SUBST(FREETYPE_LIB_DIR)
+AC_SUBST(ZLIB_LIB_DIR)
+AC_SUBST(PERLFLAGS)
+
+dnl Check for Perl.
+AC_PATH_PROG(PERL, perl, no)
+if test "x$PERL" = "xno"; then
+       COMP_PERL=
+else
+       COMP_PERL="perl_piped perl_shared"
+       AC_MSG_CHECKING(for shared library extension)
+       SO_EXT=`$PERL -e 'use Config; if (defined $Config{so} and $Config{so} ne 'a') {print "$Config{so}\n"} else {print "so\n"};'`
+       AC_MSG_RESULT($SO_EXT)
+        AC_MSG_CHECKING(for the C compiler perl wants to use to build its modules)
+        PROBLEMCC=`$PERL -e 'use Config; map {if (-x "$_/$Config{cc}"){exit 0}} split /:/, $ENV{PATH};print $Config{cc}'`
+        if test x$PROBLEMCC != x; then
+                AC_MSG_RESULT(no)
+                echo Could not find the Compiler: '"'$PROBLEMCC'"'
+                echo which has been used to build perl. You may have to compile
+                echo your own copy of perl to make this work. Binary perls often
+                echo exhibit this problem
+                exit 1
+        else
+                AC_MSG_RESULT(found)
+        fi
+fi
+AC_SUBST(COMP_PERL)
+AC_SUBST(SO_EXT)
+
+dnl Check for Tcl.
+withval=""
+AC_ARG_WITH(tcllib,[  --with-tcllib=DIR       location of the tclConfig.sh])
+found=0
+AC_MSG_CHECKING(for tclConfig.sh in $withval)
+if test -f "$withval/tclConfig.sh" ; then
+       tcl_config=$withval/tclConfig.sh
+        found=1
+        AC_MSG_RESULT(yes)
+        break
+else
+        AC_MSG_RESULT(no)
+fi
+
+if test $found -eq 0 ; then
+        AC_MSG_WARN([tclConfig.sh not found - Tcl interface won't be built])
+else
+       . $tcl_config
+fi
+
+dnl Pass additional perl options when generating Makefile from Makefile.PL
+# Options to pass when configuring perl module
+AC_ARG_WITH(perl-options,
+[  --with-perl-options=[OPTIONS]  options to pass on command-line when
+                          generating Makefile from Makefile.PL],
+[PERL_MAKE_OPTIONS=$withval])
+AC_SUBST(PERL_MAKE_OPTIONS)
+
+AM_CONDITIONAL(COMP_TCL, test x$found = x1 )
+
+AC_SUBST(TCL_PREFIX)
+AC_SUBST(TCL_SHLIB_CFLAGS)
+AC_SUBST(TCL_SHLIB_LD)
+AC_SUBST(TCL_SHLIB_SUFFIX)
+AC_SUBST(TCL_PACKAGE_PATH)
+AC_SUBST(TCL_LD_SEARCH_FLAGS)
+
+dnl Check for the compiler and static/shared library creation.
+AC_PROG_CC
+AC_PROG_CPP
+
+dnl don't build a shared library ...
+dnl this can be changed when running configure
+AC_DISABLE_SHARED
+AC_PROG_LIBTOOL
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h fp_class.h malloc.h unistd.h ieeefp.h math.h sys/time.h sys/times.h sys/param.h sys/resource.h float.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+dnl Checks for libraries.
+AC_CHECK_FUNC(acos, , AC_CHECK_LIB(m, acos))
+
+dnl Check for nroff
+AC_PATH_PROGS(NROFF, gnroff nroff)
+AC_PATH_PROGS(TROFF, groff troff)
+
+dnl Does the compiler like -Wall and -pedantic?
+if test "x$GCC" = "xyes"; then
+  oCFLAGS=$CFLAGS
+  CFLAGS="$CFLAGS -Wall -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline"
+  AC_CACHE_CHECK(if we can use GCC-specific compiler options, rd_cv_gcc_opt,
+                [AC_TRY_COMPILE( , return 0 ,
+                    rd_cv_gcc_opt=yes,
+                    rd_cv_gcc_opt=no )
+               ]
+        )
+  if test $rd_cv_gcc_opt = no; then
+         CFLAGS=$oCFLAGS
+  fi
+fi
+
+dnl add pic flag in any case this makes sure all our code is relocatable
+CFLAGS="$CFLAGS "`grep pic_flag= libtool | sed -e 's/.*pic_flag=//' -e 's/"//g'`
+
+ZLIB_CFLAGS=$CFLAGS
+dnl it seems that hpux chockes on -fPIC for some reason
+case $target_os in
+*hpux*)
+        ZLIB_CFLAGS=`echo $CFLAGS|sed -e 's/-fPIC/-fpic/g'`
+;;
+esac
+AC_SUBST(ZLIB_CFLAGS)
+
+dnl Checks for library functions.
+AC_FUNC_STRFTIME
+AC_FUNC_VPRINTF
+
+dnl for each function found we get a definition in config.h 
+dnl of the form HAVE_FUNCTION
+
+AC_CHECK_FUNCS(strerror snprintf vsnprintf fpclass class fp_class isnan memmove strchr mktime getrusage gettimeofday)
+
+dnl HP-UX 11.00 does not have finite but does have isfinite as a macro
+AC_CHECK_FUNCS(fpclassify, ,
+  [AC_MSG_CHECKING(for fpclassify with <math.h>)
+    AC_TRY_LINK([#include <math.h>], [float f = 0.0; fpclassify(f)],
+      AC_MSG_RESULT(yes)
+      AC_DEFINE(HAVE_FPCLASSIFY), AC_MSG_RESULT(no))])
+AC_CHECK_FUNCS(finite, ,
+  [AC_CHECK_FUNCS(isfinite, ,
+    [AC_MSG_CHECKING(for isfinite with <math.h>)
+    AC_TRY_LINK([#include <math.h>], [float f = 0.0; isfinite(f)],
+      AC_MSG_RESULT(yes)
+      AC_DEFINE(HAVE_ISFINITE), AC_MSG_RESULT(no))])])
+AC_CHECK_FUNCS(isinf, ,
+  [AC_MSG_CHECKING(for isinf with <math.h>)
+    AC_TRY_LINK([#include <math.h>], [float f = 0.0; isinf(f)],
+      AC_MSG_RESULT(yes)
+      AC_DEFINE(HAVE_ISINF), AC_MSG_RESULT(no))])
+
+dnl what does realloc do if it gets called with a NULL pointer
+
+AC_CACHE_CHECK([if realloc can deal with NULL], rd_cv_null_realloc,
+[AC_TRY_RUN([#include <stdlib.h>
+             int main(void){
+              char *x = NULL;
+             x = realloc (x,10);
+             if (x==NULL) return 1;
+             return 0;
+             }],
+           [rd_cv_null_realloc=yes],[rd_cv_null_realloc=nope],:)])
+
+if test x"$rd_cv_null_realloc" = xnope; then
+AC_DEFINE(NO_NULL_REALLOC)
+fi
+
+dnl determine how to get IEEE math working
+dnl AC_IEEE(MESSAGE, set rd_cv_ieee_[var] variable, INCLUDES,
+dnl   FUNCTION-BODY, [ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]])
+
+AC_C_BIGENDIAN
+
+AC_DEFUN(AC_IEEE, 
+AC_MSG_CHECKING([if IEEE math works $1])
+AC_CACHE_VAL([rd_cv_ieee_$2],
+[AC_TRY_RUN([$3
+
+#if HAVE_MATH_H
+#  include <math.h>
+#endif
+
+#if HAVE_FLOAT_H
+#  include <float.h>  
+#endif
+
+#if HAVE_IEEEFP_H
+#  include <ieeefp.h>
+#endif
+
+#if HAVE_FP_CLASS_H
+#  include <fp_class.h>
+#endif
+
+/* Solaris */
+#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASS))
+#  define HAVE_ISINF 1
+#  define isinf(a) (fpclass(a) == FP_NINF || fpclass(a) == FP_PINF)
+#endif
+
+/* Digital UNIX */
+#if (! defined(HAVE_ISINF) && defined(HAVE_FP_CLASS) && defined(HAVE_FP_CLASS_H))
+#  define HAVE_ISINF 1
+#  define isinf(a) (fp_class(a) == FP_NEG_INF || fp_class(a) == FP_POS_INF)
+#endif 
+
+/* AIX */
+#if (! defined(HAVE_ISINF) && defined(HAVE_CLASS))
+#  define HAVE_ISINF 1
+#  define isinf(a) (class(a) == FP_MINUS_INF || class(a) == FP_PLUS_INF)
+#endif
+
+#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASSIFY) && defined(FP_PLUS_INF) && defined(FP_MINUS_INF))
+#  define HAVE_ISINF 1
+#  define isinf(a) (fpclassify(a) == FP_MINUS_INF || fpclassify(a) == FP_PLUS_INF)
+#endif
+
+#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASSIFY) && defined(FP_INFINITE))
+#  define HAVE_ISINF 1
+#  define isinf(a) (fpclassify(a) == FP_INFINITE)
+#endif
+
+#include <stdio.h>
+int main(void){
+    double nan,inf,c,zero;
+    $4;
+    /* some math to see if we get a floating point exception */
+    zero=sin(0.0); /* don't let the compiler optimize us away */
+    nan=0.0/zero; /* especially here */
+    inf=1.0/zero; /* and here. I want to know if it can do the magic */
+                 /* at run time without sig fpe */
+    c = inf + nan;
+    c = inf / nan;
+    if (! isnan(nan)) {printf ("not isnan(NaN) ... "); return 1;}
+    if (nan == nan) {printf ("nan == nan ... "); return 1;}
+    if (! isinf(inf)) {printf ("not isinf(oo) ... "); return 1;}
+    if (! isinf(-inf)) {printf ("not isinf(-oo) ... "); return 1;}
+    if (! inf > 0) {printf ("not inf > 0 ... "); return 1;}
+    if (! -inf < 0) {printf ("not -inf < 0 ... "); return 1;}
+    return 0;
+ }],
+
+rd_cv_ieee_$2=yes,
+rd_cv_ieee_$2=no,
+:)])
+dnl these we run regardles is cached or not
+if test x${rd_cv_ieee_$2} = "xyes"; then
+ AC_MSG_RESULT(yes)
+ $5
+else
+ AC_MSG_RESULT(no)
+ $6
+fi
+
+)
+
+_cflags=${CFLAGS}
+AC_IEEE([out of the box], works, , , ,
+  [CFLAGS="$_cflags -ieee"
+  AC_IEEE([with the -ieee switch], switch, , , ,
+    [CFLAGS="$_cflags -qfloat=nofold"
+    AC_IEEE([with the -qfloat=nofold switch], nofold, , , ,
+      [CFLAGS="$_cflags -w -qflttrap=enable:zerodivide"
+      AC_IEEE([with the -w -qflttrap=enable:zerodivide], flttrap, , , ,
+       [CFLAGS="$_cflags -mieee"
+       AC_IEEE([with the -mieee switch], mswitch, , , ,
+         [CFLAGS="$_cflags -q float=rndsngl"
+         AC_IEEE([with the -q float=rndsngl switch], qswitch, , , ,
+           [CFLAGS="$_cflags -OPT:IEEE_comparisons=ON"
+           AC_IEEE([with the -OPT:IEEE_comparisons=ON switch], ieeecmpswitch, , , ,
+             [CFLAGS=$_cflags
+             AC_IEEE([with fpsetmask(0)], mask,
+               [#include <floatingpoint.h>], [fpsetmask(0)],
+               [AC_DEFINE(MUST_DISABLE_FPMASK)
+              PERLFLAGS="CCFLAGS=-DMUST_DISABLE_FPMASK"],
+               [AC_IEEE([with signal(SIGFPE,SIG_IGN)], sigfpe,
+                 [#include <signal.h>], [signal(SIGFPE,SIG_IGN)],
+                 [AC_DEFINE(MUST_DISABLE_SIGFPE)
+                 PERLFLAGS="CCFLAGS=-DMUST_DISABLE_SIGFPE"],           
+                 AC_MSG_ERROR([
+Your Compiler does not do propper IEEE math ... Please find out how to
+make IEEE math work with your compiler and let me know (oetiker@ee.ethz.ch).
+Check config.log to see what went wrong ...
+]))])])])])])])])])
+
+
+AC_CONFIG_FILES([examples/shared-demo.pl                       \
+          examples/piped-demo.pl                       \
+          examples/stripes.pl                          \
+          examples/bigtops.pl                          \
+          examples/minmax.pl                           \
+          examples/cgi-demo.cgi                                \
+          examples/Makefile                            \
+          doc/Makefile                                 \
+          libraries/Makefile                            \
+          libraries/cgilib-0.4/Makefile                 \
+          libraries/libart_lgpl-2.3.7/Makefile         \
+          libraries/libpng-1.2.0/Makefile              \
+          libraries/zlib-1.1.3/Makefile                        \
+          libraries/freetype-2.0.5/Makefile            \
+          src/Makefile                                 \
+          bindings/Makefile                             \
+          bindings/tcl/Makefile                                \
+          Makefile])
+AC_CONFIG_COMMANDS([default],[[\
+          chmod +x examples/*.cgi examples/*.pl]],[[]])
+AC_OUTPUT
+
+AC_MSG_CHECKING(in)
+AC_MSG_RESULT(and out again)
+
+echo $ECHO_N "ordering CD from http://ee-staff.ethz.ch/~oetiker/wish $ECHO_C" 1>&6
+sleep 1
+echo $ECHO_N ".$ECHO_C" 1>&6
+sleep 1
+echo $ECHO_N ".$ECHO_C" 1>&6
+sleep 1
+echo $ECHO_N ".$ECHO_C" 1>&6
+sleep 1
+echo $ECHO_N ".$ECHO_C" 1>&6
+sleep 1
+AC_MSG_RESULT([ just kidding ;-)])
+echo
+echo "----------------------------------------------------------------"
+echo "Config is DONE!"
+echo
+echo "Type 'make' to compile the software and use 'make install' to "
+echo "install everything to: $prefix."
+echo
+echo "If you want to install the perl"
+echo "modules in site-perl, try 'make site-perl-install'."
+echo 
+echo "       ... that wishlist is NO JOKE. If you find RRDtool useful"
+echo "make me happy. Go to http://ee-staff.ethz.ch/~oetiker/wish and"
+echo "place an order."
+echo 
+echo "                               -- Tobi Oetiker <tobi@oetiker.ch>"
+echo "----------------------------------------------------------------"
diff --git a/configure.in b/configure.in
deleted file mode 100644 (file)
index d8a27e7..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-dnl RRDtool AutoConf script ... 
-dnl ---------------------------
-dnl
-dnl Created by Jeff Allen, Tobi Oetiker, Blair Zajac
-dnl
-dnl
-
-dnl make sure we are being executed in the right place
-AC_INIT(src/rrd_tool.c)
-
-dnl all our local stuff like install scripts and include files
-dnl is in there
-AC_CONFIG_AUX_DIR(config)
-
-dnl determine the type of system we are running on
-AC_CANONICAL_SYSTEM
-
-dnl tell automake the this script is for rrdtool
-AM_INIT_AUTOMAKE(rrdtool, 1.0.33)
-AC_SUBST(VERSION)
-
-dnl where we install our stuff ...
-AC_PREFIX_DEFAULT( /usr/local/rrdtool-1.0.33 )
-
-dnl tell automake which file to use as config header
-AM_CONFIG_HEADER(config/config.h)
-
-dnl Minimum Autoconf version required.
-AC_PREREQ(2.13)
-
-dnl Define library subdirectory names here.
-CGI_LIB_DIR=libraries/cgilib-0.4
-GD_LIB_DIR=libraries/gd1.3
-PNG_LIB_DIR=libraries/libpng-1.0.9
-ZLIB_LIB_DIR=libraries/zlib-1.1.3
-
-dnl substitute them in all the files listed in AC_OUTPUT
-AC_SUBST(CGI_LIB_DIR)
-AC_SUBST(GD_LIB_DIR)
-AC_SUBST(PNG_LIB_DIR)
-AC_SUBST(ZLIB_LIB_DIR)
-AC_SUBST(PERLFLAGS)
-
-dnl Check for Perl.
-AC_PATH_PROG(PERL, perl, no)
-if test "x$PERL" = "xno"; then
-       COMP_PERL=
-else
-       COMP_PERL="perl_piped perl_shared"
-       AC_MSG_CHECKING(for shared library extension)
-       SO_EXT=`$PERL -e 'use Config; if (defined $Config{so} and $Config{so} ne 'a') {print "$Config{so}\n"} else {print "so\n"};'`
-       AC_MSG_RESULT($SO_EXT)
-        AC_MSG_CHECKING(for the C compiler perl wants to use to build its modules)
-        PROBLEMCC=`$PERL -e 'use Config; map {if (-x "$_/$Config{cc}"){exit 0}} split /:/, $ENV{PATH};print $Config{cc}'`
-        if test x$PROBLEMCC != x; then
-                AC_MSG_RESULT(no)
-                echo Could not find the Compiler: '"'$PROBLEMCC'"'
-                echo which has been used to build perl. You may have to compile
-                echo your own copy of perl to make this work. Binary perls often
-                echo exhibit this problem
-                exit 1
-        else
-                AC_MSG_RESULT(found)
-        fi
-fi
-AC_SUBST(COMP_PERL)
-AC_SUBST(SO_EXT)
-
-dnl Check for Tcl.
-withval=""
-AC_ARG_WITH(tcllib,[  --with-tcllib=DIR       location of the tclConfig.sh])
-found=0
-AC_MSG_CHECKING(for tclConfig.sh in $withval)
-if test -f "$withval/tclConfig.sh" ; then
-       tcl_config=$withval/tclConfig.sh
-        found=1
-        AC_MSG_RESULT(yes)
-        break
-else
-        AC_MSG_RESULT(no)
-fi
-
-if test $found -eq 0 ; then
-        AC_MSG_WARN([tclConfig.sh not found - Tcl interface won't be built])
-else
-       . $tcl_config
-fi
-
-dnl Pass additional perl options when generating Makefile from Makefile.PL
-# Options to pass when configuring perl module
-AC_ARG_WITH(perl-options,
-[  --with-perl-options=[OPTIONS]  options to pass on command-line when
-                          generating Makefile from Makefile.PL],
-[PERL_MAKE_OPTIONS=$withval])
-AC_SUBST(PERL_MAKE_OPTIONS)
-
-AM_CONDITIONAL(COMP_TCL, test x$found = x1 )
-
-AC_SUBST(TCL_PREFIX)
-AC_SUBST(TCL_SHLIB_CFLAGS)
-AC_SUBST(TCL_SHLIB_LD)
-AC_SUBST(TCL_SHLIB_SUFFIX)
-AC_SUBST(TCL_PACKAGE_PATH)
-AC_SUBST(TCL_LD_SEARCH_FLAGS)
-
-dnl Check for the compiler and static/shared library creation.
-AC_PROG_CC
-AC_PROG_CPP
-dnl RRD_ACLOCAL_FIND_LIBTOOL
-
-dnl don't build a shared library ...
-dnl this can be changed when running configure
-AC_DISABLE_SHARED
-
-AM_PROG_LIBTOOL
-
-dnl Checks for header files.
-AC_HEADER_STDC
-AC_CHECK_HEADERS(fcntl.h fp_class.h malloc.h unistd.h ieeefp.h math.h sys/time.h sys/times.h sys/param.h sys/resource.h float.h)
-
-dnl Checks for typedefs, structures, and compiler characteristics.
-AC_C_CONST
-AC_HEADER_TIME
-AC_STRUCT_TM
-
-dnl Checks for libraries.
-AC_CHECK_FUNC(acos, , AC_CHECK_LIB(m, acos))
-
-dnl Check for nroff
-AC_PATH_PROGS(NROFF, gnroff nroff)
-AC_PATH_PROGS(TROFF, groff troff)
-
-dnl Does the compiler like -Wall and -pedantic?
-if test "x$GCC" = "xyes"; then
-  oCFLAGS=$CFLAGS
-  CFLAGS="$CFLAGS -Wall -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline"
-  AC_CACHE_CHECK(if we can use GCC-specific compiler options, rd_cv_gcc_opt,
-                [AC_TRY_COMPILE( , return 0 ,
-                    rd_cv_gcc_opt=yes,
-                    rd_cv_gcc_opt=no )
-               ]
-        )
-  if test $rd_cv_gcc_opt = no; then
-         CFLAGS=$oCFLAGS
-  fi
-fi
-
-dnl add pic flag in any case this makes sure all our code is relocatable
-CFLAGS="$CFLAGS "`grep pic_flag= libtool | sed -e 's/.*pic_flag=//' -e 's/"//g'`
-
-ZLIB_CFLAGS=$CFLAGS
-dnl it seems that hpux chockes on -fPIC for some reason
-case $target_os in
-*hpux*)
-        ZLIB_CFLAGS=`echo $CFLAGS|sed -e 's/-fPIC/-fpic/g'`
-;;
-esac
-AC_SUBST(ZLIB_CFLAGS)
-
-dnl Checks for library functions.
-AC_FUNC_STRFTIME
-AC_FUNC_VPRINTF
-
-dnl for each function found we get a definition in config.h 
-dnl of the form HAVE_FUNCTION
-
-AC_CHECK_FUNCS(strerror snprintf vsnprintf fpclass class fp_class isnan memmove strchr mktime getrusage gettimeofday)
-
-dnl HP-UX 11.00 does not have finite but does have isfinite as a macro
-AC_CHECK_FUNCS(fpclassify, ,
-  [AC_MSG_CHECKING(for fpclassify with <math.h>)
-    AC_TRY_LINK([#include <math.h>], [float f = 0.0; fpclassify(f)],
-      AC_MSG_RESULT(yes)
-      AC_DEFINE(HAVE_FPCLASSIFY), AC_MSG_RESULT(no))])
-AC_CHECK_FUNCS(finite, ,
-  [AC_CHECK_FUNCS(isfinite, ,
-    [AC_MSG_CHECKING(for isfinite with <math.h>)
-    AC_TRY_LINK([#include <math.h>], [float f = 0.0; isfinite(f)],
-      AC_MSG_RESULT(yes)
-      AC_DEFINE(HAVE_ISFINITE), AC_MSG_RESULT(no))])])
-AC_CHECK_FUNCS(isinf, ,
-  [AC_MSG_CHECKING(for isinf with <math.h>)
-    AC_TRY_LINK([#include <math.h>], [float f = 0.0; isinf(f)],
-      AC_MSG_RESULT(yes)
-      AC_DEFINE(HAVE_ISINF), AC_MSG_RESULT(no))])
-
-dnl what does realloc do if it gets called with a NULL pointer
-
-AC_CACHE_CHECK([if realloc can deal with NULL], rd_cv_null_realloc,
-[AC_TRY_RUN([#include <stdlib.h>
-             int main(void){
-              char *x = NULL;
-             x = realloc (x,10);
-             if (x==NULL) return 1;
-             return 0;
-             }],
-           [rd_cv_null_realloc=yes],[rd_cv_null_realloc=nope],:)])
-
-if test x"$rd_cv_null_realloc" = xnope; then
-AC_DEFINE(NO_NULL_REALLOC)
-fi
-
-dnl determine how to get IEEE math working
-dnl AC_IEEE(MESSAGE, set rd_cv_ieee_[var] variable, INCLUDES,
-dnl   FUNCTION-BODY, [ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]])
-
-AC_DEFUN(AC_IEEE, 
-AC_MSG_CHECKING([if IEEE math works $1])
-AC_CACHE_VAL([rd_cv_ieee_$2],
-[AC_TRY_RUN([$3
-
-#if HAVE_MATH_H
-#  include <math.h>
-#endif
-
-#if HAVE_FLOAT_H
-#  include <float.h>  
-#endif
-
-#if HAVE_IEEEFP_H
-#  include <ieeefp.h>
-#endif
-
-#if HAVE_FP_CLASS_H
-#  include <fp_class.h>
-#endif
-
-/* Solaris */
-#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASS))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fpclass(a) == FP_NINF || fpclass(a) == FP_PINF)
-#endif
-
-/* Digital UNIX */
-#if (! defined(HAVE_ISINF) && defined(HAVE_FP_CLASS) && defined(HAVE_FP_CLASS_H))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fp_class(a) == FP_NEG_INF || fp_class(a) == FP_POS_INF)
-#endif 
-
-/* AIX */
-#if (! defined(HAVE_ISINF) && defined(HAVE_CLASS))
-#  define HAVE_ISINF 1
-#  define isinf(a) (class(a) == FP_MINUS_INF || class(a) == FP_PLUS_INF)
-#endif
-
-#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASSIFY) && defined(FP_PLUS_INF) && defined(FP_MINUS_INF))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fpclassify(a) == FP_MINUS_INF || fpclassify(a) == FP_PLUS_INF)
-#endif
-
-#if (! defined(HAVE_ISINF) && defined(HAVE_FPCLASSIFY) && defined(FP_INFINITE))
-#  define HAVE_ISINF 1
-#  define isinf(a) (fpclassify(a) == FP_INFINITE)
-#endif
-
-#include <stdio.h>
-int main(void){
-    double nan,inf,c,zero;
-    $4;
-    /* some math to see if we get a floating point exception */
-    zero=sin(0.0); /* don't let the compiler optimize us away */
-    nan=0.0/zero; /* especially here */
-    inf=1.0/zero; /* and here. I want to know if it can do the magic */
-                 /* at run time without sig fpe */
-    c = inf + nan;
-    c = inf / nan;
-    if (! isnan(nan)) {printf ("not isnan(NaN) ... "); return 1;}
-    if (nan == nan) {printf ("nan == nan ... "); return 1;}
-    if (! isinf(inf)) {printf ("not isinf(oo) ... "); return 1;}
-    if (! isinf(-inf)) {printf ("not isinf(-oo) ... "); return 1;}
-    if (! inf > 0) {printf ("not inf > 0 ... "); return 1;}
-    if (! -inf < 0) {printf ("not -inf < 0 ... "); return 1;}
-    return 0;
- }],
-
-rd_cv_ieee_$2=yes,
-rd_cv_ieee_$2=no,
-:)])
-dnl these we run regardles is cached or not
-if test x${rd_cv_ieee_$2} = "xyes"; then
- AC_MSG_RESULT(yes)
- $5
-else
- AC_MSG_RESULT(no)
- $6
-fi
-
-)
-
-_cflags=${CFLAGS}
-AC_IEEE([out of the box], works, , , ,
-  [CFLAGS="$_cflags -ieee"
-  AC_IEEE([with the -ieee switch], switch, , , ,
-    [CFLAGS="$_cflags -qfloat=nofold"
-    AC_IEEE([with the -qfloat=nofold switch], nofold, , , ,
-      [CFLAGS="$_cflags -w -qflttrap=enable:zerodivide"
-      AC_IEEE([with the -w -qflttrap=enable:zerodivide], flttrap, , , ,
-       [CFLAGS="$_cflags -mieee"
-       AC_IEEE([with the -mieee switch], mswitch, , , ,
-         [CFLAGS="$_cflags -q float=rndsngl"
-         AC_IEEE([with the -q float=rndsngl switch], qswitch, , , ,
-           [CFLAGS="$_cflags -OPT:IEEE_comparisons=ON"
-           AC_IEEE([with the -OPT:IEEE_comparisons=ON switch], ieeecmpswitch, , , ,
-             [CFLAGS=$_cflags
-             AC_IEEE([with fpsetmask(0)], mask,
-               [#include <floatingpoint.h>], [fpsetmask(0)],
-               [AC_DEFINE(MUST_DISABLE_FPMASK)
-              PERLFLAGS="CCFLAGS=-DMUST_DISABLE_FPMASK"],
-               [AC_IEEE([with signal(SIGFPE,SIG_IGN)], sigfpe,
-                 [#include <signal.h>], [signal(SIGFPE,SIG_IGN)],
-                 [AC_DEFINE(MUST_DISABLE_SIGFPE)
-                 PERLFLAGS="CCFLAGS=-DMUST_DISABLE_SIGFPE"],           
-                 AC_MSG_ERROR([
-Your Compiler does not do propper IEEE math ... Please find out how to
-make IEEE math work with your compiler and let me know (oetiker@ee.ethz.ch).
-Check config.log to see what went wrong ...
-]))])])])])])])])])
-
-
-AC_OUTPUT(examples/shared-demo.pl                      \
-          examples/piped-demo.pl                       \
-          examples/stripes.pl                          \
-          examples/bigtops.pl                          \
-          examples/minmax.pl                           \
-          examples/cgi-demo.cgi                                \
-          examples/Makefile                            \
-          doc/Makefile                                 \
-          libraries/Makefile                            \
-          libraries/cgilib-0.4/Makefile                 \
-          libraries/gd1.3/Makefile                     \
-          libraries/libpng-1.0.9/Makefile              \
-          libraries/zlib-1.1.3/Makefile                        \
-          src/Makefile                                 \
-          bindings/Makefile                             \
-          bindings/tcl/Makefile                                \
-          Makefile,                                    \
-          [chmod +x examples/*.cgi examples/*.pl])
-
-AC_MSG_CHECKING(in)
-AC_MSG_RESULT(and out again)
-
-echo $ac_n "ordering CD from http://ee-staff.ethz.ch/~oetiker/wish $ac_c" 1>&6
-sleep 1
-echo $ac_n ".$ac_c" 1>&6
-sleep 1
-echo $ac_n ".$ac_c" 1>&6
-sleep 1
-echo $ac_n ".$ac_c" 1>&6
-sleep 1
-echo $ac_n ".$ac_c" 1>&6
-sleep 1
-AC_MSG_RESULT([ just kidding ;-)])
-echo
-echo "----------------------------------------------------------------"
-echo "Config is DONE!"
-echo
-echo "Type 'make' to compile the software and use 'make install' to "
-echo "install everything to: $prefix."
-echo
-echo "If you want to install the perl"
-echo "modules in site-perl, try 'make site-perl-install'."
-echo 
-echo "       ... that wishlist is NO JOKE. If you find RRDtool useful"
-echo "make me happy. Go to http://ee-staff.ethz.ch/~oetiker/wish and"
-echo "place an order."
-echo 
-echo "                               -- Tobi Oetiker <tobi@oetiker.ch>"
-echo "----------------------------------------------------------------"
index 3f9bda8..980380e 100644 (file)
@@ -269,7 +269,7 @@ would look like this:
 
     --imginfo '<IMG SRC="/img/%s" WIDTH="%lu" HEIGHT="%lu" ALT="Demo">'
 
-B<[-c|--color I<COLORTAG#rrggbb>]>
+B<[-c|--color I<COLORTAGBB<#>I<rrggbb>B<[>I<aa>B<<]>
 
 Override the default colors for the standard elements of the graph.
 The I<COLORTAG> is one of C<BACK> ground, C<CANVAS>, C<SHADEA> for the
@@ -281,7 +281,24 @@ You may set this option several times to alter multiple defaults.
 
 A green arrow is made by: C<--color ARROW:00FF00>
 
-B<[-a|--imgformat C<GIF>|C<PNG>]>
+B<--zoom> I<factor>
+
+Zoom the graphics by the given amount ... The factor must be > 0
+
+B<[-n|--font I<FONTTAG>B<:>I<size>B<:>I<font>
+
+Lets you customize which font to use for the various text elements on the
+rrd graphs. C<DEFAULT> sets the default value for all elements C<TITLE>,
+C<AXIS> for the axis labels, C<UNIT> for the vertical unit label, C<LEGEND>
+for the graph legend.
+
+Use Times for the title: C<--font TITLE:13:/usr/lib/fonts/times.ttf>
+
+B<[-a|--imgformat C<PNG>]>
+
+At present only PNG is supported, but C<EPS>, C<SVG> or even C<FLASH> should
+not be all that difficult to add.
+
 B<[-i|--interlaced]>
 
 The default is to generate a non-interlaced GIF image. It is recommended
index 2120d0f..46a5152 100644 (file)
@@ -6,22 +6,22 @@ I<(to be) Depriciated commands>
 
 [B<PRINT:>I<vname>B<:>I<CF>B<:>I<format>]
 [B<GPRINT:>I<vname>B<:>I<CF>B<:>I<format>]
-[B<HRULE:>I<value>B<#>I<rrggbb>[B<:>I<legend>]]
-[B<STACK:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]]
+[B<HRULE:>I<value>B<#>I<rrggbbaa>[B<:>I<legend>]]
+[B<STACK:>I<vname>[B<#>I<rrggbbaa>[B<:>I<legend>]]]
 
 I<(soon) available commands>
 
 [B<PRINT:>I<vname>B<:>I<format>]
 [B<GPRINT:>I<vname>B<:>I<format>]
 [B<COMMENT:>I<text>]
-[B<VRULE:>I<vname>B<#>I<rrggbb>[B<:>I<legend>]]
-[B<LINE>{B<1>|B<2>|B<3>}B<:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]][B<:STACK>]
-[B<AREA:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]][B<:STACK>]
+[B<VRULE:>I<vname>B<#>I<rrggbbaa>[B<:>I<legend>]]
+[B<LINE>{I<width>}B<:>I<vname>[B<#>I<rrggbbaa>[B<:>I<legend>]]][B<:STACK>]
+[B<AREA:>I<vname>[B<#>I<rrggbbaa>[B<:>I<legend>]]][B<:STACK>]
 
 I<to be implemented commands>
 
 [B<SHIFT:>I<vname>]
-[B<PART:>I<vname>B<#>I<rrggbb>[B<:>I<legend>]]
+[B<PART:>I<vname>B<#>I<rrggbbaa>[B<:>I<legend>]]
 
 =head1 DESCRIPTION
 
@@ -142,7 +142,7 @@ B<COMMENT:>I<text>
 
 Text is printed literally in the legend section of the graph
 
-B<HRULE:>I<value>B<#>I<rrggbb>[B<:>I<legend>]
+B<HRULE:>I<value>B<#>I<rrggbbaa>[B<:>I<legend>]
 
 Draw an horizontal line at I<value>. Its color is composed from three
 hexadecimal numbers specifying the color components (00 is off, FF is
@@ -150,7 +150,7 @@ maximum) red, green and blue.  Optionally a legend box and string is
 printed in the legend section. I<value> can be a variable from a B<VDEF>.
 It is an error to use I<vname>s from B<DEF> or B<CDEF> here.
 
-B<VRULE:>I<time>B<#>I<rrggbb>[B<:>I<legend>]
+B<VRULE:>I<time>B<#>I<rrggbbaa>[B<:>I<legend>]
 
 Draw a vertical line at I<time>.  Its color is composed from three
 hexadecimal numbers specifying the color components (00 is off, FF is
@@ -158,7 +158,7 @@ maximum) red, green and blue.  Optionally a legend box and string is
 printed in the legend section. I<time> may be a number or a variable
 from a B<VDEF>. It is an error to use I<vname>s from B<DEF> or B<CDEF> here.
 
-B<LINE>{B<1>|B<2>|B<3>}B<:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]][B<:STACK>]
+B<LINE>{I<width>}B<:>I<vname>[B<#>I<rrggbbaa>[B<:>I<legend>]][B<:STACK>]
 
 Draw a line of the specified width into the graph. If the color
 is not specified, the drawing is done 'blind'.  This is useful when
@@ -169,12 +169,12 @@ B<CDEF>.  If the optional B<STACK> modifier is used, this line is
 stacked on top of the previous element which can be a B<LINEx> or
 an B<AREA>
 
-B<AREA:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]][B<:STACK>]
+B<AREA:>I<vname>[B<#>I<rrggbbaa>[B<:>I<legend>]][B<:STACK>]
 
 See B<LINEx>, however the area between the x-axis and the line will
 also be filled.
 
-B<STACK:>I<vname>[B<#>I<rrggbb>[B<:>I<legend>]]
+B<STACK:>I<vname>[B<#>I<rrggbbaa>[B<:>I<legend>]]
 
 I<Depriciated.  Use the B<STACK> modifiers on the other commands.>
 I<Note: the comments on stacking are still valid...>
@@ -209,7 +209,7 @@ B<PART> command, the canvas is extended to make room for a chart
 used for the pie chart). The size of the canvas is determined by
 the lesser of L<width and height|rrdgraph/item_Size>.
 
-B<PART:>I<vname>B<#>I<rrggbb>[B<:>I<legend>]
+B<PART:>I<vname>B<#>I<rrggbbaa>[B<:>I<legend>]
 
 Draw a part of pie. Pie parts will be concatenated, the first one
 will start at the top and parts will be created clockwise.
index f8304dd..46ef6da 100755 (executable)
@@ -1,7 +1,7 @@
 #! @PERL@
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-shared/blib/lib ../libraries/perl-shared/blib/arch );
+use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch );
 # this is for after install
 use lib qw( @prefix@/lib/perl ../lib/perl );
 use RRDs;
index c9c7a54..24ec6af 100755 (executable)
@@ -1,9 +1,9 @@
-#! /usr/sepp/bin/perl
+#! /usr/bin/perl
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-shared/blib/lib ../libraries/perl-shared/blib/arch );
+use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch );
 # this is for after install
-use lib qw( /usr/local/rrdtool-1.0.33/lib/perl ../lib/perl );
+use lib qw( /usr/local/rrdtool-1.1.0/lib/perl ../lib/perl );
 
 use RRDs;
 my $start=time;
index ed93b7a..9bc39db 100755 (executable)
@@ -1,7 +1,7 @@
 #! @PERL@
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-shared/blib/lib ../libraries/perl-shared/blib/arch );
+use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch );
 # this is for after install
 use lib qw( @prefix@/lib/perl ../lib/perl );
 
index 436c0a8..5ab4f49 100755 (executable)
@@ -1,4 +1,4 @@
-#! /usr/local/rrdtool-1.0.33/bin/rrdcgi 
+#! /usr/local/rrdtool-1.1.0/bin/rrdcgi 
 
 <HTML>
 <HEAD>
index e4f1690..573d547 100755 (executable)
@@ -1,9 +1,9 @@
-#! /usr/sepp/bin/perl
+#! /usr/bin/perl
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-shared/blib/lib ../libraries/perl-shared/blib/arch );
+use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch );
 # this is for after install
-use lib qw( /usr/local/rrdtool-1.0.33/lib/perl ../lib/perl );
+use lib qw( /usr/local/rrdtool-1.1.0/lib/perl ../lib/perl );
 
 use RRDs;
 my $start=time;
@@ -35,6 +35,7 @@ RRDs::graph "$name.png",
   "--end", "start+1d",
   "--lower-limit=0",
   "--interlace", 
+  "--zoom=2.5",
   "--imgformat","PNG",
   "--width=450",
   "DEF:a=$rrd:a:AVERAGE",
index 87973d2..14faecb 100755 (executable)
@@ -1,7 +1,7 @@
 #! @PERL@
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-shared/blib/lib ../libraries/perl-shared/blib/arch );
+use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch );
 # this is for after install
 use lib qw( @prefix@/lib/perl ../lib/perl );
 
index c64992d..34a3ff8 100755 (executable)
@@ -1,10 +1,10 @@
-#! /usr/sepp/bin/perl 
+#! /usr/bin/perl 
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-piped/blib/lib  ../lib/perl );
+use lib qw( ../bindings/perl-piped/blib/lib  ../lib/perl );
 
 #makes programm work AFTER install 
-use lib qw( /usr/local/rrdtool-1.0.33/lib/perl );
+use lib qw( /usr/local/rrdtool-1.1.0/lib/perl );
 
 use RRDp;
 
@@ -20,8 +20,8 @@ $GIF = "piped-demo.gif";
 $PNG = "piped-demo.png";
 
 # some magic to find the correct rrdtol executable
-if ( -x "/usr/local/rrdtool-1.0.33/bin/rrdtool") {
-   RRDp::start "/usr/local/rrdtool-1.0.33/bin/rrdtool";
+if ( -x "/usr/local/rrdtool-1.1.0/bin/rrdtool") {
+   RRDp::start "/usr/local/rrdtool-1.1.0/bin/rrdtool";
 } elsif ( -x "../bin/rrdtool") {
    RRDp::start "../bin/rrdtool";
 } else {
index 792ab6d..6021f5d 100755 (executable)
@@ -1,7 +1,7 @@
 #! @PERL@ 
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-piped/blib/lib  ../lib/perl );
+use lib qw( ../bindings/perl-piped/blib/lib  ../lib/perl );
 
 #makes programm work AFTER install 
 use lib qw( @prefix@/lib/perl );
index b74e54f..0a8bb21 100755 (executable)
@@ -1,4 +1,4 @@
-#! /usr/sepp/bin/perl 
+#! /usr/bin/perl 
 
 
 END {
@@ -15,10 +15,10 @@ sub ok
 }
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-shared/blib/lib ../libraries/perl-shared/blib/arch );
+use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch );
 
 #makes programm work AFTER install
-use lib qw( /usr/local/rrdtool-1.0.33/lib/perl ../lib/perl );
+use lib qw( /usr/local/rrdtool-1.1.0/lib/perl ../lib/perl );
 
 use strict;
 use vars qw(@ISA $loaded);
index 28bbb20..fafb4e0 100755 (executable)
@@ -15,7 +15,7 @@ sub ok
 }
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-shared/blib/lib ../libraries/perl-shared/blib/arch );
+use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch );
 
 #makes programm work AFTER install
 use lib qw( @prefix@/lib/perl ../lib/perl );
index f595961..5ee8f46 100755 (executable)
@@ -1,10 +1,10 @@
-#! /usr/sepp/bin/perl
+#! /usr/bin/perl
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-shared/blib/lib ../libraries/perl-shared/blib/arch );
+use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch );
 
 #makes programm work AFTER install
-use lib qw( /usr/local/rrdtool-1.0.33/lib/perl ../lib/perl );
+use lib qw( /usr/local/rrdtool-1.1.0/lib/perl ../lib/perl );
 
 use strict;
 use vars qw(@ISA $loaded);
index e4babd4..c19695a 100755 (executable)
@@ -1,7 +1,7 @@
 #! @PERL@
 
 #makes things work when run without install
-use lib qw( ../libraries/perl-shared/blib/lib ../libraries/perl-shared/blib/arch );
+use lib qw( ../bindings/perl-shared/blib/lib ../bindings/perl-shared/blib/arch );
 
 #makes programm work AFTER install
 use lib qw( @prefix@/lib/perl ../lib/perl );
index 444f9aa..3ca8123 100644 (file)
@@ -1,2 +1 @@
-SUBDIRS =  cgilib-0.4 gd1.3 libpng-1.0.9 zlib-1.1.3
-
+SUBDIRS =  cgilib-0.4 zlib-1.1.3  libpng-1.2.0 libart_lgpl-2.3.7 freetype-2.0.5
index 1cc8da4..e4715bf 100644 (file)
@@ -1,6 +1,5 @@
-noinst_LTLIBRARIES    = librrd_cgi.la
+noinst_LTLIBRARIES  = librrd_cgi.la
 
 librrd_cgi_la_SOURCES = cgi.c cgi.h
 
-EXTRA_DIST=    *.[1-9] *.dsp *.dsw readme cgitest.c jumpto.c
-
+EXTRA_DIST= *.[1-9] *.dsp *.dsw readme cgitest.c jumpto.c
diff --git a/libraries/freetype-2.0.5-import.txt b/libraries/freetype-2.0.5-import.txt
new file mode 100644 (file)
index 0000000..4cee31f
--- /dev/null
@@ -0,0 +1,7 @@
+wget http://prdownloads.sourceforge.net/freetype/freetype-2.0.5.tar.gz
+gtar zxvf freetype-2.0.5.tar.gz
+mv freetype-2.0.5 f
+mkdir freetype-2.0.5
+cp f/src/*/*.c freetype-2.0.5
+cp -r f/include freetype-2.0.5
+cp f/src/*/*.h freetype-2.0.5/include
diff --git a/libraries/freetype-2.0.5/Makefile.am b/libraries/freetype-2.0.5/Makefile.am
new file mode 100644 (file)
index 0000000..1f2def1
--- /dev/null
@@ -0,0 +1,25 @@
+## Process this file with automake to produce Makefile.in
+# preparation
+# cp src/*/*.c .
+# cp src/*/*.h include
+
+noinst_LTLIBRARIES  = librrd_freetype.la
+
+
+librrd_freetype_la_SOURCES = \
+       ahangles.c      ahglyph.c       ahglobal.c      ahhint.c        ahmodule.c\
+       cff.c ftglyph.c winfnt.c\
+       ftcalc.c        fttrigon.c      ftobjs.c        ftstream.c      ftlist.c\
+       ftoutln.c       ftnames.c       ftextend.c      ftlru.c         ftcmanag.c\
+       ftcglyph.c      ftcchunk.c      ftcimage.c      ftcsbits.c      pcfutil.c\
+       pcfread.c       pcfdriver.c     psobjs.c        psauxmod.c      t1decode.c\
+       psmodule.c      ftraster.c      ftrend1.c       ttload.c        ttcmap.c\
+       sfobjs.c        sfdriver.c      ttsbit.c        ttpost.c        ftgrays.c\
+       ftsmooth.c      ttdriver.c      ttpload.c       ttgload.c       ttobjs.c\
+       ttinterp.c      t1parse.c       t1load.c        t1objs.c        t1driver.c\
+       t1gload.c       t1afm.c         cidparse.c      cidload.c       cidobjs.c\
+       cidriver.c      cidgload.c      ftinit.c        ftsystem.c
+
+EXTRA_DIST= README ChangeLog cffdrivr.c      cffparse.c      cffload.c       cffobjs.c       cffgload.c
+
+INCLUDES = -Iinclude
diff --git a/libraries/freetype-2.0.5/README b/libraries/freetype-2.0.5/README
new file mode 100644 (file)
index 0000000..b66b68b
--- /dev/null
@@ -0,0 +1,6 @@
+* this is a mutilated copy of free type ... please get the original from 
+
+    ftp://ftp.freetype.org/pub/freetype2/ftdocs-2.0.5.tar.bz2
+    ftp://ftp.freetype.org/pub/freetype2/ftdocs-2.0.5.tar.gz
+    ftp://ftp.freetype.org/pub/freetype2/ftdoc205.zip
+
diff --git a/libraries/freetype-2.0.5/ahangles.c b/libraries/freetype-2.0.5/ahangles.c
new file mode 100644 (file)
index 0000000..02da850
--- /dev/null
@@ -0,0 +1,130 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahangles.h                                                             */
+/*                                                                         */
+/*    A routine used to compute vector angles with limited accuracy        */
+/*    and very high speed (body).                                          */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "ahangles.h"
+
+
+  /* the following table has been automatically generated with */
+  /* the `mather.py' Python script                             */
+
+  const AH_Angle  ah_arctan[1L << AH_ATAN_BITS] =
+  {
+     0,  0,  1,  1,  1,  2,  2,  2,
+     3,  3,  3,  3,  4,  4,  4,  5,
+     5,  5,  6,  6,  6,  7,  7,  7,
+     8,  8,  8,  9,  9,  9, 10, 10,
+    10, 10, 11, 11, 11, 12, 12, 12,
+    13, 13, 13, 14, 14, 14, 14, 15,
+    15, 15, 16, 16, 16, 17, 17, 17,
+    18, 18, 18, 18, 19, 19, 19, 20,
+    20, 20, 21, 21, 21, 21, 22, 22,
+    22, 23, 23, 23, 24, 24, 24, 24,
+    25, 25, 25, 26, 26, 26, 26, 27,
+    27, 27, 28, 28, 28, 28, 29, 29,
+    29, 30, 30, 30, 30, 31, 31, 31,
+    31, 32, 32, 32, 33, 33, 33, 33,
+    34, 34, 34, 34, 35, 35, 35, 35,
+    36, 36, 36, 36, 37, 37, 37, 38,
+    38, 38, 38, 39, 39, 39, 39, 40,
+    40, 40, 40, 41, 41, 41, 41, 42,
+    42, 42, 42, 42, 43, 43, 43, 43,
+    44, 44, 44, 44, 45, 45, 45, 45,
+    46, 46, 46, 46, 46, 47, 47, 47,
+    47, 48, 48, 48, 48, 48, 49, 49,
+    49, 49, 50, 50, 50, 50, 50, 51,
+    51, 51, 51, 51, 52, 52, 52, 52,
+    52, 53, 53, 53, 53, 53, 54, 54,
+    54, 54, 54, 55, 55, 55, 55, 55,
+    56, 56, 56, 56, 56, 57, 57, 57,
+    57, 57, 57, 58, 58, 58, 58, 58,
+    59, 59, 59, 59, 59, 59, 60, 60,
+    60, 60, 60, 61, 61, 61, 61, 61,
+    61, 62, 62, 62, 62, 62, 62, 63,
+    63, 63, 63, 63, 63, 64, 64, 64
+  };
+
+
+  FT_LOCAL_DEF AH_Angle
+  ah_angle( FT_Vector*  v )
+  {
+    FT_Pos    dx, dy;
+    AH_Angle  angle;
+
+
+    dx = v->x;
+    dy = v->y;
+
+    /* check trivial cases */
+    if ( dy == 0 )
+    {
+      angle = 0;
+      if ( dx < 0 )
+        angle = AH_PI;
+      return angle;
+    }
+    else if ( dx == 0 )
+    {
+      angle = AH_HALF_PI;
+      if ( dy < 0 )
+        angle = -AH_HALF_PI;
+      return angle;
+    }
+
+    angle = 0;
+    if ( dx < 0 )
+    {
+      dx = -v->x;
+      dy = -v->y;
+      angle = AH_PI;
+    }
+
+    if ( dy < 0 )
+    {
+      FT_Pos  tmp;
+
+
+      tmp = dx;
+      dx  = -dy;
+      dy  = tmp;
+      angle -= AH_HALF_PI;
+    }
+
+    if ( dx == 0 && dy == 0 )
+      return 0;
+
+    if ( dx == dy )
+      angle += AH_PI / 4;
+    else if ( dx > dy )
+      angle += ah_arctan[FT_DivFix( dy, dx ) >> ( 16 - AH_ATAN_BITS )];
+    else
+      angle += AH_HALF_PI -
+               ah_arctan[FT_DivFix( dx, dy ) >> ( 16 - AH_ATAN_BITS )];
+
+    if ( angle > AH_PI )
+      angle -= AH_2PI;
+
+    return angle;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ahglobal.c b/libraries/freetype-2.0.5/ahglobal.c
new file mode 100644 (file)
index 0000000..4e648ac
--- /dev/null
@@ -0,0 +1,395 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahglobal.c                                                             */
+/*                                                                         */
+/*    Routines used to compute global metrics automatically (body).        */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include "ahglobal.h"
+#include "ahglyph.h"
+
+
+#define MAX_TEST_CHARACTERS  12
+
+  static
+  const char*  blue_chars[ah_blue_max] =
+  {
+    "THEZOCQS",
+    "HEZLOCUS",
+    "xzroesc",
+    "xzroesc",
+    "pqgjy"
+  };
+
+
+  /* simple insertion sort */
+  static void
+  sort_values( FT_Int   count,
+               FT_Pos*  table )
+  {
+    FT_Int  i, j, swap;
+
+
+    for ( i = 1; i < count; i++ )
+    {
+      for ( j = i; j > 0; j-- )
+      {
+        if ( table[j] > table[j - 1] )
+          break;
+
+        swap         = table[j];
+        table[j]     = table[j - 1];
+        table[j - 1] = swap;
+      }
+    }
+  }
+
+
+  static FT_Error
+  ah_hinter_compute_blues( AH_Hinter*  hinter )
+  {
+    AH_Blue       blue;
+    AH_Globals*   globals = &hinter->globals->design;
+    FT_Pos        flats [MAX_TEST_CHARACTERS];
+    FT_Pos        rounds[MAX_TEST_CHARACTERS];
+    FT_Int        num_flats;
+    FT_Int        num_rounds;
+
+    FT_Face       face;
+    FT_GlyphSlot  glyph;
+    FT_Error      error;
+    FT_CharMap    charmap;
+
+
+    face  = hinter->face;
+    glyph = face->glyph;
+
+    /* save current charmap */
+    charmap = face->charmap;
+
+    /* do we have a Unicode charmap in there? */
+    error = FT_Select_Charmap( face, ft_encoding_unicode );
+    if ( error )
+      goto Exit;
+
+    /* we compute the blues simply by loading each character from the */
+    /* 'blue_chars[blues]' string, then compute its top-most and      */
+    /* bottom-most points                                             */
+
+    AH_LOG(( "blue zones computation\n" ));
+    AH_LOG(( "------------------------------------------------\n" ));
+
+    for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ )
+    {
+      const char*  p     = blue_chars[blue];
+      const char*  limit = p + MAX_TEST_CHARACTERS;
+      FT_Pos       *blue_ref, *blue_shoot;
+
+
+      AH_LOG(( "blue %3d: ", blue ));
+
+      num_flats  = 0;
+      num_rounds = 0;
+
+      for ( ; p < limit; p++ )
+      {
+        FT_UInt     glyph_index;
+        FT_Vector*  extremum;
+        FT_Vector*  points;
+        FT_Vector*  point_limit;
+        FT_Vector*  point;
+        FT_Bool     round;
+
+
+        /* exit if we reach the end of the string */
+        if ( !*p )
+          break;
+
+        AH_LOG(( "`%c'", *p ));
+
+        /* load the character in the face -- skip unknown or empty ones */
+        glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
+        if ( glyph_index == 0 )
+          continue;
+
+        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+        if ( error || glyph->outline.n_points <= 0 )
+          continue;
+
+        /* now compute min or max point indices and coordinates */
+        points      = glyph->outline.points;
+        point_limit = points + glyph->outline.n_points;
+        point       = points;
+        extremum    = point;
+        point++;
+
+        if ( AH_IS_TOP_BLUE( blue ) )
+        {
+          for ( ; point < point_limit; point++ )
+            if ( point->y > extremum->y )
+              extremum = point;
+        }
+        else
+        {
+          for ( ; point < point_limit; point++ )
+            if ( point->y < extremum->y )
+              extremum = point;
+        }
+
+        AH_LOG(( "%5d", (int)extremum->y ));
+
+        /* now, check whether the point belongs to a straight or round  */
+        /* segment; we first need to find in which contour the extremum */
+        /* lies, then see its previous and next points                  */
+        {
+          FT_Int  index = (FT_Int)( extremum - points );
+          FT_Int  n;
+          FT_Int  first, last, prev, next, end;
+          FT_Pos  dist;
+
+
+          last  = -1;
+          first = 0;
+
+          for ( n = 0; n < glyph->outline.n_contours; n++ )
+          {
+            end = glyph->outline.contours[n];
+            if ( end >= index )
+            {
+              last = end;
+              break;
+            }
+            first = end + 1;
+          }
+
+          /* XXX: should never happen! */
+          if ( last < 0 )
+            continue;
+
+          /* now look for the previous and next points that are not on the */
+          /* same Y coordinate.  Threshold the `closeness'...              */
+
+          prev = index;
+          next = prev;
+
+          do
+          {
+            if ( prev > first )
+              prev--;
+            else
+              prev = last;
+
+            dist = points[prev].y - extremum->y;
+            if ( dist < -5 || dist > 5 )
+              break;
+
+          } while ( prev != index );
+
+          do
+          {
+            if ( next < last )
+              next++;
+            else
+              next = first;
+
+            dist = points[next].y - extremum->y;
+            if ( dist < -5 || dist > 5 )
+              break;
+
+          } while ( next != index );
+
+          /* now, set the `round' flag depending on the segment's kind */
+          round = FT_BOOL(
+            FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_Curve_Tag_On ||
+            FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_Curve_Tag_On );
+
+          AH_LOG(( "%c ", round ? 'r' : 'f' ));
+        }
+
+        if ( round )
+          rounds[num_rounds++] = extremum->y;
+        else
+          flats[num_flats++] = extremum->y;
+      }
+
+      AH_LOG(( "\n" ));
+
+      /* we have computed the contents of the `rounds' and `flats' tables, */
+      /* now determine the reference and overshoot position of the blue;   */
+      /* we simply take the median value after a simple short              */
+      sort_values( num_rounds, rounds );
+      sort_values( num_flats,  flats  );
+
+      blue_ref   = globals->blue_refs + blue;
+      blue_shoot = globals->blue_shoots + blue;
+      if ( num_flats == 0 && num_rounds == 0 )
+      {
+        *blue_ref   = -10000;
+        *blue_shoot = -10000;
+      }
+      else if ( num_flats == 0 )
+      {
+        *blue_ref   =
+        *blue_shoot = rounds[num_rounds / 2];
+      }
+      else if ( num_rounds == 0 )
+      {
+        *blue_ref   =
+        *blue_shoot = flats[num_flats / 2];
+      }
+      else
+      {
+        *blue_ref   = flats[num_flats / 2];
+        *blue_shoot = rounds[num_rounds / 2];
+      }
+
+      /* there are sometimes problems: if the overshoot position of top     */
+      /* zones is under its reference position, or the opposite for bottom  */
+      /* zones.  We must thus check everything there and correct the errors */
+      if ( *blue_shoot != *blue_ref )
+      {
+        FT_Pos   ref      = *blue_ref;
+        FT_Pos   shoot    = *blue_shoot;
+        FT_Bool  over_ref = FT_BOOL( shoot > ref );
+
+
+        if ( AH_IS_TOP_BLUE( blue ) ^ over_ref )
+          *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+      }
+
+      AH_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+    }
+
+    /* reset original face charmap */
+    FT_Set_Charmap( face, charmap );
+    error = 0;
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_Error
+  ah_hinter_compute_widths( AH_Hinter*  hinter )
+  {
+    /* scan the array of segments in each direction */
+    AH_Outline*  outline = hinter->glyph;
+    AH_Segment*  segments;
+    AH_Segment*  limit;
+    AH_Globals*  globals = &hinter->globals->design;
+    FT_Pos*      widths;
+    FT_Int       dimension;
+    FT_Int*      p_num_widths;
+    FT_Error     error = 0;
+    FT_Pos       edge_distance_threshold = 32000;
+
+
+    globals->num_widths  = 0;
+    globals->num_heights = 0;
+
+    /* For now, compute the standard width and height from the `o'       */
+    /* character.  I started computing the stem width of the `i' and the */
+    /* stem height of the "-", but it wasn't too good.  Moreover, we now */
+    /* have a single character that gives us standard width and height.  */
+    {
+      FT_UInt   glyph_index;
+
+
+      glyph_index = FT_Get_Char_Index( hinter->face, 'o' );
+      if ( glyph_index == 0 )
+        return 0;
+
+      error = FT_Load_Glyph( hinter->face, glyph_index, FT_LOAD_NO_SCALE );
+      if ( error )
+        goto Exit;
+
+      error = ah_outline_load( hinter->glyph, hinter->face );
+      if ( error )
+        goto Exit;
+
+      ah_outline_compute_segments( hinter->glyph );
+      ah_outline_link_segments( hinter->glyph );
+    }
+
+    segments     = outline->horz_segments;
+    limit        = segments + outline->num_hsegments;
+    widths       = globals->heights;
+    p_num_widths = &globals->num_heights;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Segment*  seg = segments;
+      AH_Segment*  link;
+      FT_Int       num_widths = 0;
+
+
+      for ( ; seg < limit; seg++ )
+      {
+        link = seg->link;
+        /* we only consider stem segments there! */
+        if ( link && link->link == seg && link > seg )
+        {
+          FT_Int  dist;
+
+
+          dist = seg->pos - link->pos;
+          if ( dist < 0 )
+            dist = -dist;
+
+          if ( num_widths < 12 )
+            widths[num_widths++] = dist;
+        }
+      }
+
+      sort_values( num_widths, widths );
+      *p_num_widths = num_widths;
+
+      /* we will now try to find the smallest width */
+      if ( num_widths > 0 && widths[0] < edge_distance_threshold )
+        edge_distance_threshold = widths[0];
+
+      segments     = outline->vert_segments;
+      limit        = segments + outline->num_vsegments;
+      widths       = globals->widths;
+      p_num_widths = &globals->num_widths;
+
+    }
+
+    /* Now, compute the edge distance threshold as a fraction of the */
+    /* smallest width in the font. Set it in `hinter.glyph' too!     */
+    if ( edge_distance_threshold == 32000 )
+      edge_distance_threshold = 50;
+
+    /* let's try 20% */
+    hinter->glyph->edge_distance_threshold = edge_distance_threshold / 5;
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  ah_hinter_compute_globals( AH_Hinter*  hinter )
+  {
+    return ah_hinter_compute_widths( hinter ) ||
+           ah_hinter_compute_blues ( hinter );
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ahglyph.c b/libraries/freetype-2.0.5/ahglyph.c
new file mode 100644 (file)
index 0000000..390be7e
--- /dev/null
@@ -0,0 +1,1465 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahglyph.c                                                              */
+/*                                                                         */
+/*    Routines used to load and analyze a given glyph before hinting       */
+/*    (body).                                                              */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "ahglyph.h"
+#include "ahangles.h"
+#include "ahglobal.h"
+#include "aherrors.h"
+
+#include <stdio.h>
+
+
+
+#ifdef AH_DEBUG
+
+  void
+  ah_dump_edges( AH_Outline*  outline )
+  {
+    AH_Edge*     edges;
+    AH_Edge*     edge_limit;
+    AH_Segment*  segments;
+    FT_Int       dimension;
+
+
+    edges      = outline->horz_edges;
+    edge_limit = edges + outline->num_hedges;
+    segments   = outline->horz_segments;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Edge*  edge;
+
+
+      printf ( "Table of %s edges:\n",
+               !dimension ? "vertical" : "horizontal" );
+      printf ( "  [ index |  pos |  dir  | link |"
+               " serif | blue | opos  |  pos  ]\n" );
+
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        printf ( "  [ %5d | %4d | %5s | %4d | %5d |  %c  | %5.2f | %5.2f ]\n",
+                 edge - edges,
+                 (int)edge->fpos,
+                 edge->dir == ah_dir_up
+                   ? "up"
+                   : ( edge->dir == ah_dir_down
+                         ? "down"
+                         : ( edge->dir == ah_dir_left
+                               ? "left"
+                               : ( edge->dir == ah_dir_right
+                                     ? "right"
+                                     : "none" ) ) ),
+                 edge->link ? ( edge->link - edges ) : -1,
+                 edge->serif ? ( edge->serif - edges ) : -1,
+                 edge->blue_edge ? 'y' : 'n',
+                 edge->opos / 64.0,
+                 edge->pos / 64.0 );
+      }
+
+      edges      = outline->vert_edges;
+      edge_limit = edges + outline->num_vedges;
+      segments   = outline->vert_segments;
+    }
+  }
+
+
+  /* A function used to dump the array of linked segments */
+  void
+  ah_dump_segments( AH_Outline*  outline )
+  {
+    AH_Segment*  segments;
+    AH_Segment*  segment_limit;
+    AH_Point*    points;
+    FT_Int       dimension;
+
+
+    points        = outline->points;
+    segments      = outline->horz_segments;
+    segment_limit = segments + outline->num_hsegments;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Segment*  seg;
+
+
+      printf ( "Table of %s segments:\n",
+               !dimension ? "vertical" : "horizontal" );
+      printf ( "  [ index |  pos |  dir  | link | serif |"
+               " numl | first | start ]\n" );
+
+      for ( seg = segments; seg < segment_limit; seg++ )
+      {
+        printf ( "  [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n",
+                 seg - segments,
+                 (int)seg->pos,
+                 seg->dir == ah_dir_up
+                   ? "up"
+                   : ( seg->dir == ah_dir_down
+                         ? "down"
+                         : ( seg->dir == ah_dir_left
+                               ? "left"
+                               : ( seg->dir == ah_dir_right
+                                     ? "right"
+                                     : "none" ) ) ),
+                 seg->link ? (seg->link-segments) : -1,
+                 seg->serif ? (seg->serif-segments) : -1,
+                 (int)seg->num_linked,
+                 seg->first - points,
+                 seg->last - points );
+      }
+
+      segments      = outline->vert_segments;
+      segment_limit = segments + outline->num_vsegments;
+    }
+  }
+
+#endif /* AH_DEBUG */
+
+
+  /* compute the direction value of a given vector.. */
+  static AH_Direction
+  ah_compute_direction( FT_Pos  dx,
+                        FT_Pos  dy )
+  {
+    AH_Direction  dir;
+    FT_Pos        ax = ABS( dx );
+    FT_Pos        ay = ABS( dy );
+
+
+    dir = ah_dir_none;
+
+    /* test for vertical direction */
+    if ( ax * 12 < ay )
+    {
+      dir = dy > 0 ? ah_dir_up : ah_dir_down;
+    }
+    /* test for horizontal direction */
+    else if ( ay * 12 < ax )
+    {
+      dir = dx > 0 ? ah_dir_right : ah_dir_left;
+    }
+
+    return dir;
+  }
+
+
+  /* this function is used by ah_get_orientation (see below) to test */
+  /* the fill direction of a given bbox extrema                      */
+  static int
+  ah_test_extrema( FT_Outline*  outline,
+                   int          n )
+  {
+    FT_Vector  *prev, *cur, *next;
+    FT_Pos      product;
+    FT_Int      first, last, c;
+
+
+    /* we need to compute the `previous' and `next' point */
+    /* for these extrema                                  */
+    cur  = outline->points + n;
+    prev = cur - 1;
+    next = cur + 1;
+
+    first = 0;
+    for ( c = 0; c < outline->n_contours; c++ )
+    {
+      last  = outline->contours[c];
+
+      if ( n == first )
+        prev = outline->points + last;
+
+      if ( n == last )
+        next = outline->points + first;
+
+      first = last + 1;
+    }
+
+    product = FT_MulDiv( cur->x  - prev->x,  /* in.x  */
+                         next->y - cur->y,   /* out.y */
+                         0x40 )
+              -
+              FT_MulDiv( cur->y  - prev->y,  /* in.y  */
+                         next->x - cur->x,   /* out.x */
+                         0x40 );
+
+    if ( product )
+      product = product > 0 ? 2 : 1;
+
+    return product;
+  }
+
+
+  /* Compute the orientation of path filling.  It differs between TrueType */
+  /* and Type1 formats.  We could use the `ft_outline_reverse_fill' flag,  */
+  /* but it is better to re-compute it directly (it seems that this flag   */
+  /* isn't correctly set for some weird composite glyphs currently).       */
+  /*                                                                       */
+  /* We do this by computing bounding box points, and computing their      */
+  /* curvature.                                                            */
+  /*                                                                       */
+  /* The function returns either 1 or -1.                                  */
+  /*                                                                       */
+  static int
+  ah_get_orientation( FT_Outline*  outline )
+  {
+    FT_BBox  box;
+    FT_BBox  indices;
+    int      n, last;
+
+
+    indices.xMin = -1;
+    indices.yMin = -1;
+    indices.xMax = -1;
+    indices.yMax = -1;
+
+    box.xMin = box.yMin =  32767L;
+    box.xMax = box.yMax = -32768L;
+
+    /* is it empty? */
+    if ( outline->n_contours < 1 )
+      return 1;
+
+    last = outline->contours[outline->n_contours - 1];
+
+    for ( n = 0; n <= last; n++ )
+    {
+      FT_Pos  x, y;
+
+
+      x = outline->points[n].x;
+      if ( x < box.xMin )
+      {
+        box.xMin     = x;
+        indices.xMin = n;
+      }
+      if ( x > box.xMax )
+      {
+        box.xMax     = x;
+        indices.xMax = n;
+      }
+
+      y = outline->points[n].y;
+      if ( y < box.yMin )
+      {
+        box.yMin     = y;
+        indices.yMin = n;
+      }
+      if ( y > box.yMax )
+      {
+        box.yMax     = y;
+        indices.yMax = n;
+      }
+    }
+
+    /* test orientation of the xmin */
+    n = ah_test_extrema( outline, indices.xMin );
+    if ( n )
+      goto Exit;
+
+    n = ah_test_extrema( outline, indices.yMin );
+    if ( n )
+      goto Exit;
+
+    n = ah_test_extrema( outline, indices.xMax );
+    if ( n )
+      goto Exit;
+
+    n = ah_test_extrema( outline, indices.yMax );
+    if ( !n )
+      n = 1;
+
+  Exit:
+    return n;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_new                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new and empty AH_Outline object.                         */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  ah_outline_new( FT_Memory     memory,
+                  AH_Outline**  aoutline )
+  {
+    FT_Error     error;
+    AH_Outline*  outline;
+
+
+    if ( !ALLOC( outline, sizeof ( *outline ) ) )
+    {
+      outline->memory = memory;
+      *aoutline = outline;
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_done                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given AH_Outline object.                                */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  ah_outline_done( AH_Outline*  outline )
+  {
+    FT_Memory memory = outline->memory;
+
+
+    FREE( outline->horz_edges );
+    FREE( outline->horz_segments );
+    FREE( outline->contours );
+    FREE( outline->points );
+
+    FREE( outline );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_save                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Saves the content of a given AH_Outline object into a face's glyph */
+  /*    slot.                                                              */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  ah_outline_save( AH_Outline*  outline,
+                   AH_Loader*   gloader )
+  {
+    AH_Point*   point       = outline->points;
+    AH_Point*   point_limit = point + outline->num_points;
+    FT_Vector*  vec         = gloader->current.outline.points;
+    char*       tag         = gloader->current.outline.tags;
+
+
+    /* we assume that the glyph loader has already been checked for storage */
+    for ( ; point < point_limit; point++, vec++, tag++ )
+    {
+      vec->x = point->x;
+      vec->y = point->y;
+
+      if ( point->flags & ah_flah_conic )
+        tag[0] = FT_Curve_Tag_Conic;
+      else if ( point->flags & ah_flah_cubic )
+        tag[0] = FT_Curve_Tag_Cubic;
+      else
+        tag[0] = FT_Curve_Tag_On;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_load                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads an unscaled outline from a glyph slot into an AH_Outline     */
+  /*    object.                                                            */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  ah_outline_load( AH_Outline*  outline,
+                   FT_Face      face )
+  {
+    FT_Memory   memory       = outline->memory;
+    FT_Error    error        = AH_Err_Ok;
+    FT_Outline* source       = &face->glyph->outline;
+    FT_Int      num_points   = source->n_points;
+    FT_Int      num_contours = source->n_contours;
+    AH_Point*   points;
+
+
+    /* check arguments */
+    if ( !face                                          ||
+         !face->size                                    ||
+         face->glyph->format != ft_glyph_format_outline )
+      return AH_Err_Invalid_Argument;
+
+    /* first of all, reallocate the contours array if necessary */
+    if ( num_contours > outline->max_contours )
+    {
+      FT_Int  new_contours = ( num_contours + 3 ) & -4;
+
+
+      if ( REALLOC_ARRAY( outline->contours, outline->max_contours,
+                          new_contours, AH_Point* ) )
+        goto Exit;
+
+      outline->max_contours = new_contours;
+    }
+
+    /* then, reallocate the points, segments & edges arrays if needed -- */
+    /* note that we reserved two additional point positions, used to     */
+    /* hint metrics appropriately                                        */
+    /*                                                                   */
+    if ( num_points + 2 > outline->max_points )
+    {
+      FT_Int  news = ( num_points + 2 + 7 ) & -8;
+      FT_Int  max  = outline->max_points;
+
+
+      if ( REALLOC_ARRAY( outline->points,
+                          max, news, AH_Point )            ||
+           REALLOC_ARRAY( outline->horz_edges,
+                          max * 2, news * 2, AH_Edge )     ||
+           REALLOC_ARRAY( outline->horz_segments,
+                          max * 2, news * 2, AH_Segment ) )
+        goto Exit;
+
+      /* readjust some pointers */
+      outline->vert_edges    = outline->horz_edges    + news;
+      outline->vert_segments = outline->horz_segments + news;
+      outline->max_points    = news;
+    }
+
+    outline->num_points   = num_points;
+    outline->num_contours = num_contours;
+
+    outline->num_hedges    = 0;
+    outline->num_vedges    = 0;
+    outline->num_hsegments = 0;
+    outline->num_vsegments = 0;
+
+    /* We can't rely on the value of `FT_Outline.flags' to know the fill  */
+    /* direction used for a glyph, given that some fonts are broken (e.g. */
+    /* the Arphic ones). We thus recompute it each time we need to.       */
+    /*                                                                    */
+    outline->vert_major_dir = ah_dir_up;
+    outline->horz_major_dir = ah_dir_left;
+
+    if ( ah_get_orientation( source ) > 1 )
+    {
+      outline->vert_major_dir = ah_dir_down;
+      outline->horz_major_dir = ah_dir_right;
+    }
+
+    outline->x_scale = face->size->metrics.x_scale;
+    outline->y_scale = face->size->metrics.y_scale;
+
+    points = outline->points;
+    if ( outline->num_points == 0 )
+      goto Exit;
+
+    {
+      /* do one thing at a time -- it is easier to understand, and */
+      /* the code is clearer                                       */
+      AH_Point*  point;
+      AH_Point*  point_limit = points + outline->num_points;
+
+
+      /* compute coordinates */
+      {
+        FT_Vector*  vec     = source->points;
+        FT_Fixed    x_scale = outline->x_scale;
+        FT_Fixed    y_scale = outline->y_scale;
+
+
+        for ( point = points; point < point_limit; vec++, point++ )
+        {
+          point->fx = vec->x;
+          point->fy = vec->y;
+          point->ox = point->x = FT_MulFix( vec->x, x_scale );
+          point->oy = point->y = FT_MulFix( vec->y, y_scale );
+
+          point->flags = 0;
+        }
+      }
+
+      /* compute Bezier flags */
+      {
+        char*  tag = source->tags;
+
+
+        for ( point = points; point < point_limit; point++, tag++ )
+        {
+          switch ( FT_CURVE_TAG( *tag ) )
+          {
+          case FT_Curve_Tag_Conic:
+            point->flags = ah_flah_conic; break;
+          case FT_Curve_Tag_Cubic:
+            point->flags = ah_flah_cubic; break;
+          default:
+            ;
+          }
+        }
+      }
+
+      /* compute `next' and `prev' */
+      {
+        FT_Int     contour_index;
+        AH_Point*  prev;
+        AH_Point*  first;
+        AH_Point*  end;
+
+
+        contour_index = 0;
+
+        first = points;
+        end   = points + source->contours[0];
+        prev  = end;
+
+        for ( point = points; point < point_limit; point++ )
+        {
+          point->prev = prev;
+          if ( point < end )
+          {
+            point->next = point + 1;
+            prev        = point;
+          }
+          else
+          {
+            point->next = first;
+            contour_index++;
+            if ( point + 1 < point_limit )
+            {
+              end   = points + source->contours[contour_index];
+              first = point + 1;
+              prev  = end;
+            }
+          }
+        }
+      }
+
+      /* set-up the contours array */
+      {
+        AH_Point**  contour       = outline->contours;
+        AH_Point**  contour_limit = contour + outline->num_contours;
+        short*      end           = source->contours;
+        short       index         = 0;
+
+
+        for ( ; contour < contour_limit; contour++, end++ )
+        {
+          contour[0] = points + index;
+          index      = (short)( end[0] + 1 );
+        }
+      }
+
+      /* compute directions of in & out vectors */
+      {
+        for ( point = points; point < point_limit; point++ )
+        {
+          AH_Point*  prev;
+          AH_Point*  next;
+          FT_Vector  vec;
+
+
+          prev  = point->prev;
+          vec.x = point->fx - prev->fx;
+          vec.y = point->fy - prev->fy;
+
+          point->in_dir = ah_compute_direction( vec.x, vec.y );
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+          point->in_angle = ah_angle( &vec );
+#endif
+
+          next  = point->next;
+          vec.x = next->fx - point->fx;
+          vec.y = next->fy - point->fy;
+
+          point->out_dir = ah_compute_direction( vec.x, vec.y );
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+          point->out_angle = ah_angle( &vec );
+
+          {
+            AH_Angle  delta = point->in_angle - point->out_angle;
+
+
+            if ( delta < 0 )
+              delta = -delta;
+            if ( delta < 2 )
+              point->flags |= ah_flah_weak_interpolation;
+          }
+
+#if 0
+          if ( point->flags & ( ah_flah_conic | ah_flah_cubic ) )
+            point->flags |= ah_flah_weak_interpolation;
+#endif
+
+#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */
+
+#ifdef AH_OPTION_NO_STRONG_INTERPOLATION
+          point->flags |= ah_flah_weak_interpolation;
+#endif
+        }
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF void
+  ah_setup_uv( AH_Outline*  outline,
+               AH_UV        source )
+  {
+    AH_Point*  point       = outline->points;
+    AH_Point*  point_limit = point + outline->num_points;
+
+
+    for ( ; point < point_limit; point++ )
+    {
+      FT_Pos  u, v;
+
+
+      switch ( source )
+      {
+      case ah_uv_fxy:
+        u = point->fx;
+        v = point->fy;
+        break;
+      case ah_uv_fyx:
+        u = point->fy;
+        v = point->fx;
+        break;
+      case ah_uv_oxy:
+        u = point->ox;
+        v = point->oy;
+        break;
+      case ah_uv_oyx:
+        u = point->oy;
+        v = point->ox;
+        break;
+      case ah_uv_yx:
+        u = point->y;
+        v = point->x;
+        break;
+      case ah_uv_ox:
+        u = point->x;
+        v = point->ox;
+        break;
+      case ah_uv_oy:
+        u = point->y;
+        v = point->oy;
+        break;
+      default:
+        u = point->x;
+        v = point->y;
+        break;
+      }
+      point->u = u;
+      point->v = v;
+    }
+  }
+
+
+  FT_LOCAL_DEF void
+  ah_outline_compute_segments( AH_Outline*  outline )
+  {
+    int           dimension;
+    AH_Segment*   segments;
+    FT_Int*       p_num_segments;
+    AH_Direction  segment_dir;
+    AH_Direction  major_dir;
+
+
+    segments       = outline->horz_segments;
+    p_num_segments = &outline->num_hsegments;
+    major_dir      = ah_dir_right;      /* This value must be positive! */
+    segment_dir    = major_dir;
+
+    /* set up (u,v) in each point */
+    ah_setup_uv( outline, ah_uv_fyx );
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Point**   contour       =  outline->contours;
+      AH_Point**   contour_limit =  contour + outline->num_contours;
+      AH_Segment*  segment       =  segments;
+      FT_Int       num_segments  =  0;
+
+#ifdef AH_HINT_METRICS
+      AH_Point*    min_point     =  0;
+      AH_Point*    max_point     =  0;
+      FT_Pos       min_coord     =  32000;
+      FT_Pos       max_coord     = -32000;
+#endif
+
+
+      /* do each contour separately */
+      for ( ; contour < contour_limit; contour++ )
+      {
+        AH_Point*  point   = contour[0];
+        AH_Point*  last    = point->prev;
+        int        on_edge = 0;
+        FT_Pos     min_pos = +32000;  /* minimum segment pos != min_coord */
+        FT_Pos     max_pos = -32000;  /* maximum segment pos != max_coord */
+        FT_Bool    passed;
+
+
+#ifdef AH_HINT_METRICS
+        if ( point->u < min_coord )
+        {
+          min_coord = point->u;
+          min_point = point;
+        }
+        if ( point->u > max_coord )
+        {
+          max_coord = point->u;
+          max_point = point;
+        }
+#endif
+
+        if ( point == last )  /* skip singletons -- just in case? */
+          continue;
+
+        if ( ABS( last->out_dir )  == major_dir &&
+             ABS( point->out_dir ) == major_dir )
+        {
+          /* we are already on an edge, try to locate its start */
+          last = point;
+
+          for (;;)
+          {
+            point = point->prev;
+            if ( ABS( point->out_dir ) != major_dir )
+            {
+              point = point->next;
+              break;
+            }
+            if ( point == last )
+              break;
+          }
+
+        }
+
+        last   = point;
+        passed = 0;
+
+        for (;;)
+        {
+          FT_Pos  u, v;
+
+
+          if ( on_edge )
+          {
+            u = point->u;
+            if ( u < min_pos )
+              min_pos = u;
+            if ( u > max_pos )
+              max_pos = u;
+
+            if ( point->out_dir != segment_dir || point == last )
+            {
+              /* we are just leaving an edge; record a new segment! */
+              segment->last = point;
+              segment->pos  = ( min_pos + max_pos ) >> 1;
+
+              /* a segment is round if either its first or last point */
+              /* is a control point                                   */
+              if ( ( segment->first->flags | point->flags ) &
+                     ah_flah_control                        )
+                segment->flags |= ah_edge_round;
+
+              /* compute segment size */
+              min_pos = max_pos = point->v;
+
+              v = segment->first->v;
+              if ( v < min_pos )
+                min_pos = v;
+              if ( v > max_pos )
+                max_pos = v;
+
+              segment->min_coord = min_pos;
+              segment->max_coord = max_pos;
+
+              on_edge = 0;
+              num_segments++;
+              segment++;
+              /* fallthrough */
+            }
+          }
+
+          /* now exit if we are at the start/end point */
+          if ( point == last )
+          {
+            if ( passed )
+              break;
+            passed = 1;
+          }
+
+          if ( !on_edge && ABS( point->out_dir ) == major_dir )
+          {
+            /* this is the start of a new segment! */
+            segment_dir = point->out_dir;
+
+            /* clear all segment fields */
+            memset( segment, 0, sizeof ( *segment ) );
+
+            segment->dir      = segment_dir;
+            segment->flags    = ah_edge_normal;
+            min_pos = max_pos = point->u;
+            segment->first    = point;
+            segment->last     = point;
+            segment->contour  = contour;
+            on_edge           = 1;
+
+#ifdef AH_HINT_METRICS
+            if ( point == max_point )
+              max_point = 0;
+
+            if ( point == min_point )
+              min_point = 0;
+#endif
+          }
+
+          point = point->next;
+        }
+
+      } /* contours */
+
+#ifdef AH_HINT_METRICS
+      /* we need to ensure that there are edges on the left-most and  */
+      /* right-most points of the glyph in order to hint the metrics; */
+      /* we do this by inserting fake segments when needed            */
+      if ( dimension == 0 )
+      {
+        AH_Point*  point       =  outline->points;
+        AH_Point*  point_limit =  point + outline->num_points;
+
+        FT_Pos     min_pos     =  32000;
+        FT_Pos     max_pos     = -32000;
+
+
+        min_point = 0;
+        max_point = 0;
+
+        /* compute minimum and maximum points */
+        for ( ; point < point_limit; point++ )
+        {
+          FT_Pos  x = point->fx;
+
+
+          if ( x < min_pos )
+          {
+            min_pos   = x;
+            min_point = point;
+          }
+          if ( x > max_pos )
+          {
+            max_pos   = x;
+            max_point = point;
+          }
+        }
+
+        /* insert minimum segment */
+        if ( min_point )
+        {
+          /* clear all segment fields */
+          memset( segment, 0, sizeof ( *segment ) );
+
+          segment->dir   = segment_dir;
+          segment->flags = ah_edge_normal;
+          segment->first = min_point;
+          segment->last  = min_point;
+          segment->pos   = min_pos;
+
+          num_segments++;
+          segment++;
+        }
+
+        /* insert maximum segment */
+        if ( max_point )
+        {
+          /* clear all segment fields */
+          memset( segment, 0, sizeof ( *segment ) );
+
+          segment->dir   = segment_dir;
+          segment->flags = ah_edge_normal;
+          segment->first = max_point;
+          segment->last  = max_point;
+          segment->pos   = max_pos;
+
+          num_segments++;
+          segment++;
+        }
+      }
+#endif /* AH_HINT_METRICS */
+
+      *p_num_segments = num_segments;
+
+      segments       = outline->vert_segments;
+      major_dir      = ah_dir_up;
+      p_num_segments = &outline->num_vsegments;
+      ah_setup_uv( outline, ah_uv_fxy );
+    }
+  }
+
+
+  FT_LOCAL_DEF void
+  ah_outline_link_segments( AH_Outline*  outline )
+  {
+    AH_Segment*  segments;
+    AH_Segment*  segment_limit;
+    int          dimension;
+
+
+    ah_setup_uv( outline, ah_uv_fyx );
+
+    segments      = outline->horz_segments;
+    segment_limit = segments + outline->num_hsegments;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Segment*  seg1;
+      AH_Segment*  seg2;
+
+
+      /* now compare each segment to the others */
+      for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+      {
+        FT_Pos       best_score   = 32000;
+        AH_Segment*  best_segment = 0;
+
+
+        /* the fake segments are introduced to hint the metrics -- */
+        /* we must never link them to anything                     */
+        if ( seg1->first == seg1->last )
+          continue;
+
+        for ( seg2 = segments; seg2 < segment_limit; seg2++ )
+          if ( seg1 != seg2 && seg1->dir + seg2->dir == 0 )
+          {
+            FT_Pos   pos1 = seg1->pos;
+            FT_Pos   pos2 = seg2->pos;
+            FT_Bool  is_dir;
+            FT_Bool  is_pos;
+
+
+            /* check that the segments are correctly oriented and */
+            /* positioned to form a black distance                */
+
+            is_dir = (FT_Bool)( seg1->dir == outline->horz_major_dir ||
+                                seg1->dir == outline->vert_major_dir );
+            is_pos = (FT_Bool)( pos1 > pos2 );
+
+            if ( pos1 == pos2 || !(is_dir ^ is_pos) )
+              continue;
+
+            /* Check the two segments.  We now have a better algorithm */
+            /* that doesn't rely on the segment points themselves but  */
+            /* on their relative position.  This gets rids of many     */
+            /* unpleasant artefacts and incorrect stem/serifs          */
+            /* computations.                                           */
+
+            /* first of all, compute the size of the `common' height */
+            {
+              FT_Pos  min = seg1->min_coord;
+              FT_Pos  max = seg1->max_coord;
+              FT_Pos  len, score;
+              FT_Pos  size1, size2;
+
+
+              size1 = max - min;
+              size2 = seg2->max_coord - seg2->min_coord;
+
+              if ( min < seg2->min_coord )
+                min = seg2->min_coord;
+
+              if ( max < seg2->max_coord )
+                max = seg2->max_coord;
+
+              len   = max - min;
+              score = seg2->pos - seg1->pos;
+              if ( score < 0 )
+                score = -score;
+
+              /* before comparing the scores, take care that the segments */
+              /* are really facing each other (often not for italics..)   */
+              if ( 4 * len >= size1 && 4 * len >= size2 )
+                if ( score < best_score )
+                {
+                  best_score   = score;
+                  best_segment = seg2;
+                }
+            }
+          }
+
+        if ( best_segment )
+        {
+          seg1->link  = best_segment;
+          seg1->score = best_score;
+
+          best_segment->num_linked++;
+        }
+
+
+      } /* edges 1 */
+
+      /* now, compute the `serif' segments */
+      for ( seg1 = segments; seg1 < segment_limit; seg1++ )
+      {
+        seg2 = seg1->link;
+
+        if ( seg2 && seg2->link != seg1 )
+        {
+          seg1->link  = 0;
+          seg1->serif = seg2->link;
+        }
+      }
+
+      ah_setup_uv( outline, ah_uv_fxy );
+
+      segments      = outline->vert_segments;
+      segment_limit = segments + outline->num_vsegments;
+    }
+  }
+
+
+  static void
+  ah_outline_compute_edges( AH_Outline*  outline )
+  {
+    AH_Edge*      edges;
+    AH_Segment*   segments;
+    AH_Segment*   segment_limit;
+    AH_Direction  up_dir;
+    FT_Int*       p_num_edges;
+    FT_Int        dimension;
+    FT_Fixed      scale;
+    FT_Pos        edge_distance_threshold;
+
+
+    edges         = outline->horz_edges;
+    segments      = outline->horz_segments;
+    segment_limit = segments + outline->num_hsegments;
+    p_num_edges   = &outline->num_hedges;
+    up_dir        = ah_dir_right;
+    scale         = outline->y_scale;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Edge*     edge;
+      AH_Edge*     edge_limit;  /* really == edge + num_edges */
+      AH_Segment*  seg;
+
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* We will begin by generating a sorted table of edges for the       */
+      /* current direction.  To do so, we simply scan each segment and try */
+      /* to find an edge in our table that corresponds to its position.    */
+      /*                                                                   */
+      /* If no edge is found, we create and insert a new edge in the       */
+      /* sorted table.  Otherwise, we simply add the segment to the edge's */
+      /* list which will be processed in the second step to compute the    */
+      /* edge's properties.                                                */
+      /*                                                                   */
+      /* Note that the edges table is sorted along the segment/edge        */
+      /* position.                                                         */
+      /*                                                                   */
+      /*********************************************************************/
+
+      edge_distance_threshold = FT_MulFix( outline->edge_distance_threshold,
+                                           scale );
+      if ( edge_distance_threshold > 64 / 4 )
+        edge_distance_threshold = 64 / 4;
+
+      edge_limit = edges;
+      for ( seg = segments; seg < segment_limit; seg++ )
+      {
+        AH_Edge*  found = 0;
+
+
+        /* look for an edge corresponding to the segment */
+        for ( edge = edges; edge < edge_limit; edge++ )
+        {
+          FT_Pos  dist;
+
+
+          dist = seg->pos - edge->fpos;
+          if ( dist < 0 )
+            dist = -dist;
+
+          dist = FT_MulFix( dist, scale );
+          if ( dist < edge_distance_threshold )
+          {
+            found = edge;
+            break;
+          }
+        }
+
+        if ( !found )
+        {
+          /* insert a new edge in the list and */
+          /* sort according to the position    */
+          while ( edge > edges && edge[-1].fpos > seg->pos )
+          {
+            edge[0] = edge[-1];
+            edge--;
+          }
+          edge_limit++;
+
+          /* clear all edge fields */
+          memset( edge, 0, sizeof ( *edge ) );
+
+          /* add the segment to the new edge's list */
+          edge->first    = seg;
+          edge->last     = seg;
+          edge->fpos     = seg->pos;
+          edge->opos     = edge->pos = FT_MulFix( seg->pos, scale );
+          seg->edge_next = seg;
+        }
+        else
+        {
+          /* if an edge was found, simply add the segment to the edge's */
+          /* list                                                       */
+          seg->edge_next        = edge->first;
+          edge->last->edge_next = seg;
+          edge->last            = seg;
+        }
+      }
+
+      *p_num_edges = (FT_Int)( edge_limit - edges );
+
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Good, we will now compute each edge's properties according to     */
+      /* segments found on its position.  Basically, these are:            */
+      /*                                                                   */
+      /*  - edge's main direction                                          */
+      /*  - stem edge, serif edge or both (which defaults to stem then)    */
+      /*  - rounded edge, straigth or both (which defaults to straight)    */
+      /*  - link for edge                                                  */
+      /*                                                                   */
+      /*********************************************************************/
+
+      /* first of all, set the `edge' field in each segment -- this is */
+      /* required in order to compute edge links                       */
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        seg = edge->first;
+        if ( seg )
+          do
+          {
+            seg->edge = edge;
+            seg       = seg->edge_next;
+          }
+          while ( seg != edge->first );
+      }
+
+      /* now, compute each edge properties */
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        int  is_round    = 0;  /* does it contain round segments?    */
+        int  is_straight = 0;  /* does it contain straight segments? */
+        int  ups         = 0;  /* number of upwards segments         */
+        int  downs       = 0;  /* number of downwards segments       */
+
+
+        seg = edge->first;
+
+        do
+        {
+          FT_Bool  is_serif;
+
+
+          /* check for roundness of segment */
+          if ( seg->flags & ah_edge_round )
+            is_round++;
+          else
+            is_straight++;
+
+          /* check for segment direction */
+          if ( seg->dir == up_dir )
+            ups   += seg->max_coord-seg->min_coord;
+          else
+            downs += seg->max_coord-seg->min_coord;
+
+          /* check for links -- if seg->serif is set, then seg->link must */
+          /* be ignored                                                   */
+          is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge );
+
+          if ( seg->link || is_serif )
+          {
+            AH_Edge*     edge2;
+            AH_Segment*  seg2;
+
+
+            edge2 = edge->link;
+            seg2  = seg->link;
+
+            if ( is_serif )
+            {
+              seg2  = seg->serif;
+              edge2 = edge->serif;
+            }
+
+            if ( edge2 )
+            {
+              FT_Pos  edge_delta;
+              FT_Pos  seg_delta;
+
+
+              edge_delta = edge->fpos - edge2->fpos;
+              if ( edge_delta < 0 )
+                edge_delta = -edge_delta;
+
+              seg_delta = seg->pos - seg2->pos;
+              if ( seg_delta < 0 )
+                seg_delta = -seg_delta;
+
+              if ( seg_delta < edge_delta )
+                edge2 = seg2->edge;
+            }
+            else
+              edge2 = seg2->edge;
+
+            if ( is_serif )
+              edge->serif = edge2;
+            else
+              edge->link  = edge2;
+          }
+
+          seg = seg->edge_next;
+
+        } while ( seg != edge->first );
+
+        /* set the round/straight flags */
+        edge->flags = ah_edge_normal;
+
+        if ( is_round > 0 && is_round >= is_straight )
+          edge->flags |= ah_edge_round;
+
+        /* set the edge's main direction */
+        edge->dir = ah_dir_none;
+
+        if ( ups > downs )
+          edge->dir = up_dir;
+
+        else if ( ups < downs )
+          edge->dir = - up_dir;
+
+        else if ( ups == downs )
+          edge->dir = 0;  /* both up and down !! */
+
+        /* gets rid of serifs if link is set                */
+        /* XXX: This gets rid of many unpleasant artefacts! */
+        /*      Example: the `c' in cour.pfa at size 13     */
+
+        if ( edge->serif && edge->link )
+          edge->serif = 0;
+      }
+
+      edges         = outline->vert_edges;
+      segments      = outline->vert_segments;
+      segment_limit = segments + outline->num_vsegments;
+      p_num_edges   = &outline->num_vedges;
+      up_dir        = ah_dir_up;
+      scale         = outline->x_scale;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_detect_features                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Performs feature detection on a given AH_Outline object.           */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  ah_outline_detect_features( AH_Outline*  outline )
+  {
+    ah_outline_compute_segments( outline );
+    ah_outline_link_segments   ( outline );
+    ah_outline_compute_edges   ( outline );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_compute_blue_edges                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the `blue edges' in a given outline (i.e. those that must */
+  /*    be snapped to a blue zone edge (top or bottom).                    */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  ah_outline_compute_blue_edges( AH_Outline*       outline,
+                                 AH_Face_Globals*  face_globals )
+  {
+    AH_Edge*     edge       = outline->horz_edges;
+    AH_Edge*     edge_limit = edge + outline->num_hedges;
+    AH_Globals*  globals    = &face_globals->design;
+    FT_Fixed     y_scale    = outline->y_scale;
+
+    FT_Bool      blue_active[ah_blue_max];
+
+
+    /* compute which blue zones are active, i.e. have their scaled */
+    /* size < 3/4 pixels                                           */
+    {
+      AH_Blue  blue;
+      FT_Bool  check = 0;
+
+
+      for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ )
+      {
+        FT_Pos  ref, shoot, dist;
+
+
+        ref   = globals->blue_refs[blue];
+        shoot = globals->blue_shoots[blue];
+        dist  = ref-shoot;
+        if ( dist < 0 )
+          dist = -dist;
+
+        blue_active[blue] = 0;
+
+        if ( FT_MulFix( dist, y_scale ) < 48 )
+        {
+          blue_active[blue] = 1;
+          check = 1;
+        }
+      }
+
+      /* return immediately if no blue zone is active */
+      if ( !check )
+        return;
+    }
+
+    /* compute for each horizontal edge, which blue zone is closer */
+    for ( ; edge < edge_limit; edge++ )
+    {
+      AH_Blue  blue;
+      FT_Pos*  best_blue = 0;
+      FT_Pos   best_dist;  /* initial threshold */
+
+
+      /* compute the initial threshold as a fraction of the EM size */
+      best_dist = FT_MulFix( face_globals->face->units_per_EM / 40, y_scale );
+      if ( best_dist > 64 / 4 )
+        best_dist = 64 / 4;
+
+      for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ )
+      {
+        /* if it is a top zone, check for right edges -- if it is a bottom */
+        /* zone, check for left edges                                      */
+        /*                                                                 */
+        /* of course, that's for TrueType XXX                              */
+        FT_Bool  is_top_blue  =
+                   FT_BOOL( AH_IS_TOP_BLUE( blue ) );
+        FT_Bool  is_major_dir =
+                   FT_BOOL( edge->dir == outline->horz_major_dir );
+
+        if ( !blue_active[blue] )
+          continue;
+
+        /* if it is a top zone, the edge must be against the major    */
+        /* direction; if it is a bottom zone, it must be in the major */
+        /* direction                                                  */
+        if ( is_top_blue ^ is_major_dir )
+        {
+          FT_Pos   dist;
+          FT_Pos*  blue_pos = globals->blue_refs + blue;
+
+
+          /* first of all, compare it to the reference position */
+          dist = edge->fpos - *blue_pos;
+          if ( dist < 0 )
+            dist = -dist;
+
+          dist = FT_MulFix( dist, y_scale );
+          if ( dist < best_dist )
+          {
+            best_dist = dist;
+            best_blue = blue_pos;
+          }
+
+          /* now, compare it to the overshoot position if the edge is     */
+          /* rounded, and if the edge is over the reference position of a */
+          /* top zone, or under the reference position of a bottom zone   */
+          if ( edge->flags & ah_edge_round && dist != 0 )
+          {
+            FT_Bool  is_under_ref = FT_BOOL( edge->fpos < *blue_pos );
+
+
+            if ( is_top_blue ^ is_under_ref )
+            {
+              blue_pos = globals->blue_shoots + blue;
+              dist = edge->fpos - *blue_pos;
+              if ( dist < 0 )
+                dist = -dist;
+
+              dist = FT_MulFix( dist, y_scale );
+              if ( dist < best_dist )
+              {
+                best_dist = dist;
+                best_blue = blue_pos;
+              }
+            }
+          }
+        }
+      }
+
+      if ( best_blue )
+        edge->blue_edge = best_blue;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ah_outline_scale_blue_edges                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This functions must be called before hinting in order to re-adjust */
+  /*    the contents of the detected edges (basically change the `blue     */
+  /*    edge' pointer from `design units' to `scaled ones').               */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  ah_outline_scale_blue_edges( AH_Outline*       outline,
+                               AH_Face_Globals*  globals )
+  {
+    AH_Edge*  edge       = outline->horz_edges;
+    AH_Edge*  edge_limit = edge + outline->num_hedges;
+    FT_Int    delta;
+
+
+    delta = globals->scaled.blue_refs - globals->design.blue_refs;
+
+    for ( ; edge < edge_limit; edge++ )
+    {
+      if ( edge->blue_edge )
+        edge->blue_edge += delta;
+    }
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ahhint.c b/libraries/freetype-2.0.5/ahhint.c
new file mode 100644 (file)
index 0000000..12f43fd
--- /dev/null
@@ -0,0 +1,1407 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahhint.c                                                               */
+/*                                                                         */
+/*    Glyph hinter (body).                                                 */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "ahhint.h"
+#include "ahglyph.h"
+#include "ahangles.h"
+#include "aherrors.h"
+#include FT_OUTLINE_H
+
+
+#define FACE_GLOBALS( face )  ((AH_Face_Globals*)(face)->autohint.data)
+
+#define AH_USE_IUP
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   Hinting routines                                              ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* snap a given width in scaled coordinates to one of the */
+  /* current standard widths                                */
+  static FT_Pos
+  ah_snap_width( FT_Pos*  widths,
+                 FT_Int   count,
+                 FT_Pos   width )
+  {
+    int     n;
+    FT_Pos  best      = 64 + 32 + 2;
+    FT_Pos  reference = width;
+
+
+    for ( n = 0; n < count; n++ )
+    {
+      FT_Pos  w;
+      FT_Pos  dist;
+
+
+      w = widths[n];
+      dist = width - w;
+      if ( dist < 0 )
+        dist = -dist;
+      if ( dist < best )
+      {
+        best      = dist;
+        reference = w;
+      }
+    }
+
+    if ( width >= reference )
+    {
+      width -= 0x21;
+      if ( width < reference )
+        width = reference;
+    }
+    else
+    {
+      width += 0x21;
+      if ( width > reference )
+        width = reference;
+    }
+
+    return width;
+  }
+
+
+  /* align one stem edge relative to the previous stem edge */
+  static void
+  ah_align_linked_edge( AH_Hinter*  hinter,
+                        AH_Edge*    base_edge,
+                        AH_Edge*    stem_edge,
+                        int         vertical )
+  {
+    FT_Pos       dist    = stem_edge->opos - base_edge->opos;
+    AH_Globals*  globals = &hinter->globals->scaled;
+    FT_Pos       sign    = 1;
+
+
+    if ( dist < 0 )
+    {
+      dist = -dist;
+      sign = -1;
+    }
+
+    if ( vertical )
+    {
+      dist = ah_snap_width( globals->heights, globals->num_heights, dist );
+
+      /* in the case of vertical hinting, always round */
+      /* the stem heights to integer pixels            */
+      if ( dist >= 64 )
+        dist = ( dist + 16 ) & -64;
+      else
+        dist = 64;
+    }
+    else
+    {
+      dist = ah_snap_width( globals->widths,  globals->num_widths, dist );
+
+      if ( hinter->flags & ah_hinter_monochrome )
+      {
+        /* monochrome horizontal hinting: snap widths to integer pixels */
+        /* with a different threshold                                   */
+        if ( dist < 64 )
+          dist = 64;
+        else
+          dist = ( dist + 32 ) & -64;
+      }
+      else
+      {
+        /* for horizontal anti-aliased hinting, we adopt a more subtle */
+        /* approach: we strengthen small stems, round stems whose size */
+        /* is between 1 and 2 pixels to an integer, otherwise nothing  */
+        if ( dist < 48 )
+          dist = ( dist + 64 ) >> 1;
+
+        else if ( dist < 128 )
+          dist = ( dist + 42 ) & -64;
+      }
+    }
+
+    stem_edge->pos = base_edge->pos + sign * dist;
+  }
+
+
+  static void
+  ah_align_serif_edge( AH_Hinter*  hinter,
+                       AH_Edge*    base,
+                       AH_Edge*    serif )
+  {
+    FT_Pos  dist;
+    FT_Pos  sign = 1;
+
+    UNUSED( hinter );
+
+
+    dist = serif->opos - base->opos;
+    if ( dist < 0 )
+    {
+      dist = -dist;
+      sign = -1;
+    }
+
+    /* do not strengthen serifs */
+    if ( base->flags & ah_edge_done )
+    {
+      if ( dist > 64 )
+        dist = ( dist + 16 ) & -64;
+
+      else if ( dist <= 32 )
+        dist = ( dist + 33 ) >> 1;
+    }
+
+    serif->pos = base->pos + sign * dist;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****       E D G E   H I N T I N G                                   ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* Another alternative edge hinting algorithm */
+  static void
+  ah_hint_edges_3( AH_Hinter*  hinter )
+  {
+    AH_Edge*     edges;
+    AH_Edge*     edge_limit;
+    AH_Outline*  outline = hinter->glyph;
+    FT_Int       dimension;
+
+
+    edges      = outline->horz_edges;
+    edge_limit = edges + outline->num_hedges;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Edge*  edge;
+      AH_Edge*  anchor = 0;
+      int       has_serifs = 0;
+
+
+      if ( hinter->disable_vert_edges && !dimension )
+        goto Next_Dimension;
+
+      if ( hinter->disable_horz_edges && dimension )
+        goto Next_Dimension;
+
+      /* we begin by aligning all stems relative to the blue zone */
+      /* if needed -- that's only for horizontal edges            */
+      if ( dimension )
+      {
+        for ( edge = edges; edge < edge_limit; edge++ )
+        {
+          FT_Pos*  blue;
+          AH_Edge  *edge1, *edge2;
+
+
+          if ( edge->flags & ah_edge_done )
+            continue;
+
+          blue  = edge->blue_edge;
+          edge1 = 0;
+          edge2 = edge->link;
+
+          if ( blue )
+          {
+            edge1 = edge;
+          }
+          else if (edge2 && edge2->blue_edge)
+          {
+            blue  = edge2->blue_edge;
+            edge1 = edge2;
+            edge2 = edge;
+          }
+
+          if ( !edge1 )
+            continue;
+
+          edge1->pos    = blue[0];
+          edge1->flags |= ah_edge_done;
+
+          if ( edge2 && !edge2->blue_edge )
+          {
+            ah_align_linked_edge( hinter, edge1, edge2, dimension );
+            edge2->flags |= ah_edge_done;
+          }
+
+          if ( !anchor )
+            anchor = edge;
+         }
+       }
+
+      /* now, we will align all stem edges, trying to maintain the */
+      /* relative order of stems in the glyph..                    */
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        AH_Edge  *edge2;
+
+
+        if ( edge->flags & ah_edge_done )
+          continue;
+
+        /* skip all non-stem edges */
+        edge2 = edge->link;
+        if ( !edge2 )
+        {
+          has_serifs++;
+          continue;
+        }
+
+        /* now, align the stem */
+
+        /* this should not happen, but it's better to be safe.. */
+        if ( edge2->blue_edge || edge2 < edge )
+        {
+
+#if 0
+          printf( "strange blue alignement, edge %d to %d\n",
+                  edge - edges, edge2 - edges );
+#endif
+
+          ah_align_linked_edge( hinter, edge2, edge, dimension );
+          edge->flags |= ah_edge_done;
+          continue;
+        }
+
+        {
+          FT_Bool  min = 0;
+          FT_Pos   delta;
+
+          if ( !anchor )
+          {
+            edge->pos = ( edge->opos + 32 ) & -64;
+            anchor    = edge;
+          }
+          else
+            edge->pos = anchor->pos +
+                        ( ( edge->opos - anchor->opos + 32 ) & -64 );
+
+          edge->flags |= ah_edge_done;
+
+          if ( edge > edges && edge->pos < edge[-1].pos )
+          {
+            edge->pos = edge[-1].pos;
+            min       = 1;
+          }
+
+          ah_align_linked_edge( hinter, edge, edge2, dimension );
+          delta = 0;
+          if ( edge2 + 1 < edge_limit        &&
+               edge2[1].flags & ah_edge_done )
+            delta = edge2[1].pos - edge2->pos;
+
+          if ( delta < 0 )
+          {
+            edge2->pos += delta;
+            if ( !min )
+              edge->pos += delta;
+          }
+          edge2->flags |= ah_edge_done;
+        }
+      }
+
+      if ( !has_serifs )
+        goto Next_Dimension;
+
+      /* now, hint the remaining edges (serifs and single) in order */
+      /* to complete our processing                                 */
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        if ( edge->flags & ah_edge_done )
+          continue;
+
+        if ( edge->serif )
+        {
+          ah_align_serif_edge( hinter, edge->serif, edge );
+        }
+        else if ( !anchor )
+        {
+          edge->pos = ( edge->opos + 32 ) & -64;
+          anchor    = edge;
+        }
+        else
+          edge->pos = anchor->pos +
+                      ( ( edge->opos-anchor->opos + 32 ) & -64 );
+
+        edge->flags |= ah_edge_done;
+
+        if ( edge > edges && edge->pos < edge[-1].pos )
+          edge->pos = edge[-1].pos;
+
+        if ( edge + 1 < edge_limit        &&
+             edge[1].flags & ah_edge_done &&
+             edge->pos > edge[1].pos      )
+          edge->pos = edge[1].pos;
+      }
+
+    Next_Dimension:
+      edges      = outline->vert_edges;
+      edge_limit = edges + outline->num_vedges;
+    }
+  }
+
+
+  FT_LOCAL_DEF void
+  ah_hinter_hint_edges( AH_Hinter*  hinter,
+                        FT_Bool     no_horz_edges,
+                        FT_Bool     no_vert_edges )
+  {
+    hinter->disable_horz_edges = no_horz_edges;
+    hinter->disable_vert_edges = no_vert_edges;
+
+    /* AH_Interpolate_Blue_Edges( hinter ); -- doesn't seem to help      */
+    /* reduce the problem of the disappearing eye in the `e' of Times... */
+    /* also, creates some artifacts near the blue zones?                 */
+    {
+      ah_hint_edges_3( hinter );
+
+#if 0
+      /* outline optimizer removed temporarily */
+      if ( hinter->flags & ah_hinter_optimize )
+      {
+        AH_Optimizer  opt;
+
+
+        if ( !AH_Optimizer_Init( &opt, hinter->glyph, hinter->memory ) )
+        {
+          AH_Optimizer_Compute( &opt );
+          AH_Optimizer_Done( &opt );
+        }
+      }
+#endif
+
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****       P O I N T   H I N T I N G                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static void
+  ah_hinter_align_edge_points( AH_Hinter*  hinter )
+  {
+    AH_Outline*  outline = hinter->glyph;
+    AH_Edge*     edges;
+    AH_Edge*     edge_limit;
+    FT_Int       dimension;
+
+
+    edges      = outline->horz_edges;
+    edge_limit = edges + outline->num_hedges;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Edge*   edge;
+
+
+      edge = edges;
+      for ( ; edge < edge_limit; edge++ )
+      {
+        /* move the points of each segment     */
+        /* in each edge to the edge's position */
+        AH_Segment*  seg = edge->first;
+
+
+        do
+        {
+          AH_Point*  point = seg->first;
+
+
+          for (;;)
+          {
+            if ( dimension )
+            {
+              point->y      = edge->pos;
+              point->flags |= ah_flah_touch_y;
+            }
+            else
+            {
+              point->x      = edge->pos;
+              point->flags |= ah_flah_touch_x;
+            }
+
+            if ( point == seg->last )
+              break;
+
+            point = point->next;
+          }
+
+          seg = seg->edge_next;
+
+        } while ( seg != edge->first );
+      }
+
+      edges      = outline->vert_edges;
+      edge_limit = edges + outline->num_vedges;
+    }
+  }
+
+
+  /* hint the strong points -- this is equivalent to the TrueType `IP' */
+  static void
+  ah_hinter_align_strong_points( AH_Hinter*  hinter )
+  {
+    AH_Outline*  outline = hinter->glyph;
+    FT_Int       dimension;
+    AH_Edge*     edges;
+    AH_Edge*     edge_limit;
+    AH_Point*    points;
+    AH_Point*    point_limit;
+    AH_Flags     touch_flag;
+
+
+    points      = outline->points;
+    point_limit = points + outline->num_points;
+
+    edges       = outline->horz_edges;
+    edge_limit  = edges + outline->num_hedges;
+    touch_flag  = ah_flah_touch_y;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Point*  point;
+      AH_Edge*   edge;
+
+
+      if ( edges < edge_limit )
+        for ( point = points; point < point_limit; point++ )
+        {
+          FT_Pos  u, ou, fu;  /* point position */
+          FT_Pos  delta;
+
+
+          if ( point->flags & touch_flag )
+            continue;
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+          /* if this point is candidate to weak interpolation, we will  */
+          /* interpolate it after all strong points have been processed */
+          if ( point->flags & ah_flah_weak_interpolation )
+            continue;
+#endif
+
+          if ( dimension )
+          {
+            u  = point->fy;
+            ou = point->oy;
+          }
+          else
+          {
+            u  = point->fx;
+            ou = point->ox;
+          }
+
+          fu = u;
+
+          /* is the point before the first edge? */
+          edge  = edges;
+          delta = edge->fpos - u;
+          if ( delta >= 0 )
+          {
+            u = edge->pos - ( edge->opos - ou );
+            goto Store_Point;
+          }
+
+          /* is the point after the last edge ? */
+          edge  = edge_limit - 1;
+          delta = u - edge->fpos;
+          if ( delta >= 0 )
+          {
+            u = edge->pos + ( ou - edge->opos );
+            goto Store_Point;
+          }
+
+          /* otherwise, interpolate the point in between */
+          {
+            AH_Edge*  before = 0;
+            AH_Edge*  after  = 0;
+
+
+            for ( edge = edges; edge < edge_limit; edge++ )
+            {
+              if ( u == edge->fpos )
+              {
+                u = edge->pos;
+                goto Store_Point;
+              }
+              if ( u < edge->fpos )
+                break;
+              before = edge;
+            }
+
+            for ( edge = edge_limit - 1; edge >= edges; edge-- )
+            {
+              if ( u == edge->fpos )
+              {
+                u = edge->pos;
+                goto Store_Point;
+              }
+              if ( u > edge->fpos )
+                break;
+              after = edge;
+            }
+
+            /* assert( before && after && before != after ) */
+            u = before->pos + FT_MulDiv( fu - before->fpos,
+                                         after->pos - before->pos,
+                                         after->fpos - before->fpos );
+          }
+
+        Store_Point:
+
+          /* save the point position */
+          if ( dimension )
+            point->y = u;
+          else
+            point->x = u;
+
+          point->flags |= touch_flag;
+        }
+
+      edges      = outline->vert_edges;
+      edge_limit = edges + outline->num_vedges;
+      touch_flag = ah_flah_touch_x;
+    }
+  }
+
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+
+  static void
+  ah_iup_shift( AH_Point*  p1,
+                AH_Point*  p2,
+                AH_Point*  ref )
+  {
+    AH_Point*  p;
+    FT_Pos     delta = ref->u - ref->v;
+
+
+    for ( p = p1; p < ref; p++ )
+      p->u = p->v + delta;
+
+    for ( p = ref + 1; p <= p2; p++ )
+      p->u = p->v + delta;
+  }
+
+
+  static void
+  ah_iup_interp( AH_Point*  p1,
+                 AH_Point*  p2,
+                 AH_Point*  ref1,
+                 AH_Point*  ref2 )
+  {
+    AH_Point*  p;
+    FT_Pos     u;
+    FT_Pos     v1 = ref1->v;
+    FT_Pos     v2 = ref2->v;
+    FT_Pos     d1 = ref1->u - v1;
+    FT_Pos     d2 = ref2->u - v2;
+
+
+    if ( p1 > p2 )
+      return;
+
+    if ( v1 == v2 )
+    {
+      for ( p = p1; p <= p2; p++ )
+      {
+        u = p->v;
+
+        if ( u <= v1 )
+          u += d1;
+        else
+          u += d2;
+
+        p->u = u;
+      }
+      return;
+    }
+
+    if ( v1 < v2 )
+    {
+      for ( p = p1; p <= p2; p++ )
+      {
+        u = p->v;
+
+        if ( u <= v1 )
+          u += d1;
+        else if ( u >= v2 )
+          u += d2;
+        else
+          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+
+        p->u = u;
+      }
+    }
+    else
+    {
+      for ( p = p1; p <= p2; p++ )
+      {
+        u = p->v;
+
+        if ( u <= v2 )
+          u += d2;
+        else if ( u >= v1 )
+          u += d1;
+        else
+          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+
+        p->u = u;
+      }
+    }
+  }
+
+
+  /* interpolate weak points -- this is equivalent to the TrueType `IUP' */
+  static void
+  ah_hinter_align_weak_points( AH_Hinter*  hinter )
+  {
+    AH_Outline*  outline = hinter->glyph;
+    FT_Int       dimension;
+    AH_Point*    points;
+    AH_Point*    point_limit;
+    AH_Point**   contour_limit;
+    AH_Flags     touch_flag;
+
+
+    points      = outline->points;
+    point_limit = points + outline->num_points;
+
+    /* PASS 1: Move segment points to edge positions */
+
+    touch_flag = ah_flah_touch_y;
+
+    contour_limit = outline->contours + outline->num_contours;
+
+    ah_setup_uv( outline, ah_uv_oy );
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Point*   point;
+      AH_Point*   end_point;
+      AH_Point*   first_point;
+      AH_Point**  contour;
+
+
+      point   = points;
+      contour = outline->contours;
+
+      for ( ; contour < contour_limit; contour++ )
+      {
+        point       = *contour;
+        end_point   = point->prev;
+        first_point = point;
+
+        while ( point <= end_point && !( point->flags & touch_flag ) )
+          point++;
+
+        if ( point <= end_point )
+        {
+          AH_Point*  first_touched = point;
+          AH_Point*  cur_touched   = point;
+
+
+          point++;
+          while ( point <= end_point )
+          {
+            if ( point->flags & touch_flag )
+            {
+              /* we found two successive touched points; we interpolate */
+              /* all contour points between them                        */
+              ah_iup_interp( cur_touched + 1, point - 1,
+                             cur_touched, point );
+              cur_touched = point;
+            }
+            point++;
+          }
+
+          if ( cur_touched == first_touched )
+          {
+            /* this is a special case: only one point was touched in the */
+            /* contour; we thus simply shift the whole contour           */
+            ah_iup_shift( first_point, end_point, cur_touched );
+          }
+          else
+          {
+            /* now interpolate after the last touched point to the end */
+            /* of the contour                                          */
+            ah_iup_interp( cur_touched + 1, end_point,
+                           cur_touched, first_touched );
+
+            /* if the first contour point isn't touched, interpolate */
+            /* from the contour start to the first touched point     */
+            if ( first_touched > points )
+              ah_iup_interp( first_point, first_touched - 1,
+                             cur_touched, first_touched );
+          }
+        }
+      }
+
+      /* now save the interpolated values back to x/y */
+      if ( dimension )
+      {
+        for ( point = points; point < point_limit; point++ )
+          point->y = point->u;
+
+        touch_flag = ah_flah_touch_x;
+        ah_setup_uv( outline, ah_uv_ox );
+      }
+      else
+      {
+        for ( point = points; point < point_limit; point++ )
+          point->x = point->u;
+
+        break;  /* exit loop */
+      }
+    }
+  }
+
+#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */
+
+
+  FT_LOCAL_DEF void
+  ah_hinter_align_points( AH_Hinter*  hinter )
+  {
+    ah_hinter_align_edge_points( hinter );
+
+#ifndef AH_OPTION_NO_STRONG_INTERPOLATION
+    ah_hinter_align_strong_points( hinter );
+#endif
+
+#ifndef AH_OPTION_NO_WEAK_INTERPOLATION
+    ah_hinter_align_weak_points( hinter );
+#endif
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****       H I N T E R   O B J E C T   M E T H O D S                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* scale and fit the global metrics */
+  static void
+  ah_hinter_scale_globals( AH_Hinter*  hinter,
+                           FT_Fixed    x_scale,
+                           FT_Fixed    y_scale )
+  {
+    FT_Int            n;
+    AH_Face_Globals*  globals = hinter->globals;
+    AH_Globals*       design = &globals->design;
+    AH_Globals*       scaled = &globals->scaled;
+
+
+    /* copy content */
+    *scaled = *design;
+
+    /* scale the standard widths & heights */
+    for ( n = 0; n < design->num_widths; n++ )
+      scaled->widths[n] = FT_MulFix( design->widths[n], x_scale );
+
+    for ( n = 0; n < design->num_heights; n++ )
+      scaled->heights[n] = FT_MulFix( design->heights[n], y_scale );
+
+    /* scale the blue zones */
+    for ( n = 0; n < ah_blue_max; n++ )
+    {
+      FT_Pos  delta, delta2;
+
+
+      delta = design->blue_shoots[n] - design->blue_refs[n];
+      delta2 = delta;
+      if ( delta < 0 )
+        delta2 = -delta2;
+      delta2 = FT_MulFix( delta2, y_scale );
+
+      if ( delta2 < 32 )
+        delta2 = 0;
+      else if ( delta2 < 64 )
+        delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & -32 );
+      else
+        delta2 = ( delta2 + 32 ) & -64;
+
+      if ( delta < 0 )
+        delta2 = -delta2;
+
+      scaled->blue_refs[n] =
+        ( FT_MulFix( design->blue_refs[n], y_scale ) + 32 ) & -64;
+      scaled->blue_shoots[n] = scaled->blue_refs[n] + delta2;
+    }
+
+    globals->x_scale = x_scale;
+    globals->y_scale = y_scale;
+  }
+
+
+  static void
+  ah_hinter_align( AH_Hinter*  hinter )
+  {
+    ah_hinter_align_edge_points( hinter );
+    ah_hinter_align_points( hinter );
+  }
+
+
+  /* finalize a hinter object */
+  FT_LOCAL_DEF void
+  ah_hinter_done( AH_Hinter*  hinter )
+  {
+    if ( hinter )
+    {
+      FT_Memory  memory = hinter->memory;
+
+
+      ah_loader_done( hinter->loader );
+      ah_outline_done( hinter->glyph );
+
+      /* note: the `globals' pointer is _not_ owned by the hinter */
+      /*       but by the current face object, we don't need to   */
+      /*       release it                                         */
+      hinter->globals = 0;
+      hinter->face    = 0;
+
+      FREE( hinter );
+    }
+  }
+
+
+  /* create a new empty hinter object */
+  FT_LOCAL_DEF FT_Error
+  ah_hinter_new( FT_Library   library,
+                 AH_Hinter**  ahinter )
+  {
+    AH_Hinter*  hinter = 0;
+    FT_Memory   memory = library->memory;
+    FT_Error    error;
+
+
+    *ahinter = 0;
+
+    /* allocate object */
+    if ( ALLOC( hinter, sizeof ( *hinter ) ) )
+      goto Exit;
+
+    hinter->memory = memory;
+    hinter->flags  = 0;
+
+    /* allocate outline and loader */
+    error = ah_outline_new( memory, &hinter->glyph )  ||
+            ah_loader_new ( memory, &hinter->loader ) ||
+            ah_loader_create_extra( hinter->loader );
+    if ( error )
+      goto Exit;
+
+    *ahinter = hinter;
+
+  Exit:
+    if ( error )
+      ah_hinter_done( hinter );
+
+    return error;
+  }
+
+
+  /* create a face's autohint globals */
+  FT_LOCAL_DEF FT_Error
+  ah_hinter_new_face_globals( AH_Hinter*   hinter,
+                              FT_Face      face,
+                              AH_Globals*  globals )
+  {
+    FT_Error          error;
+    FT_Memory         memory = hinter->memory;
+    AH_Face_Globals*  face_globals;
+
+
+    if ( ALLOC( face_globals, sizeof ( *face_globals ) ) )
+      goto Exit;
+
+    hinter->face    = face;
+    hinter->globals = face_globals;
+
+    if ( globals )
+      face_globals->design = *globals;
+    else
+      ah_hinter_compute_globals( hinter );
+
+    face->autohint.data      = face_globals;
+    face->autohint.finalizer = (FT_Generic_Finalizer)
+                                 ah_hinter_done_face_globals;
+    face_globals->face       = face;
+
+  Exit:
+    return error;
+  }
+
+
+  /* discard a face's autohint globals */
+  FT_LOCAL_DEF void
+  ah_hinter_done_face_globals( AH_Face_Globals*  globals )
+  {
+    FT_Face    face   = globals->face;
+    FT_Memory  memory = face->memory;
+
+
+    FREE( globals );
+  }
+
+
+  static FT_Error
+  ah_hinter_load( AH_Hinter*  hinter,
+                  FT_UInt     glyph_index,
+                  FT_UInt     load_flags,
+                  FT_UInt     depth )
+  {
+    FT_Face           face     = hinter->face;
+    FT_GlyphSlot      slot     = face->glyph;
+    FT_Slot_Internal  internal = slot->internal;
+    FT_Fixed          x_scale  = face->size->metrics.x_scale;
+    FT_Fixed          y_scale  = face->size->metrics.y_scale;
+    FT_Error          error;
+    AH_Outline*       outline  = hinter->glyph;
+    AH_Loader*        gloader  = hinter->loader;
+    FT_Bool           no_horz_hints = FT_BOOL(
+                        ( load_flags & AH_HINT_NO_HORZ_EDGES ) != 0 );
+    FT_Bool           no_vert_hints = FT_BOOL(
+                        ( load_flags & AH_HINT_NO_VERT_EDGES ) != 0 );
+
+
+    /* load the glyph */
+    error = FT_Load_Glyph( face, glyph_index, load_flags );
+    if ( error )
+      goto Exit;
+
+    /* Set `hinter->transformed' after loading with FT_LOAD_NO_RECURSE. */
+    hinter->transformed = internal->glyph_transformed;
+
+    if ( hinter->transformed )
+    {
+      FT_Matrix  imatrix;
+
+      imatrix              = internal->glyph_matrix;
+      hinter->trans_delta  = internal->glyph_delta;
+      hinter->trans_matrix = imatrix;
+
+      FT_Matrix_Invert( &imatrix );
+      FT_Vector_Transform( &hinter->trans_delta, &imatrix );
+    }
+
+    /* set linear horizontal metrics */
+    slot->linearHoriAdvance = slot->metrics.horiAdvance;
+    slot->linearVertAdvance = slot->metrics.vertAdvance;
+
+    switch ( slot->format )
+    {
+    case ft_glyph_format_outline:
+
+      /* translate glyph outline if we need to */
+      if ( hinter->transformed )
+      {
+        FT_UInt     n     = slot->outline.n_points;
+        FT_Vector*  point = slot->outline.points;
+
+
+        for ( ; n > 0; point++, n-- )
+        {
+          point->x += hinter->trans_delta.x;
+          point->y += hinter->trans_delta.y;
+        }
+      }
+
+      /* copy the outline points in the loader's current                */
+      /* extra points, which is used to keep original glyph coordinates */
+      error = ah_loader_check_points( gloader, slot->outline.n_points + 2,
+                                      slot->outline.n_contours );
+      if ( error )
+        goto Exit;
+
+      MEM_Copy( gloader->current.extra_points, slot->outline.points,
+                slot->outline.n_points * sizeof ( FT_Vector ) );
+
+      MEM_Copy( gloader->current.outline.contours, slot->outline.contours,
+                slot->outline.n_contours * sizeof ( short ) );
+
+      MEM_Copy( gloader->current.outline.tags, slot->outline.tags,
+                slot->outline.n_points * sizeof ( char ) );
+
+      gloader->current.outline.n_points   = slot->outline.n_points;
+      gloader->current.outline.n_contours = slot->outline.n_contours;
+
+      /* compute original phantom points */
+      hinter->pp1.x = 0;
+      hinter->pp1.y = 0;
+      hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale );
+      hinter->pp2.y = 0;
+
+      /* be sure to check for spacing glyphs */
+      if ( slot->outline.n_points == 0 )
+        goto Hint_Metrics;
+
+      /* now, load the slot image into the auto-outline, and run the */
+      /* automatic hinting process                                   */
+      error = ah_outline_load( outline, face );   /* XXX: change to slot */
+      if ( error )
+        goto Exit;
+
+      /* perform feature detection */
+      ah_outline_detect_features( outline );
+
+      if ( !no_horz_hints )
+      {
+        ah_outline_compute_blue_edges( outline, hinter->globals );
+        ah_outline_scale_blue_edges( outline, hinter->globals );
+      }
+
+      /* perform alignment control */
+      ah_hinter_hint_edges( hinter, no_horz_hints, no_vert_hints );
+      ah_hinter_align( hinter );
+
+      /* now save the current outline into the loader's current table */
+      ah_outline_save( outline, gloader );
+
+      /* we now need to hint the metrics according to the change in */
+      /* width/positioning that occured during the hinting process  */
+      {
+        FT_Pos    old_advance;
+        FT_Pos    old_lsb, new_lsb;
+        AH_Edge*  edge1 = outline->vert_edges;     /* leftmost edge  */
+        AH_Edge*  edge2 = edge1 +
+                          outline->num_vedges - 1; /* rightmost edge */
+
+
+        old_advance = hinter->pp2.x;
+        old_lsb     = edge1->opos;
+        new_lsb     = edge1->pos;
+
+        hinter->pp1.x = ( ( new_lsb - old_lsb ) + 32 ) & -64;
+        hinter->pp2.x = ( ( edge2->pos +
+                            ( old_advance - edge2->opos ) ) + 32 ) & -64;
+      }
+
+      /* good, we simply add the glyph to our loader's base */
+      ah_loader_add( gloader );
+      break;
+
+    case ft_glyph_format_composite:
+      {
+        FT_UInt       nn, num_subglyphs = slot->num_subglyphs;
+        FT_UInt       num_base_subgs, start_point;
+        FT_SubGlyph*  subglyph;
+
+
+        start_point   = gloader->base.outline.n_points;
+
+        /* first of all, copy the subglyph descriptors in the glyph loader */
+        error = ah_loader_check_subglyphs( gloader, num_subglyphs );
+        if ( error )
+          goto Exit;
+
+        MEM_Copy( gloader->current.subglyphs, slot->subglyphs,
+                  num_subglyphs * sizeof ( FT_SubGlyph ) );
+
+        gloader->current.num_subglyphs = num_subglyphs;
+        num_base_subgs = gloader->base.num_subglyphs;
+
+        /* now, read each subglyph independently */
+        for ( nn = 0; nn < num_subglyphs; nn++ )
+        {
+          FT_Vector  pp1, pp2;
+          FT_Pos     x, y;
+          FT_UInt    num_points, num_new_points, num_base_points;
+
+
+          /* gloader.current.subglyphs can change during glyph loading due */
+          /* to re-allocation -- we must recompute the current subglyph on */
+          /* each iteration                                                */
+          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
+
+          pp1 = hinter->pp1;
+          pp2 = hinter->pp2;
+
+          num_base_points = gloader->base.outline.n_points;
+
+          error = ah_hinter_load( hinter, subglyph->index,
+                                  load_flags, depth + 1 );
+          if ( error )
+            goto Exit;
+
+          /* recompute subglyph pointer */
+          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
+
+          if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
+          {
+            pp1 = hinter->pp1;
+            pp2 = hinter->pp2;
+          }
+          else
+          {
+            hinter->pp1 = pp1;
+            hinter->pp2 = pp2;
+          }
+
+          num_points     = gloader->base.outline.n_points;
+          num_new_points = num_points - num_base_points;
+
+          /* now perform the transform required for this subglyph */
+
+          if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE    |
+                                   FT_SUBGLYPH_FLAG_XY_SCALE |
+                                   FT_SUBGLYPH_FLAG_2X2      ) )
+          {
+            FT_Vector*  cur   = gloader->base.outline.points +
+                                num_base_points;
+            FT_Vector*  org   = gloader->base.extra_points +
+                                num_base_points;
+            FT_Vector*  limit = cur + num_new_points;
+
+
+            for ( ; cur < limit; cur++, org++ )
+            {
+              FT_Vector_Transform( cur, &subglyph->transform );
+              FT_Vector_Transform( org, &subglyph->transform );
+            }
+          }
+
+          /* apply offset */
+
+          if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
+          {
+            FT_Int      k = subglyph->arg1;
+            FT_UInt     l = subglyph->arg2;
+            FT_Vector*  p1;
+            FT_Vector*  p2;
+
+
+            if ( start_point + k >= num_base_points          ||
+                               l >= (FT_UInt)num_new_points  )
+            {
+              error = AH_Err_Invalid_Composite;
+              goto Exit;
+            }
+
+            l += num_base_points;
+
+            /* for now, only use the current point coordinates     */
+            /* we may consider another approach in the near future */
+            p1 = gloader->base.outline.points + start_point + k;
+            p2 = gloader->base.outline.points + start_point + l;
+
+            x = p1->x - p2->x;
+            y = p1->y - p2->y;
+          }
+          else
+          {
+            x = FT_MulFix( subglyph->arg1, x_scale );
+            y = FT_MulFix( subglyph->arg2, y_scale );
+
+            x = ( x + 32 ) & -64;
+            y = ( y + 32 ) & -64;
+          }
+
+          {
+            FT_Outline  dummy = gloader->base.outline;
+
+
+            dummy.points  += num_base_points;
+            dummy.n_points = (short)num_new_points;
+
+            FT_Outline_Translate( &dummy, x, y );
+          }
+        }
+      }
+      break;
+
+    default:
+      /* we don't support other formats (yet?) */
+      error = AH_Err_Unimplemented_Feature;
+    }
+
+  Hint_Metrics:
+    if ( depth == 0 )
+    {
+      FT_BBox  bbox;
+
+
+      /* transform the hinted outline if needed */
+      if ( hinter->transformed )
+        FT_Outline_Transform( &gloader->base.outline, &hinter->trans_matrix );
+
+      /* we must translate our final outline by -pp1.x, and compute */
+      /* the new metrics                                            */
+      if ( hinter->pp1.x )
+        FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 );
+
+      FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
+      bbox.xMin &= -64;
+      bbox.yMin &= -64;
+      bbox.xMax  = ( bbox.xMax + 63 ) & -64;
+      bbox.yMax  = ( bbox.yMax + 63 ) & -64;
+
+      slot->metrics.width        = bbox.xMax - bbox.xMin;
+      slot->metrics.height       = bbox.yMax - bbox.yMin;
+      slot->metrics.horiBearingX = bbox.xMin;
+      slot->metrics.horiBearingY = bbox.yMax;
+      slot->metrics.horiAdvance  = hinter->pp2.x - hinter->pp1.x;
+      /* XXX: TO DO - slot->linearHoriAdvance */
+
+      /* now copy outline into glyph slot */
+      ah_loader_rewind( slot->internal->loader );
+      error = ah_loader_copy_points( slot->internal->loader, gloader );
+      if ( error )
+        goto Exit;
+
+      slot->outline = slot->internal->loader->base.outline;
+      slot->format  = ft_glyph_format_outline;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* load and hint a given glyph */
+  FT_LOCAL_DEF FT_Error
+  ah_hinter_load_glyph( AH_Hinter*    hinter,
+                        FT_GlyphSlot  slot,
+                        FT_Size       size,
+                        FT_UInt       glyph_index,
+                        FT_Int        load_flags )
+  {
+    FT_Face           face         = slot->face;
+    FT_Error          error;
+    FT_Fixed          x_scale      = size->metrics.x_scale;
+    FT_Fixed          y_scale      = size->metrics.y_scale;
+    AH_Face_Globals*  face_globals = FACE_GLOBALS( face );
+
+
+    /* first of all, we need to check that we're using the correct face and */
+    /* global hints to load the glyph                                       */
+    if ( hinter->face != face || hinter->globals != face_globals )
+    {
+      hinter->face = face;
+      if ( !face_globals )
+      {
+        error = ah_hinter_new_face_globals( hinter, face, 0 );
+        if ( error )
+          goto Exit;
+
+      }
+      hinter->globals = FACE_GLOBALS( face );
+      face_globals    = FACE_GLOBALS( face );
+
+    }
+
+    /* now, we must check the current character pixel size to see if we */
+    /* need to rescale the global metrics                               */
+    if ( face_globals->x_scale != x_scale ||
+         face_globals->y_scale != y_scale )
+      ah_hinter_scale_globals( hinter, x_scale, y_scale );
+
+    ah_loader_rewind( hinter->loader );
+
+#if 1
+    load_flags  = FT_LOAD_NO_SCALE
+                | FT_LOAD_IGNORE_TRANSFORM ;
+#else
+    load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE;
+#endif
+
+    error = ah_hinter_load( hinter, glyph_index, load_flags, 0 );
+
+  Exit:
+    return error;
+  }
+
+
+  /* retrieve a face's autohint globals for client applications */
+  FT_LOCAL_DEF void
+  ah_hinter_get_global_hints( AH_Hinter*  hinter,
+                              FT_Face     face,
+                              void**      global_hints,
+                              long*       global_len )
+  {
+    AH_Globals*  globals = 0;
+    FT_Memory    memory  = hinter->memory;
+    FT_Error     error;
+
+
+    /* allocate new master globals */
+    if ( ALLOC( globals, sizeof ( *globals ) ) )
+      goto Fail;
+
+    /* compute face globals if needed */
+    if ( !FACE_GLOBALS( face ) )
+    {
+      error = ah_hinter_new_face_globals( hinter, face, 0 );
+      if ( error )
+        goto Fail;
+    }
+
+    *globals      = FACE_GLOBALS( face )->design;
+    *global_hints = globals;
+    *global_len   = sizeof( *globals );
+
+    return;
+
+  Fail:
+    FREE( globals );
+
+    *global_hints = 0;
+    *global_len   = 0;
+  }
+
+
+  FT_LOCAL_DEF void
+  ah_hinter_done_global_hints( AH_Hinter*  hinter,
+                               void*       global_hints )
+  {
+    FT_Memory  memory = hinter->memory;
+
+
+    FREE( global_hints );
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ahmodule.c b/libraries/freetype-2.0.5/ahmodule.c
new file mode 100644 (file)
index 0000000..6b6969a
--- /dev/null
@@ -0,0 +1,119 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahmodule.c                                                             */
+/*                                                                         */
+/*    Auto-hinting module implementation (declaration).                    */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+#include "ahhint.h"
+
+
+  typedef struct  FT_AutoHinterRec_
+  {
+    FT_ModuleRec  root;
+    AH_Hinter*    hinter;
+
+  } FT_AutoHinterRec;
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ft_autohinter_init( FT_AutoHinter  module )
+  {
+    return ah_hinter_new( module->root.library, &module->hinter );
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  ft_autohinter_done( FT_AutoHinter  module )
+  {
+    ah_hinter_done( module->hinter );
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ft_autohinter_load( FT_AutoHinter  module,
+                      FT_GlyphSlot   slot,
+                      FT_Size        size,
+                      FT_UInt        glyph_index,
+                      FT_ULong       load_flags )
+  {
+    return ah_hinter_load_glyph( module->hinter,
+                                 slot, size, glyph_index, load_flags );
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  ft_autohinter_reset( FT_AutoHinter  module,
+                       FT_Face        face )
+  {
+    UNUSED( module );
+
+    if ( face->autohint.data )
+      ah_hinter_done_face_globals( (AH_Face_Globals*)(face->autohint.data) );
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  ft_autohinter_get_globals( FT_AutoHinter  module,
+                             FT_Face        face,
+                             void**         global_hints,
+                             long*          global_len )
+  {
+    ah_hinter_get_global_hints( module->hinter, face,
+                                global_hints, global_len );
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  ft_autohinter_done_globals( FT_AutoHinter  module,
+                              void*          global_hints )
+  {
+    ah_hinter_done_global_hints( module->hinter, global_hints );
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_AutoHinter_Interface  autohinter_interface =
+  {
+    ft_autohinter_reset,
+    ft_autohinter_load,
+    ft_autohinter_get_globals,
+    ft_autohinter_done_globals
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Module_Class  autohint_module_class =
+  {
+    ft_module_hinter,
+    sizeof ( FT_AutoHinterRec ),
+
+    "autohinter",
+    0x10000L,   /* version 1.0 of the autohinter  */
+    0x20000L,   /* requires FreeType 2.0 or above */
+
+    (const void*)&autohinter_interface,
+
+    (FT_Module_Constructor)ft_autohinter_init,
+    (FT_Module_Destructor) ft_autohinter_done,
+    (FT_Module_Requester)  0
+  };
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ahoptim.c b/libraries/freetype-2.0.5/ahoptim.c
new file mode 100644 (file)
index 0000000..87c9ee5
--- /dev/null
@@ -0,0 +1,883 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahoptim.c                                                              */
+/*                                                                         */
+/*    FreeType auto hinting outline optimization (body).                   */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This module is in charge of optimising the outlines produced by the   */
+  /* auto-hinter in direct mode. This is required at small pixel sizes in  */
+  /* order to ensure coherent spacing, among other things..                */
+  /*                                                                       */
+  /* The technique used in this module is a simplified simulated           */
+  /* annealing.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H        /* for ALLOC_ARRAY() and FREE() */
+#include "ahoptim.h"
+
+
+  /* define this macro to use brute force optimisation -- this is slow,  */
+  /* but a good way to perfect the distortion function `by hand' through */
+  /* tweaking                                                            */
+#define AH_BRUTE_FORCE
+
+
+#define xxxAH_DEBUG_OPTIM
+
+
+#undef LOG
+#ifdef AH_DEBUG_OPTIM
+
+#define LOG( x )  optim_log ## x
+
+#else
+
+#define LOG( x )
+
+#endif /* AH_DEBUG_OPTIM */
+
+
+#ifdef AH_DEBUG_OPTIM
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FLOAT( x )  ( (float)( (x) / 64.0 ) )
+
+  static void
+  optim_log( const char*  fmt, ... )
+  {
+    va_list  ap;
+
+
+    va_start( ap, fmt );
+    vprintf( fmt, ap );
+    va_end( ap );
+  }
+
+
+  static void
+  AH_Dump_Stems( AH_Optimizer*  optimizer )
+  {
+    int       n;
+    AH_Stem*  stem;
+
+
+    stem = optimizer->stems;
+    for ( n = 0; n < optimizer->num_stems; n++, stem++ )
+    {
+      LOG(( " %c%2d [%.1f:%.1f]={%.1f:%.1f}="
+            "<%1.f..%1.f> force=%.1f speed=%.1f\n",
+            optimizer->vertical ? 'V' : 'H', n,
+            FLOAT( stem->edge1->opos ), FLOAT( stem->edge2->opos ),
+            FLOAT( stem->edge1->pos ),  FLOAT( stem->edge2->pos ),
+            FLOAT( stem->min_pos ),     FLOAT( stem->max_pos ),
+            FLOAT( stem->force ),       FLOAT( stem->velocity ) ));
+    }
+  }
+
+
+  static void
+  AH_Dump_Stems2( AH_Optimizer*  optimizer )
+  {
+    int       n;
+    AH_Stem*  stem;
+
+
+    stem = optimizer->stems;
+    for ( n = 0; n < optimizer->num_stems; n++, stem++ )
+    {
+      LOG(( " %c%2d [%.1f]=<%1.f..%1.f> force=%.1f speed=%.1f\n",
+            optimizer->vertical ? 'V' : 'H', n,
+            FLOAT( stem->pos ),
+            FLOAT( stem->min_pos ), FLOAT( stem->max_pos ),
+            FLOAT( stem->force ),   FLOAT( stem->velocity ) ));
+    }
+  }
+
+
+  static void
+  AH_Dump_Springs( AH_Optimizer*  optimizer )
+  {
+    int  n;
+    AH_Spring*  spring;
+    AH_Stem*    stems;
+
+
+    spring = optimizer->springs;
+    stems  = optimizer->stems;
+    LOG(( "%cSprings ", optimizer->vertical ? 'V' : 'H' ));
+
+    for ( n = 0; n < optimizer->num_springs; n++, spring++ )
+    {
+      LOG(( " [%d-%d:%.1f:%1.f:%.1f]",
+            spring->stem1 - stems, spring->stem2 - stems,
+            FLOAT( spring->owidth ),
+            FLOAT( spring->stem2->pos -
+                   ( spring->stem1->pos + spring->stem1->width ) ),
+            FLOAT( spring->tension ) ));
+    }
+
+    LOG(( "\n" ));
+  }
+
+#endif /* AH_DEBUG_OPTIM */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   COMPUTE STEMS AND SPRINGS IN AN OUTLINE                       ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static int
+  valid_stem_segments( AH_Segment*  seg1,
+                       AH_Segment*  seg2 )
+  {
+    return seg1->serif == 0                   &&
+           seg2                               &&
+           seg2->link == seg1                 &&
+           seg1->pos < seg2->pos              &&
+           seg1->min_coord <= seg2->max_coord &&
+           seg2->min_coord <= seg1->max_coord;
+  }
+
+
+  /* compute all stems in an outline */
+  static int
+  optim_compute_stems( AH_Optimizer*  optimizer )
+  {
+    AH_Outline*  outline = optimizer->outline;
+    FT_Fixed     scale;
+    FT_Memory    memory  = optimizer->memory;
+    FT_Error     error   = 0;
+    FT_Int       dimension;
+    AH_Edge*     edges;
+    AH_Edge*     edge_limit;
+    AH_Stem**    p_stems;
+    FT_Int*      p_num_stems;
+
+
+    edges      = outline->horz_edges;
+    edge_limit = edges + outline->num_hedges;
+    scale      = outline->y_scale;
+
+    p_stems     = &optimizer->horz_stems;
+    p_num_stems = &optimizer->num_hstems;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AH_Stem*  stems     = 0;
+      FT_Int    num_stems = 0;
+      AH_Edge*  edge;
+
+
+      /* first of all, count the number of stems in this direction */
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        AH_Segment*  seg = edge->first;
+
+
+        do
+        {
+          if (valid_stem_segments( seg, seg->link ) )
+            num_stems++;
+
+          seg = seg->edge_next;
+
+        } while ( seg != edge->first );
+      }
+
+      /* now allocate the stems and build their table */
+      if ( num_stems > 0 )
+      {
+        AH_Stem*  stem;
+
+
+        if ( ALLOC_ARRAY( stems, num_stems, AH_Stem ) )
+          goto Exit;
+
+        stem = stems;
+        for ( edge = edges; edge < edge_limit; edge++ )
+        {
+          AH_Segment*  seg = edge->first;
+          AH_Segment*  seg2;
+
+
+          do
+          {
+            seg2 = seg->link;
+            if ( valid_stem_segments( seg, seg2 ) )
+            {
+              AH_Edge*  edge1 = seg->edge;
+              AH_Edge*  edge2 = seg2->edge;
+
+
+              stem->edge1  = edge1;
+              stem->edge2  = edge2;
+              stem->opos   = edge1->opos;
+              stem->pos    = edge1->pos;
+              stem->owidth = edge2->opos - edge1->opos;
+              stem->width  = edge2->pos  - edge1->pos;
+
+              /* compute min_coord and max_coord */
+              {
+                FT_Pos  min_coord = seg->min_coord;
+                FT_Pos  max_coord = seg->max_coord;
+
+
+                if ( seg2->min_coord > min_coord )
+                  min_coord = seg2->min_coord;
+
+                if ( seg2->max_coord < max_coord )
+                  max_coord = seg2->max_coord;
+
+                stem->min_coord = min_coord;
+                stem->max_coord = max_coord;
+              }
+
+              /* compute minimum and maximum positions for stem --   */
+              /* note that the left-most/bottom-most stem has always */
+              /* a fixed position                                    */
+              if ( stem == stems || edge1->blue_edge || edge2->blue_edge )
+              {
+                /* this stem cannot move; it is snapped to a blue edge */
+                stem->min_pos = stem->pos;
+                stem->max_pos = stem->pos;
+              }
+              else
+              {
+                /* this edge can move; compute its min and max positions */
+                FT_Pos  pos1 = stem->opos;
+                FT_Pos  pos2 = pos1 + stem->owidth - stem->width;
+                FT_Pos  min1 = pos1 & -64;
+                FT_Pos  min2 = pos2 & -64;
+
+
+                stem->min_pos = min1;
+                stem->max_pos = min1 + 64;
+                if ( min2 < min1 )
+                  stem->min_pos = min2;
+                else
+                  stem->max_pos = min2 + 64;
+
+                /* XXX: just to see what it does */
+                stem->max_pos += 64;
+
+                /* just for the case where direct hinting did some */
+                /* incredible things (e.g. blue edge shifts)       */
+                if ( stem->min_pos > stem->pos )
+                  stem->min_pos = stem->pos;
+
+                if ( stem->max_pos < stem->pos )
+                  stem->max_pos = stem->pos;
+              }
+
+              stem->velocity = 0;
+              stem->force    = 0;
+
+              stem++;
+            }
+            seg = seg->edge_next;
+
+          } while ( seg != edge->first );
+        }
+      }
+
+      *p_stems     = stems;
+      *p_num_stems = num_stems;
+
+      edges      = outline->vert_edges;
+      edge_limit = edges + outline->num_vedges;
+      scale      = outline->x_scale;
+
+      p_stems     = &optimizer->vert_stems;
+      p_num_stems = &optimizer->num_vstems;
+    }
+
+  Exit:
+
+#ifdef AH_DEBUG_OPTIM
+    AH_Dump_Stems( optimizer );
+#endif
+
+    return error;
+  }
+
+
+  /* returns the spring area between two stems, 0 if none */
+  static FT_Pos
+  stem_spring_area( AH_Stem*  stem1,
+                    AH_Stem*  stem2 )
+  {
+    FT_Pos  area1 = stem1->max_coord - stem1->min_coord;
+    FT_Pos  area2 = stem2->max_coord - stem2->min_coord;
+    FT_Pos  min   = stem1->min_coord;
+    FT_Pos  max   = stem1->max_coord;
+    FT_Pos  area;
+
+
+    /* order stems */
+    if ( stem2->opos <= stem1->opos + stem1->owidth )
+      return 0;
+
+    if ( min < stem2->min_coord )
+      min = stem2->min_coord;
+
+    if ( max < stem2->max_coord )
+      max = stem2->max_coord;
+
+    area = ( max-min );
+    if ( 2 * area < area1 && 2 * area < area2 )
+      area = 0;
+
+    return area;
+  }
+
+
+  /* compute all springs in an outline */
+  static int
+  optim_compute_springs( AH_Optimizer*  optimizer )
+  {
+    /* basically, a spring exists between two stems if most of their */
+    /* surface is aligned                                            */
+    FT_Memory    memory  = optimizer->memory;
+
+    AH_Stem*     stems;
+    AH_Stem*     stem_limit;
+    AH_Stem*     stem;
+    int          dimension;
+    int          error = 0;
+
+    FT_Int*      p_num_springs;
+    AH_Spring**  p_springs;
+
+
+    stems      = optimizer->horz_stems;
+    stem_limit = stems + optimizer->num_hstems;
+
+    p_springs     = &optimizer->horz_springs;
+    p_num_springs = &optimizer->num_hsprings;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      FT_Int      num_springs = 0;
+      AH_Spring*  springs     = 0;
+
+
+      /* first of all, count stem springs */
+      for ( stem = stems; stem + 1 < stem_limit; stem++ )
+      {
+        AH_Stem*  stem2;
+
+
+        for ( stem2 = stem+1; stem2 < stem_limit; stem2++ )
+          if ( stem_spring_area( stem, stem2 ) )
+            num_springs++;
+      }
+
+      /* then allocate and build the springs table */
+      if ( num_springs > 0 )
+      {
+        AH_Spring*  spring;
+
+
+        /* allocate table of springs */
+        if ( ALLOC_ARRAY( springs, num_springs, AH_Spring ) )
+          goto Exit;
+
+        /* fill the springs table */
+        spring = springs;
+        for ( stem = stems; stem+1 < stem_limit; stem++ )
+        {
+          AH_Stem*  stem2;
+          FT_Pos    area;
+
+
+          for ( stem2 = stem + 1; stem2 < stem_limit; stem2++ )
+          {
+            area = stem_spring_area( stem, stem2 );
+            if ( area )
+            {
+              /* add a new spring here */
+              spring->stem1   = stem;
+              spring->stem2   = stem2;
+              spring->owidth  = stem2->opos - ( stem->opos + stem->owidth );
+              spring->tension = 0;
+
+              spring++;
+            }
+          }
+        }
+      }
+      *p_num_springs = num_springs;
+      *p_springs     = springs;
+
+      stems      = optimizer->vert_stems;
+      stem_limit = stems + optimizer->num_vstems;
+
+      p_springs     = &optimizer->vert_springs;
+      p_num_springs = &optimizer->num_vsprings;
+    }
+
+  Exit:
+
+#ifdef AH_DEBUG_OPTIM
+    AH_Dump_Springs( optimizer );
+#endif
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   OPTIMIZE THROUGH MY STRANGE SIMULATED ANNEALING ALGO ;-)      ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+#ifndef AH_BRUTE_FORCE
+
+  /* compute all spring tensions */
+  static void
+  optim_compute_tensions( AH_Optimizer*  optimizer )
+  {
+    AH_Spring*  spring = optimizer->springs;
+    AH_Spring*  limit  = spring + optimizer->num_springs;
+
+
+    for ( ; spring < limit; spring++ )
+    {
+      AH_Stem*  stem1 = spring->stem1;
+      AH_Stem*  stem2 = spring->stem2;
+      FT_Int    status;
+
+      FT_Pos  width;
+      FT_Pos  tension;
+      FT_Pos  sign;
+
+
+      /* compute the tension; it simply is -K*(new_width-old_width) */
+      width   = stem2->pos - ( stem1->pos + stem1->width );
+      tension = width - spring->owidth;
+
+      sign = 1;
+      if ( tension < 0 )
+      {
+        sign    = -1;
+        tension = -tension;
+      }
+
+      if ( width <= 0 )
+        tension = 32000;
+      else
+        tension = ( tension << 10 ) / width;
+
+      tension = -sign * FT_MulFix( tension, optimizer->tension_scale );
+      spring->tension = tension;
+
+      /* now, distribute tension among the englobing stems, if they */
+      /* are able to move                                           */
+      status = 0;
+      if ( stem1->pos <= stem1->min_pos )
+        status |= 1;
+      if ( stem2->pos >= stem2->max_pos )
+        status |= 2;
+
+      if ( !status )
+        tension /= 2;
+
+      if ( ( status & 1 ) == 0 )
+        stem1->force -= tension;
+
+      if ( ( status & 2 ) == 0 )
+        stem2->force += tension;
+    }
+  }
+
+
+  /* compute all stem movements -- returns 0 if nothing moved */
+  static int
+  optim_compute_stem_movements( AH_Optimizer*  optimizer )
+  {
+    AH_Stem*  stems = optimizer->stems;
+    AH_Stem*  limit = stems + optimizer->num_stems;
+    AH_Stem*  stem  = stems;
+    int       moved = 0;
+
+
+    /* set initial forces to velocity */
+    for ( stem = stems; stem < limit; stem++ )
+    {
+      stem->force     = stem->velocity;
+      stem->velocity /= 2;                  /* XXX: Heuristics */
+    }
+
+    /* compute the sum of forces applied on each stem */
+    optim_compute_tensions( optimizer );
+
+#ifdef AH_DEBUG_OPTIM
+    AH_Dump_Springs( optimizer );
+    AH_Dump_Stems2( optimizer );
+#endif
+
+    /* now, see whether something can move */
+    for ( stem = stems; stem < limit; stem++ )
+    {
+      if ( stem->force > optimizer->tension_threshold )
+      {
+        /* there is enough tension to move the stem to the right */
+        if ( stem->pos < stem->max_pos )
+        {
+          stem->pos     += 64;
+          stem->velocity = stem->force / 2;
+          moved          = 1;
+        }
+        else
+          stem->velocity = 0;
+      }
+      else if ( stem->force < optimizer->tension_threshold )
+      {
+        /* there is enough tension to move the stem to the left */
+        if ( stem->pos > stem->min_pos )
+        {
+          stem->pos     -= 64;
+          stem->velocity = stem->force / 2;
+          moved          = 1;
+        }
+        else
+          stem->velocity = 0;
+      }
+    }
+
+    /* return 0 if nothing moved */
+    return moved;
+  }
+
+#endif /* AH_BRUTE_FORCE */
+
+
+  /* compute current global distortion from springs */
+  static FT_Pos
+  optim_compute_distortion( AH_Optimizer*  optimizer )
+  {
+    AH_Spring*  spring = optimizer->springs;
+    AH_Spring*  limit  = spring + optimizer->num_springs;
+    FT_Pos      distortion = 0;
+
+
+    for ( ; spring < limit; spring++ )
+    {
+      AH_Stem*  stem1 = spring->stem1;
+      AH_Stem*  stem2 = spring->stem2;
+      FT_Pos  width;
+
+      width  = stem2->pos - ( stem1->pos + stem1->width );
+      width -= spring->owidth;
+      if ( width < 0 )
+        width = -width;
+
+      distortion += width;
+    }
+
+    return distortion;
+  }
+
+
+  /* record stems configuration in `best of' history */
+  static void
+  optim_record_configuration( AH_Optimizer*  optimizer )
+  {
+    FT_Pos             distortion;
+    AH_Configuration*  configs = optimizer->configs;
+    AH_Configuration*  limit   = configs + optimizer->num_configs;
+    AH_Configuration*  config;
+
+
+    distortion = optim_compute_distortion( optimizer );
+    LOG(( "config distortion = %.1f ", FLOAT( distortion * 64 ) ));
+
+    /* check that we really need to add this configuration to our */
+    /* sorted history                                             */
+    if ( limit > configs && limit[-1].distortion < distortion )
+    {
+      LOG(( "ejected\n" ));
+      return;
+    }
+
+    /* add new configuration at the end of the table */
+    {
+      int  n;
+
+
+      config = limit;
+      if ( optimizer->num_configs < AH_MAX_CONFIGS )
+        optimizer->num_configs++;
+      else
+        config--;
+
+      config->distortion = distortion;
+
+      for ( n = 0; n < optimizer->num_stems; n++ )
+        config->positions[n] = optimizer->stems[n].pos;
+    }
+
+    /* move the current configuration towards the front of the list */
+    /* when necessary -- yes this is slow bubble sort ;-)           */
+    while ( config > configs && config[0].distortion < config[-1].distortion )
+    {
+      AH_Configuration  temp;
+
+
+      config--;
+      temp      = config[0];
+      config[0] = config[1];
+      config[1] = temp;
+    }
+    LOG(( "recorded!\n" ));
+  }
+
+
+#ifdef AH_BRUTE_FORCE
+
+  /* optimize outline in a single direction */
+  static void
+  optim_compute( AH_Optimizer*  optimizer )
+  {
+    int       n;
+    FT_Bool   moved;
+
+    AH_Stem*  stem  = optimizer->stems;
+    AH_Stem*  limit = stem + optimizer->num_stems;
+
+
+    /* empty, exit */
+    if ( stem >= limit )
+      return;
+
+    optimizer->num_configs = 0;
+
+    stem = optimizer->stems;
+    for ( ; stem < limit; stem++ )
+      stem->pos = stem->min_pos;
+
+    do
+    {
+      /* record current configuration */
+      optim_record_configuration( optimizer );
+
+      /* now change configuration */
+      moved = 0;
+      for ( stem = optimizer->stems; stem < limit; stem++ )
+      {
+        if ( stem->pos < stem->max_pos )
+        {
+          stem->pos += 64;
+          moved      = 1;
+          break;
+        }
+
+        stem->pos = stem->min_pos;
+      }
+    } while ( moved );
+
+    /* now, set the best stem positions */
+    for ( n = 0; n < optimizer->num_stems; n++ )
+    {
+      AH_Stem*  stem = optimizer->stems + n;
+      FT_Pos    pos  = optimizer->configs[0].positions[n];
+
+
+      stem->edge1->pos = pos;
+      stem->edge2->pos = pos + stem->width;
+
+      stem->edge1->flags |= ah_edge_done;
+      stem->edge2->flags |= ah_edge_done;
+    }
+  }
+
+#else /* AH_BRUTE_FORCE */
+
+  /* optimize outline in a single direction */
+  static void
+  optim_compute( AH_Optimizer*  optimizer )
+  {
+    int  n, counter, counter2;
+
+
+    optimizer->num_configs       = 0;
+    optimizer->tension_scale     = 0x80000L;
+    optimizer->tension_threshold = 64;
+
+    /* record initial configuration threshold */
+    optim_record_configuration( optimizer );
+
+    counter = 0;
+    for ( counter2 = optimizer->num_stems*8; counter2 >= 0; counter2-- )
+    {
+      if ( counter == 0 )
+        counter = 2 * optimizer->num_stems;
+
+      if ( !optim_compute_stem_movements( optimizer ) )
+        break;
+
+      optim_record_configuration( optimizer );
+
+      counter--;
+      if ( counter == 0 )
+        optimizer->tension_scale /= 2;
+    }
+
+    /* now, set the best stem positions */
+    for ( n = 0; n < optimizer->num_stems; n++ )
+    {
+      AH_Stem*  stem = optimizer->stems + n;
+      FT_Pos    pos  = optimizer->configs[0].positions[n];
+
+
+      stem->edge1->pos = pos;
+      stem->edge2->pos = pos + stem->width;
+
+      stem->edge1->flags |= ah_edge_done;
+      stem->edge2->flags |= ah_edge_done;
+    }
+  }
+
+#endif /* AH_BRUTE_FORCE */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   HIGH-LEVEL OPTIMIZER API                                      ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* releases the optimization data */
+  void
+  AH_Optimizer_Done( AH_Optimizer*  optimizer )
+  {
+    if ( optimizer )
+    {
+      FT_Memory  memory = optimizer->memory;
+
+
+      FREE( optimizer->horz_stems );
+      FREE( optimizer->vert_stems );
+      FREE( optimizer->horz_springs );
+      FREE( optimizer->vert_springs );
+      FREE( optimizer->positions );
+    }
+  }
+
+
+  /* loads the outline into the optimizer */
+  int
+  AH_Optimizer_Init( AH_Optimizer*  optimizer,
+                     AH_Outline*    outline,
+                     FT_Memory      memory )
+  {
+    FT_Error  error;
+
+
+    MEM_Set( optimizer, 0, sizeof ( *optimizer ) );
+    optimizer->outline = outline;
+    optimizer->memory  = memory;
+
+    LOG(( "initializing new optimizer\n" ));
+    /* compute stems and springs */
+    error = optim_compute_stems  ( optimizer ) ||
+            optim_compute_springs( optimizer );
+    if ( error )
+      goto Fail;
+
+    /* allocate stem positions history and configurations */
+    {
+      int  n, max_stems;
+
+
+      max_stems = optimizer->num_hstems;
+      if ( max_stems < optimizer->num_vstems )
+        max_stems = optimizer->num_vstems;
+
+      if ( ALLOC_ARRAY( optimizer->positions,
+                        max_stems * AH_MAX_CONFIGS, FT_Pos ) )
+        goto Fail;
+
+      optimizer->num_configs = 0;
+      for ( n = 0; n < AH_MAX_CONFIGS; n++ )
+        optimizer->configs[n].positions = optimizer->positions +
+                                          n * max_stems;
+    }
+
+    return error;
+
+  Fail:
+    AH_Optimizer_Done( optimizer );
+    return error;
+  }
+
+
+  /* compute optimal outline */
+  void
+  AH_Optimizer_Compute( AH_Optimizer*  optimizer )
+  {
+    optimizer->num_stems   = optimizer->num_hstems;
+    optimizer->stems       = optimizer->horz_stems;
+    optimizer->num_springs = optimizer->num_hsprings;
+    optimizer->springs     = optimizer->horz_springs;
+
+    if ( optimizer->num_springs > 0 )
+    {
+      LOG(( "horizontal optimization ------------------------\n" ));
+      optim_compute( optimizer );
+    }
+
+    optimizer->num_stems   = optimizer->num_vstems;
+    optimizer->stems       = optimizer->vert_stems;
+    optimizer->num_springs = optimizer->num_vsprings;
+    optimizer->springs     = optimizer->vert_springs;
+
+    if ( optimizer->num_springs )
+    {
+      LOG(( "vertical optimization --------------------------\n" ));
+      optim_compute( optimizer );
+    }
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/autohint.c b/libraries/freetype-2.0.5/autohint.c
new file mode 100644 (file)
index 0000000..3783a82
--- /dev/null
@@ -0,0 +1,32 @@
+/***************************************************************************/
+/*                                                                         */
+/*  autohint.c                                                             */
+/*                                                                         */
+/*    Automatic Hinting wrapper (body only).                               */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ahangles.c"
+#include "ahglyph.c"
+#include "ahglobal.c"
+#include "ahhint.c"
+#include "ahmodule.c"
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cff.c b/libraries/freetype-2.0.5/cff.c
new file mode 100644 (file)
index 0000000..19883f2
--- /dev/null
@@ -0,0 +1,29 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cff.c                                                                  */
+/*                                                                         */
+/*    FreeType OpenType driver component (body only).                      */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "cffdrivr.c"
+#include "cffparse.c"
+#include "cffload.c"
+#include "cffobjs.c"
+#include "cffgload.c"
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cffdrivr.c b/libraries/freetype-2.0.5/cffdrivr.c
new file mode 100644 (file)
index 0000000..c8270f8
--- /dev/null
@@ -0,0 +1,483 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cffdrivr.c                                                             */
+/*                                                                         */
+/*    OpenType font driver implementation (body).                          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_TRUETYPE_IDS_H
+
+#include "cffdrivr.h"
+#include "cffgload.h"
+#include "cffload.h"
+
+#include "cfferrs.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cffdriver
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                          F A C E S                              ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#undef  PAIR_TAG
+#define PAIR_TAG( left, right )  ( ( (FT_ULong)left << 16 ) | \
+                                     (FT_ULong)right        )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Kerning                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to return the kerning vector between two      */
+  /*    glyphs of the same face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the source face object.                 */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this function.  Other layouts, or more sophisticated  */
+  /*    kernings, are out of scope of this method (the basic driver        */
+  /*    interface is meant to be simple).                                  */
+  /*                                                                       */
+  /*    They can be implemented by format-specific interfaces.             */
+  /*                                                                       */
+  static FT_Error
+  Get_Kerning( TT_Face     face,
+               FT_UInt     left_glyph,
+               FT_UInt     right_glyph,
+               FT_Vector*  kerning )
+  {
+    TT_Kern_0_Pair*  pair;
+
+
+    if ( !face )
+      return CFF_Err_Invalid_Face_Handle;
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    if ( face->kern_pairs )
+    {
+      /* there are some kerning pairs in this font file! */
+      FT_ULong  search_tag = PAIR_TAG( left_glyph, right_glyph );
+      FT_Long   left, right;
+
+
+      left  = 0;
+      right = face->num_kern_pairs - 1;
+
+      while ( left <= right )
+      {
+        FT_Int    middle = left + ( ( right - left ) >> 1 );
+        FT_ULong  cur_pair;
+
+
+        pair     = face->kern_pairs + middle;
+        cur_pair = PAIR_TAG( pair->left, pair->right );
+
+        if ( cur_pair == search_tag )
+          goto Found;
+
+        if ( cur_pair < search_tag )
+          left = middle + 1;
+        else
+          right = middle - 1;
+      }
+    }
+
+  Exit:
+    return CFF_Err_Ok;
+
+  Found:
+    kerning->x = pair->value;
+    goto Exit;
+  }
+
+
+#undef PAIR_TAG
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Load_Glyph                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to load a glyph within a given glyph slot.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot        :: A handle to the target slot object where the glyph  */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    size        :: A handle to the source face size at which the glyph */
+  /*                   must be scaled, loaded, etc.                        */
+  /*                                                                       */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FTLOAD_??? constants can be used to control the     */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  Load_Glyph( CFF_GlyphSlot  slot,
+              CFF_Size       size,
+              FT_UShort      glyph_index,
+              FT_UInt        load_flags )
+  {
+    FT_Error  error;
+
+
+    if ( !slot )
+      return CFF_Err_Invalid_Slot_Handle;
+
+    /* check whether we want a scaled outline or bitmap */
+    if ( !size )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    if ( load_flags & FT_LOAD_NO_SCALE )
+      size = NULL;
+
+    /* reset the size object if necessary */
+    if ( size )
+    {
+      /* these two object must have the same parent */
+      if ( size->face != slot->root.face )
+        return CFF_Err_Invalid_Face_Handle;
+    }
+
+    /* now load the glyph outline if necessary */
+    error = CFF_Load_Glyph( slot, size, glyph_index, load_flags );
+
+    /* force drop-out mode to 2 - irrelevant now */
+    /* slot->outline.dropout_mode = 2; */
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****             C H A R A C T E R   M A P P I N G S                 ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static FT_Error
+  cff_get_glyph_name( CFF_Face    face,
+                      FT_UInt     glyph_index,
+                      FT_Pointer  buffer,
+                      FT_UInt     buffer_max )
+  {
+    CFF_Font*           font   = (CFF_Font*)face->extra.data;
+    FT_Memory           memory = FT_FACE_MEMORY(face);
+    FT_String*          gname;
+    FT_UShort           sid;
+    PSNames_Interface*  psnames;
+    FT_Error            error;
+
+    psnames = (PSNames_Interface*)FT_Get_Module_Interface(
+                face->root.driver->root.library, "psnames" );
+
+    if ( !psnames )
+    {
+      FT_ERROR(( "CFF_Init_Face:" ));
+      FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
+      FT_ERROR(( "             " ));
+      FT_ERROR(( " without the `PSNames' module\n" ));
+      error = CFF_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    /* first, locate the sid in the charset table */
+    sid = font->charset.sids[glyph_index];
+
+    /* now, lookup the name itself */
+    gname = CFF_Get_String( &font->string_index, sid, psnames );
+
+    if ( buffer_max > 0 )
+    {
+      FT_UInt  len = strlen( gname );
+
+
+      if ( len >= buffer_max )
+        len = buffer_max - 1;
+
+      MEM_Copy( buffer, gname, len );
+      ((FT_Byte*)buffer)[len] = 0;
+    }
+
+    FREE ( gname );
+    error = CFF_Err_Ok;
+
+    Exit:
+      return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    cff_get_char_index                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static FT_UInt
+  cff_get_char_index( TT_CharMap  charmap,
+                      FT_Long     charcode )
+  {
+    FT_Error       error;
+    CFF_Face       face;
+    TT_CMapTable*  cmap;
+
+
+    cmap = &charmap->cmap;
+    face = (CFF_Face)charmap->root.face;
+
+    /* Load table if needed */
+    if ( !cmap->loaded )
+    {
+      SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
+
+
+      error = sfnt->load_charmap( face, cmap, face->root.stream );
+      if ( error )
+        return 0;
+
+      cmap->loaded = TRUE;
+    }
+
+    return ( cmap->get_index ? cmap->get_index( cmap, charcode ) : 0 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    cff_get_name_index                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses the psnames module and the CFF font's charset to to return a  */
+  /*    a given glyph name's glyph index.                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the source face object.                  */
+  /*                                                                       */
+  /*    glyph_name :: The glyph name.                                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static FT_UInt
+  cff_get_name_index( CFF_Face    face,
+                      FT_String*  glyph_name )
+  {
+    CFF_Font*           cff;
+    CFF_Charset*        charset;
+    PSNames_Interface*  psnames;
+    FT_String*          name;
+    FT_UShort           sid;
+    FT_UInt             i;
+
+
+    cff     = face->extra.data;
+    charset = &cff->charset;
+
+    psnames = (PSNames_Interface*)FT_Get_Module_Interface(
+                face->root.driver->root.library, "psnames" );
+
+    for ( i = 0; i < cff->num_glyphs; i++ )
+    {
+      sid = charset->sids[i];
+
+      if ( sid > 390 )
+        name = CFF_Get_Name( &cff->string_index, sid - 391 );
+      else
+        name = (FT_String *)psnames->adobe_std_strings( sid );
+
+      if ( !strcmp( glyph_name, name ) )
+        return i;
+    }
+
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                D R I V E R  I N T E R F A C E                   ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static FT_Module_Interface
+  cff_get_interface( CFF_Driver   driver,
+                     const char*  interface )
+  {
+    FT_Module  sfnt;
+
+#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
+
+    if ( strcmp( (const char*)interface, "glyph_name" ) == 0 )
+      return (FT_Module_Interface)cff_get_glyph_name;
+
+    if ( strcmp( (const char*)interface, "name_index" ) == 0 )
+      return (FT_Module_Interface)cff_get_name_index;
+
+#endif
+
+    /* we simply pass our request to the `sfnt' module */
+    sfnt = FT_Get_Module( driver->root.root.library, "sfnt" );
+
+    return sfnt ? sfnt->clazz->get_interface( sfnt, interface ) : 0;
+  }
+
+
+  /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Driver_Class  cff_driver_class =
+  {
+    /* begin with the FT_Module_Class fields */
+    {
+      ft_module_font_driver | ft_module_driver_scalable,
+      sizeof( CFF_DriverRec ),
+      "cff",
+      0x10000L,
+      0x20000L,
+
+      0,   /* module-specific interface */
+
+      (FT_Module_Constructor)CFF_Init_Driver,
+      (FT_Module_Destructor) CFF_Done_Driver,
+      (FT_Module_Requester)  cff_get_interface,
+    },
+
+    /* now the specific driver fields */
+    sizeof( TT_FaceRec ),
+    sizeof( FT_SizeRec ),
+    sizeof( CFF_GlyphSlotRec ),
+
+    (FTDriver_initFace)     CFF_Init_Face,
+    (FTDriver_doneFace)     CFF_Done_Face,
+    (FTDriver_initSize)     0,
+    (FTDriver_doneSize)     0,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) 0,
+    (FTDriver_setPixelSizes)0,
+
+    (FTDriver_loadGlyph)    Load_Glyph,
+    (FTDriver_getCharIndex) cff_get_char_index,
+
+    (FTDriver_getKerning)   Get_Kerning,
+    (FTDriver_attachFile)   0,
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverClass                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the TrueType driver as a      */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+  FT_EXPORT_DEF( const FT_Driver_Class* )
+  getDriverClass( void )
+  {
+    return &cff_driver_class;
+  }
+
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cffgload.c b/libraries/freetype-2.0.5/cffgload.c
new file mode 100644 (file)
index 0000000..508f2fa
--- /dev/null
@@ -0,0 +1,2293 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cffgload.c                                                             */
+/*                                                                         */
+/*    OpenType Glyph Loader (body).                                        */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_OUTLINE_H
+#include FT_TRUETYPE_TAGS_H
+
+#include "cffload.h"
+#include "cffgload.h"
+
+#include "cfferrs.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cffgload
+
+
+  typedef enum  CFF_Operator_
+  {
+    cff_op_unknown = 0,
+
+    cff_op_rmoveto,
+    cff_op_hmoveto,
+    cff_op_vmoveto,
+
+    cff_op_rlineto,
+    cff_op_hlineto,
+    cff_op_vlineto,
+
+    cff_op_rrcurveto,
+    cff_op_hhcurveto,
+    cff_op_hvcurveto,
+    cff_op_rcurveline,
+    cff_op_rlinecurve,
+    cff_op_vhcurveto,
+    cff_op_vvcurveto,
+
+    cff_op_flex,
+    cff_op_hflex,
+    cff_op_hflex1,
+    cff_op_flex1,
+
+    cff_op_endchar,
+
+    cff_op_hstem,
+    cff_op_vstem,
+    cff_op_hstemhm,
+    cff_op_vstemhm,
+
+    cff_op_hintmask,
+    cff_op_cntrmask,
+    cff_op_dotsection,  /* deprecated, acts as no-op */
+
+    cff_op_abs,
+    cff_op_add,
+    cff_op_sub,
+    cff_op_div,
+    cff_op_neg,
+    cff_op_random,
+    cff_op_mul,
+    cff_op_sqrt,
+
+    cff_op_blend,
+
+    cff_op_drop,
+    cff_op_exch,
+    cff_op_index,
+    cff_op_roll,
+    cff_op_dup,
+
+    cff_op_put,
+    cff_op_get,
+    cff_op_store,
+    cff_op_load,
+
+    cff_op_and,
+    cff_op_or,
+    cff_op_not,
+    cff_op_eq,
+    cff_op_ifelse,
+
+    cff_op_callsubr,
+    cff_op_callgsubr,
+    cff_op_return,
+
+    /* do not remove */
+    cff_op_max
+
+  } CFF_Operator;
+
+
+#define CFF_COUNT_CHECK_WIDTH  0x80
+#define CFF_COUNT_EXACT        0x40
+#define CFF_COUNT_CLEAR_STACK  0x20
+
+
+  static const FT_Byte  cff_argument_counts[] =
+  {
+    0,  /* unknown */
+
+    2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
+    1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
+    1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
+
+    0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
+    0 | CFF_COUNT_CLEAR_STACK,
+    0 | CFF_COUNT_CLEAR_STACK,
+
+    0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
+    0 | CFF_COUNT_CLEAR_STACK,
+    0 | CFF_COUNT_CLEAR_STACK,
+    0 | CFF_COUNT_CLEAR_STACK,
+    0 | CFF_COUNT_CLEAR_STACK,
+    0 | CFF_COUNT_CLEAR_STACK,
+    0 | CFF_COUNT_CLEAR_STACK,
+
+    13, /* flex */
+    7,
+    9,
+    11,
+
+    0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
+
+    2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
+    2 | CFF_COUNT_CHECK_WIDTH,
+    2 | CFF_COUNT_CHECK_WIDTH,
+    2 | CFF_COUNT_CHECK_WIDTH,
+
+    0, /* hintmask */
+    0, /* cntrmask */
+    0, /* dotsection */
+
+    1, /* abs */
+    2,
+    2,
+    2,
+    1,
+    0,
+    2,
+    1,
+
+    1, /* blend */
+
+    1, /* drop */
+    2,
+    1,
+    2,
+    1,
+
+    2, /* put */
+    1,
+    4,
+    3,
+
+    2, /* and */
+    2,
+    1,
+    2,
+    4,
+
+    1, /* callsubr */
+    1,
+    0
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********             GENERIC CHARSTRING PARSING               *********/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CFF_Init_Builder                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph builder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    builder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face    :: The current face object.                                */
+  /*                                                                       */
+  /*    size    :: The current size object.                                */
+  /*                                                                       */
+  /*    glyph   :: The current glyph object.                               */
+  /*                                                                       */
+  static void
+  CFF_Init_Builder( CFF_Builder*   builder,
+                    TT_Face        face,
+                    CFF_Size       size,
+                    CFF_GlyphSlot  glyph )
+  {
+    builder->path_begun  = 0;
+    builder->load_points = 1;
+
+    builder->face   = face;
+    builder->glyph  = glyph;
+    builder->memory = face->root.memory;
+
+    if ( glyph )
+    {
+      FT_GlyphLoader*  loader = glyph->root.internal->loader;
+
+
+      builder->loader  = loader;
+      builder->base    = &loader->base.outline;
+      builder->current = &loader->current.outline;
+      FT_GlyphLoader_Rewind( loader );
+    }
+
+    if ( size )
+    {
+      builder->scale_x = size->metrics.x_scale;
+      builder->scale_y = size->metrics.y_scale;
+    }
+
+    builder->pos_x = 0;
+    builder->pos_y = 0;
+
+    builder->left_bearing.x = 0;
+    builder->left_bearing.y = 0;
+    builder->advance.x      = 0;
+    builder->advance.y      = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CFF_Done_Builder                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given glyph builder.  Its contents can still be used   */
+  /*    after the call, but the function saves important information       */
+  /*    within the corresponding glyph slot.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    builder :: A pointer to the glyph builder to finalize.             */
+  /*                                                                       */
+  static void
+  CFF_Done_Builder( CFF_Builder*  builder )
+  {
+    CFF_GlyphSlot  glyph = builder->glyph;
+
+
+    if ( glyph )
+      glyph->root.outline = *builder->base;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    cff_compute_bias                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the bias value in dependence of the number of glyph       */
+  /*    subroutines.                                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    num_subrs :: The number of glyph subroutines.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The bias value.                                                    */
+  static FT_Int
+  cff_compute_bias( FT_UInt  num_subrs )
+  {
+    FT_Int  result;
+
+
+    if ( num_subrs < 1240 )
+      result = 107;
+    else if ( num_subrs < 33900U )
+      result = 1131;
+    else
+      result = 32768U;
+
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CFF_Init_Decoder                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph decoder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    decoder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face    :: The current face object.                                */
+  /*                                                                       */
+  /*    size    :: The current size object.                                */
+  /*                                                                       */
+  /*    slot    :: The current glyph object.                               */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  CFF_Init_Decoder( CFF_Decoder*   decoder,
+                    TT_Face        face,
+                    CFF_Size       size,
+                    CFF_GlyphSlot  slot )
+  {
+    CFF_Font*  cff = (CFF_Font*)face->extra.data;
+
+
+    /* clear everything */
+    MEM_Set( decoder, 0, sizeof ( *decoder ) );
+
+    /* initialize builder */
+    CFF_Init_Builder( &decoder->builder, face, size, slot );
+
+    /* initialize Type2 decoder */
+    decoder->num_globals  = cff->num_global_subrs;
+    decoder->globals      = cff->global_subrs;
+    decoder->globals_bias = cff_compute_bias( decoder->num_globals );
+  }
+
+
+  /* this function is used to select the locals subrs array */
+  FT_LOCAL_DEF void
+  CFF_Prepare_Decoder( CFF_Decoder*  decoder,
+                       FT_UInt       glyph_index )
+  {
+    CFF_Font*     cff = (CFF_Font*)decoder->builder.face->extra.data;
+    CFF_SubFont*  sub = &cff->top_font;
+
+
+    /* manage CID fonts */
+    if ( cff->num_subfonts >= 1 )
+    {
+      FT_Byte  fd_index = CFF_Get_FD( &cff->fd_select, glyph_index );
+
+
+      sub = cff->subfonts[fd_index];
+    }
+
+    decoder->num_locals    = sub->num_local_subrs;
+    decoder->locals        = sub->local_subrs;
+    decoder->locals_bias   = cff_compute_bias( decoder->num_locals );
+
+    decoder->glyph_width   = sub->private_dict.default_width;
+    decoder->nominal_width = sub->private_dict.nominal_width;
+  }
+
+
+  /* check that there is enough room for `count' more points */
+  static FT_Error
+  check_points( CFF_Builder*  builder,
+                FT_Int        count )
+  {
+    return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
+  }
+
+
+  /* add a new point, do not check space */
+  static void
+  add_point( CFF_Builder*  builder,
+             FT_Pos        x,
+             FT_Pos        y,
+             FT_Byte       flag )
+  {
+    FT_Outline*  outline = builder->current;
+
+
+    if ( builder->load_points )
+    {
+      FT_Vector*  point   = outline->points + outline->n_points;
+      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+
+
+      point->x = x >> 16;
+      point->y = y >> 16;
+      *control = (FT_Byte)( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
+
+      builder->last = *point;
+    }
+    outline->n_points++;
+  }
+
+
+  /* check space for a new on-curve point, then add it */
+  static FT_Error
+  add_point1( CFF_Builder*  builder,
+              FT_Pos        x,
+              FT_Pos        y )
+  {
+    FT_Error  error;
+
+
+    error = check_points( builder, 1 );
+    if ( !error )
+      add_point( builder, x, y, 1 );
+
+    return error;
+  }
+
+
+  /* check room for a new contour, then add it */
+  static FT_Error
+  add_contour( CFF_Builder*  builder )
+  {
+    FT_Outline*  outline = builder->current;
+    FT_Error     error;
+
+
+    if ( !builder->load_points )
+    {
+      outline->n_contours++;
+      return CFF_Err_Ok;
+    }
+
+    error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+    if ( !error )
+    {
+      if ( outline->n_contours > 0 )
+        outline->contours[outline->n_contours - 1] =
+          (short)( outline->n_points - 1 );
+
+      outline->n_contours++;
+    }
+
+    return error;
+  }
+
+
+  /* if a path was begun, add its first on-curve point */
+  static FT_Error
+  start_point( CFF_Builder*  builder,
+               FT_Pos        x,
+               FT_Pos        y )
+  {
+    FT_Error  error = 0;
+
+
+    /* test whether we are building a new contour */
+    if ( !builder->path_begun )
+    {
+      builder->path_begun = 1;
+      error = add_contour( builder );
+      if ( !error )
+        error = add_point1( builder, x, y );
+    }
+    return error;
+  }
+
+
+  /* close the current contour */
+  static void
+  close_contour( CFF_Builder*  builder )
+  {
+    FT_Outline*  outline = builder->current;
+
+    /* XXXX: We must not include the last point in the path if it */
+    /*       is located on the first point.                       */
+    if ( outline->n_points > 1 )
+    {
+      FT_Int      first   = 0;
+      FT_Vector*  p1      = outline->points + first;
+      FT_Vector*  p2      = outline->points + outline->n_points - 1;
+      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+
+
+      if ( outline->n_contours > 1 )
+      {
+        first = outline->contours[outline->n_contours - 2] + 1;
+        p1    = outline->points + first;
+      }
+
+      /* `delete' last point only if it coincides with the first */
+      /* point and it is not a control point (which can happen). */
+      if ( p1->x == p2->x && p1->y == p2->y )
+        if ( *control == FT_Curve_Tag_On )
+          outline->n_points--;
+    }
+
+    if ( outline->n_contours > 0 )
+      outline->contours[outline->n_contours - 1] =
+        (short)( outline->n_points - 1 );
+  }
+
+
+  static FT_Int
+  cff_lookup_glyph_by_stdcharcode( CFF_Font*  cff,
+                                   FT_Int     charcode )
+  {
+    FT_UInt    n;
+    FT_UShort  glyph_sid;
+
+
+    /* check range of standard char code */
+    if ( charcode < 0 || charcode > 255 )
+      return -1;
+
+
+    /* Get code to SID mapping from `cff_standard_encoding'. */
+    glyph_sid = cff_standard_encoding[charcode];
+
+    for ( n = 0; n < cff->num_glyphs; n++ )
+    {
+      if ( cff->charset.sids[n] == glyph_sid )
+        return n;
+    }
+
+    return -1;
+  }
+
+
+  static FT_Error
+  cff_operator_seac( CFF_Decoder*  decoder,
+                     FT_Pos        adx,
+                     FT_Pos        ady,
+                     FT_Int        bchar,
+                     FT_Int        achar )
+  {
+    FT_Error     error;
+    FT_Int       bchar_index, achar_index, n_base_points;
+    FT_Outline*  base = decoder->builder.base;
+    TT_Face      face = decoder->builder.face;
+    CFF_Font*    cff  = (CFF_Font*)(face->extra.data);
+    FT_Vector    left_bearing, advance;
+    FT_Byte*     charstring;
+    FT_ULong     charstring_len;
+
+
+    bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
+    achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
+
+    if ( bchar_index < 0 || achar_index < 0 )
+    {
+      FT_ERROR(( "cff_operator_seac:" ));
+      FT_ERROR(( " invalid seac character code arguments\n" ));
+      return CFF_Err_Syntax_Error;
+    }
+
+    /* If we are trying to load a composite glyph, do not load the */
+    /* accent character and return the array of subglyphs.         */
+    if ( decoder->builder.no_recurse )
+    {
+      FT_GlyphSlot     glyph  = (FT_GlyphSlot)decoder->builder.glyph;
+      FT_GlyphLoader*  loader = glyph->internal->loader;
+      FT_SubGlyph*     subg;
+
+
+      /* reallocate subglyph array if necessary */
+      error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+      if ( error )
+        goto Exit;
+
+      subg = loader->current.subglyphs;
+
+      /* subglyph 0 = base character */
+      subg->index = bchar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+      subg->arg1  = 0;
+      subg->arg2  = 0;
+      subg++;
+
+      /* subglyph 1 = accent character */
+      subg->index = achar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+      subg->arg1  = adx;
+      subg->arg2  = ady;
+
+      /* set up remaining glyph fields */
+      glyph->num_subglyphs = 2;
+      glyph->subglyphs     = loader->base.subglyphs;
+      glyph->format        = ft_glyph_format_composite;
+
+      loader->current.num_subglyphs = 2;
+    }
+
+    /* First load `bchar' in builder */
+    error = CFF_Access_Element( &cff->charstrings_index, bchar_index,
+                                &charstring, &charstring_len );
+    if ( !error )
+    {
+      error = CFF_Parse_CharStrings( decoder, charstring, charstring_len );
+
+      if ( error )
+        goto Exit;
+
+      CFF_Forget_Element( &cff->charstrings_index, &charstring );
+    }
+
+    n_base_points = base->n_points;
+
+    /* Save the left bearing and width of the base character */
+    /* as they will be erased by the next load.              */
+
+    left_bearing = decoder->builder.left_bearing;
+    advance      = decoder->builder.advance;
+
+    decoder->builder.left_bearing.x = 0;
+    decoder->builder.left_bearing.y = 0;
+
+    /* Now load `achar' on top of the base outline. */
+    error = CFF_Access_Element( &cff->charstrings_index, achar_index,
+                                &charstring, &charstring_len );
+    if ( !error )
+    {
+      error = CFF_Parse_CharStrings( decoder, charstring, charstring_len );
+
+      if ( error )
+        goto Exit;
+
+      CFF_Forget_Element( &cff->charstrings_index, &charstring );
+    }
+
+    /* Restore the left side bearing and advance width */
+    /* of the base character.                          */
+    decoder->builder.left_bearing = left_bearing;
+    decoder->builder.advance      = advance;
+
+    /* Finally, move the accent. */
+    if ( decoder->builder.load_points )
+    {
+      FT_Outline  dummy;
+
+
+      dummy.n_points = (short)( base->n_points - n_base_points );
+      dummy.points   = base->points   + n_base_points;
+
+      FT_Outline_Translate( &dummy, adx, ady );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CFF_Parse_CharStrings                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parses a given Type 2 charstrings program.                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    decoder         :: The current Type 1 decoder.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charstring_base :: The base of the charstring stream.              */
+  /*                                                                       */
+  /*    charstring_len  :: The length in bytes of the charstring stream.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  CFF_Parse_CharStrings( CFF_Decoder*  decoder,
+                         FT_Byte*      charstring_base,
+                         FT_Int        charstring_len )
+  {
+    FT_Error           error;
+    CFF_Decoder_Zone*  zone;
+    FT_Byte*           ip;
+    FT_Byte*           limit;
+    CFF_Builder*       builder = &decoder->builder;
+    FT_Pos             x, y;
+    FT_Fixed           seed;
+    FT_Fixed*          stack;
+
+
+    /* set default width */
+    decoder->num_hints  = 0;
+    decoder->read_width = 1;
+
+    /* compute random seed from stack address of parameter */
+    seed = (FT_Fixed)(char*)&seed           ^
+           (FT_Fixed)(char*)&decoder        ^
+           (FT_Fixed)(char*)&charstring_base;
+    seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFF;
+    if ( seed == 0 )
+      seed = 0x7384;
+
+    /* initialize the decoder */
+    decoder->top  = decoder->stack;
+    decoder->zone = decoder->zones;
+    zone          = decoder->zones;
+    stack         = decoder->top;
+
+    builder->path_begun = 0;
+
+    zone->base           = charstring_base;
+    limit = zone->limit  = charstring_base + charstring_len;
+    ip    = zone->cursor = zone->base;
+
+    error = CFF_Err_Ok;
+
+    x = builder->pos_x;
+    y = builder->pos_y;
+
+    /* now, execute loop */
+    while ( ip < limit )
+    {
+      CFF_Operator  op;
+      FT_Byte       v;
+
+
+      /********************************************************************/
+      /*                                                                  */
+      /* Decode operator or operand                                       */
+      /*                                                                  */
+      v = *ip++;
+      if ( v >= 32 || v == 28 )
+      {
+        FT_Int    shift = 16;
+        FT_Int32  val;
+
+
+        /* this is an operand, push it on the stack */
+        if ( v == 28 )
+        {
+          if ( ip + 1 >= limit )
+            goto Syntax_Error;
+          val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
+          ip += 2;
+        }
+        else if ( v < 247 )
+          val = (FT_Long)v - 139;
+        else if ( v < 251 )
+        {
+          if ( ip >= limit )
+            goto Syntax_Error;
+          val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
+        }
+        else if ( v < 255 )
+        {
+          if ( ip >= limit )
+            goto Syntax_Error;
+          val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
+        }
+        else
+        {
+          if ( ip + 3 >= limit )
+            goto Syntax_Error;
+          val = ( (FT_Int32)ip[0] << 24 ) |
+                ( (FT_Int32)ip[1] << 16 ) |
+                ( (FT_Int32)ip[2] <<  8 ) |
+                            ip[3];
+          ip    += 4;
+          shift  = 0;
+        }
+        if ( decoder->top - stack >= CFF_MAX_OPERANDS )
+          goto Stack_Overflow;
+
+        val           <<= shift;
+        *decoder->top++ = val;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        if ( !( val & 0xFFFF ) )
+          FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) ));
+        else
+          FT_TRACE4(( " %.2f", val / 65536.0 ));
+#endif
+
+      }
+      else
+      {
+        FT_Fixed*  args     = decoder->top;
+        FT_Int     num_args = args - decoder->stack;
+        FT_Int     req_args;
+
+
+        /* find operator */
+        op = cff_op_unknown;
+
+        switch ( v )
+        {
+        case 1:
+          op = cff_op_hstem;
+          break;
+        case 3:
+          op = cff_op_vstem;
+          break;
+        case 4:
+          op = cff_op_vmoveto;
+          break;
+        case 5:
+          op = cff_op_rlineto;
+          break;
+        case 6:
+          op = cff_op_hlineto;
+          break;
+        case 7:
+          op = cff_op_vlineto;
+          break;
+        case 8:
+          op = cff_op_rrcurveto;
+          break;
+        case 10:
+          op = cff_op_callsubr;
+          break;
+        case 11:
+          op = cff_op_return;
+          break;
+        case 12:
+          {
+            if ( ip >= limit )
+              goto Syntax_Error;
+            v = *ip++;
+
+            switch ( v )
+            {
+            case 0:
+              op = cff_op_dotsection;
+              break;
+            case 3:
+              op = cff_op_and;
+              break;
+            case 4:
+              op = cff_op_or;
+              break;
+            case 5:
+              op = cff_op_not;
+              break;
+            case 8:
+              op = cff_op_store;
+              break;
+            case 9:
+              op = cff_op_abs;
+              break;
+            case 10:
+              op = cff_op_add;
+              break;
+            case 11:
+              op = cff_op_sub;
+              break;
+            case 12:
+              op = cff_op_div;
+              break;
+            case 13:
+              op = cff_op_load;
+              break;
+            case 14:
+              op = cff_op_neg;
+              break;
+            case 15:
+              op = cff_op_eq;
+              break;
+            case 18:
+              op = cff_op_drop;
+              break;
+            case 20:
+              op = cff_op_put;
+              break;
+            case 21:
+              op = cff_op_get;
+              break;
+            case 22:
+              op = cff_op_ifelse;
+              break;
+            case 23:
+              op = cff_op_random;
+              break;
+            case 24:
+              op = cff_op_mul;
+              break;
+            case 26:
+              op = cff_op_sqrt;
+              break;
+            case 27:
+              op = cff_op_dup;
+              break;
+            case 28:
+              op = cff_op_exch;
+              break;
+            case 29:
+              op = cff_op_index;
+              break;
+            case 30:
+              op = cff_op_roll;
+              break;
+            case 34:
+              op = cff_op_hflex;
+              break;
+            case 35:
+              op = cff_op_flex;
+              break;
+            case 36:
+              op = cff_op_hflex1;
+              break;
+            case 37:
+              op = cff_op_flex1;
+              break;
+            default:
+              /* decrement ip for syntax error message */
+              ip--;
+            }
+          }
+          break;
+        case 14:
+          op = cff_op_endchar;
+          break;
+        case 16:
+          op = cff_op_blend;
+          break;
+        case 18:
+          op = cff_op_hstemhm;
+          break;
+        case 19:
+          op = cff_op_hintmask;
+          break;
+        case 20:
+          op = cff_op_cntrmask;
+          break;
+        case 21:
+          op = cff_op_rmoveto;
+          break;
+        case 22:
+          op = cff_op_hmoveto;
+          break;
+        case 23:
+          op = cff_op_vstemhm;
+          break;
+        case 24:
+          op = cff_op_rcurveline;
+          break;
+        case 25:
+          op = cff_op_rlinecurve;
+          break;
+        case 26:
+          op = cff_op_vvcurveto;
+          break;
+        case 27:
+          op = cff_op_hhcurveto;
+          break;
+        case 29:
+          op = cff_op_callgsubr;
+          break;
+        case 30:
+          op = cff_op_vhcurveto;
+          break;
+        case 31:
+          op = cff_op_hvcurveto;
+          break;
+        default:
+          ;
+        }
+        if ( op == cff_op_unknown )
+          goto Syntax_Error;
+
+        /* check arguments */
+        req_args = cff_argument_counts[op];
+        if ( req_args & CFF_COUNT_CHECK_WIDTH )
+        {
+          args = stack;
+
+          if ( num_args > 0 && decoder->read_width )
+          {
+            /* If `nominal_width' is non-zero, the number is really a      */
+            /* difference against `nominal_width'.  Else, the number here  */
+            /* is truly a width, not a difference against `nominal_width'. */
+            /* If the font does not set `nominal_width', then              */
+            /* `nominal_width' defaults to zero, and so we can set         */
+            /* `glyph_width' to `nominal_width' plus number on the stack   */
+            /* -- for either case.                                         */
+
+            FT_Int set_width_ok;
+
+
+            switch ( op )
+            {
+            case cff_op_hmoveto:
+            case cff_op_vmoveto:
+              set_width_ok = num_args & 2;
+              break;
+
+            case cff_op_hstem:
+            case cff_op_vstem:
+            case cff_op_hstemhm:
+            case cff_op_vstemhm:
+            case cff_op_rmoveto:
+              set_width_ok = num_args & 1;
+              break;
+
+            case cff_op_endchar:
+              /* If there is a width specified for endchar, we either have */
+              /* 1 argument or 5 arguments.  We like to argue.             */
+              set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) );
+              break;
+
+            default:
+              set_width_ok = 0;
+              break;
+            }
+
+            if ( set_width_ok )
+            {
+              decoder->glyph_width = decoder->nominal_width +
+                                       ( stack[0] >> 16 );
+
+              /* Consumed an argument. */
+              num_args--;
+              args++;
+            }
+          }
+
+          decoder->read_width = 0;
+          req_args            = 0;
+        }
+
+        req_args &= 15;
+        if ( num_args < req_args )
+          goto Stack_Underflow;
+        args     -= req_args;
+        num_args -= req_args;
+
+        switch ( op )
+        {
+        case cff_op_hstem:
+        case cff_op_vstem:
+        case cff_op_hstemhm:
+        case cff_op_vstemhm:
+          /* if the number of arguments is not even, the first one */
+          /* is simply the glyph width, encoded as the difference  */
+          /* to nominalWidthX                                      */
+          FT_TRACE4(( op == cff_op_hstem   ? " hstem"   :
+                      op == cff_op_vstem   ? " vstem"   :
+                      op == cff_op_hstemhm ? " hstemhm" :
+                                             " vstemhm" ));
+          decoder->num_hints += num_args / 2;
+          args = stack;
+          break;
+
+        case cff_op_hintmask:
+        case cff_op_cntrmask:
+          FT_TRACE4(( op == cff_op_hintmask ? " hintmask"
+                                            : " cntrmask" ));
+
+          decoder->num_hints += num_args / 2;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+          {
+            FT_UInt maskbyte;
+
+            FT_TRACE4(( " " ));
+
+            for ( maskbyte = 0;
+                  maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3);
+                  maskbyte++, ip++ )
+            {
+              FT_TRACE4(( "%02X", *ip ));
+            }
+
+          }
+#else
+          ip += ( decoder->num_hints + 7 ) >> 3;
+#endif
+          if ( ip >= limit )
+            goto Syntax_Error;
+          args = stack;
+          break;
+
+        case cff_op_rmoveto:
+          FT_TRACE4(( " rmoveto" ));
+
+          close_contour( builder );
+          builder->path_begun = 0;
+          x   += args[0];
+          y   += args[1];
+          args = stack;
+          break;
+
+        case cff_op_vmoveto:
+          FT_TRACE4(( " vmoveto" ));
+
+          close_contour( builder );
+          builder->path_begun = 0;
+          y   += args[0];
+          args = stack;
+          break;
+
+        case cff_op_hmoveto:
+          FT_TRACE4(( " hmoveto" ));
+
+          close_contour( builder );
+          builder->path_begun = 0;
+          x   += args[0];
+          args = stack;
+          break;
+
+        case cff_op_rlineto:
+          FT_TRACE4(( " rlineto" ));
+
+          if ( start_point ( builder, x, y )         ||
+               check_points( builder, num_args / 2 ) )
+            goto Memory_Error;
+
+          if ( num_args < 2 || num_args & 1 )
+            goto Stack_Underflow;
+
+          args = stack;
+          while ( args < decoder->top )
+          {
+            x += args[0];
+            y += args[1];
+            add_point( builder, x, y, 1 );
+            args += 2;
+          }
+          args = stack;
+          break;
+
+        case cff_op_hlineto:
+        case cff_op_vlineto:
+          {
+            FT_Int  phase = ( op == cff_op_hlineto );
+
+
+            FT_TRACE4(( op == cff_op_hlineto ? " hlineto"
+                                             : " vlineto" ));
+
+            if ( start_point ( builder, x, y )     ||
+                 check_points( builder, num_args ) )
+              goto Memory_Error;
+
+            args = stack;
+            while (args < decoder->top )
+            {
+              if ( phase )
+                x += args[0];
+              else
+                y += args[0];
+
+              if ( add_point1( builder, x, y ) )
+                goto Memory_Error;
+
+              args++;
+              phase ^= 1;
+            }
+            args = stack;
+          }
+          break;
+
+        case cff_op_rrcurveto:
+          FT_TRACE4(( " rrcurveto" ));
+
+          /* check number of arguments; must be a multiple of 6 */
+          if ( num_args % 6 != 0 )
+            goto Stack_Underflow;
+
+          if ( start_point ( builder, x, y )         ||
+               check_points( builder, num_args / 2 ) )
+            goto Memory_Error;
+
+          args = stack;
+          while ( args < decoder->top )
+          {
+            x += args[0];
+            y += args[1];
+            add_point( builder, x, y, 0 );
+            x += args[2];
+            y += args[3];
+            add_point( builder, x, y, 0 );
+            x += args[4];
+            y += args[5];
+            add_point( builder, x, y, 1 );
+            args += 6;
+          }
+          args = stack;
+          break;
+
+        case cff_op_vvcurveto:
+          FT_TRACE4(( " vvcurveto" ));
+
+          if ( start_point ( builder, x, y ) )
+            goto Memory_Error;
+
+          args = stack;
+          if ( num_args & 1 )
+          {
+            x += args[0];
+            args++;
+            num_args--;
+          }
+
+          if ( num_args % 4 != 0 )
+            goto Stack_Underflow;
+
+          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
+            goto Memory_Error;
+
+          while ( args < decoder->top )
+          {
+            y += args[0];
+            add_point( builder, x, y, 0 );
+            x += args[1];
+            y += args[2];
+            add_point( builder, x, y, 0 );
+            y += args[3];
+            add_point( builder, x, y, 1 );
+            args += 4;
+          }
+          args = stack;
+          break;
+
+        case cff_op_hhcurveto:
+          FT_TRACE4(( " hhcurveto" ));
+
+          if ( start_point ( builder, x, y ) )
+            goto Memory_Error;
+
+          args = stack;
+          if ( num_args & 1 )
+          {
+            y += args[0];
+            args++;
+            num_args--;
+          }
+
+          if ( num_args % 4 != 0 )
+            goto Stack_Underflow;
+
+          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
+            goto Memory_Error;
+
+          while ( args < decoder->top )
+          {
+            x += args[0];
+            add_point( builder, x, y, 0 );
+            x += args[1];
+            y += args[2];
+            add_point( builder, x, y, 0 );
+            x += args[3];
+            add_point( builder, x, y, 1 );
+            args += 4;
+          }
+          args = stack;
+          break;
+
+        case cff_op_vhcurveto:
+        case cff_op_hvcurveto:
+          {
+            FT_Int  phase;
+
+
+            FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto"
+                                               : " hvcurveto" ));
+
+            if ( start_point ( builder, x, y ) )
+              goto Memory_Error;
+
+            args = stack;
+            if (num_args < 4 || ( num_args % 4 ) > 1 )
+              goto Stack_Underflow;
+
+            if ( check_points( builder, ( num_args / 4 ) * 3 ) )
+              goto Stack_Underflow;
+
+            phase = ( op == cff_op_hvcurveto );
+
+            while ( num_args >= 4 )
+            {
+              num_args -= 4;
+              if ( phase )
+              {
+                x += args[0];
+                add_point( builder, x, y, 0 );
+                x += args[1];
+                y += args[2];
+                add_point( builder, x, y, 0 );
+                y += args[3];
+                if ( num_args == 1 )
+                  x += args[4];
+                add_point( builder, x, y, 1 );
+              }
+              else
+              {
+                y += args[0];
+                add_point( builder, x, y, 0 );
+                x += args[1];
+                y += args[2];
+                add_point( builder, x, y, 0 );
+                x += args[3];
+                if ( num_args == 1 )
+                  y += args[4];
+                add_point( builder, x, y, 1 );
+              }
+              args  += 4;
+              phase ^= 1;
+            }
+            args = stack;
+          }
+          break;
+
+        case cff_op_rlinecurve:
+          {
+            FT_Int  num_lines = ( num_args - 6 ) / 2;
+
+
+            FT_TRACE4(( " rlinecurve" ));
+
+            if ( num_args < 8 || ( num_args - 6 ) & 1 )
+              goto Stack_Underflow;
+
+            if ( start_point( builder, x, y )           ||
+                 check_points( builder, num_lines + 3 ) )
+              goto Memory_Error;
+
+            args = stack;
+
+            /* first, add the line segments */
+            while ( num_lines > 0 )
+            {
+              x += args[0];
+              y += args[1];
+              add_point( builder, x, y, 1 );
+              args += 2;
+              num_lines--;
+            }
+
+            /* then the curve */
+            x += args[0];
+            y += args[1];
+            add_point( builder, x, y, 0 );
+            x += args[2];
+            y += args[3];
+            add_point( builder, x, y, 0 );
+            x += args[4];
+            y += args[5];
+            add_point( builder, x, y, 1 );
+            args = stack;
+          }
+          break;
+
+        case cff_op_rcurveline:
+          {
+            FT_Int  num_curves = ( num_args - 2 ) / 6;
+
+
+            FT_TRACE4(( " rcurveline" ));
+
+            if ( num_args < 8 || ( num_args - 2 ) % 6 )
+              goto Stack_Underflow;
+
+            if ( start_point ( builder, x, y )             ||
+                 check_points( builder, num_curves*3 + 2 ) )
+              goto Memory_Error;
+
+            args = stack;
+
+            /* first, add the curves */
+            while ( num_curves > 0 )
+            {
+              x += args[0];
+              y += args[1];
+              add_point( builder, x, y, 0 );
+              x += args[2];
+              y += args[3];
+              add_point( builder, x, y, 0 );
+              x += args[4];
+              y += args[5];
+              add_point( builder, x, y, 1 );
+              args += 6;
+              num_curves--;
+            }
+
+            /* then the final line */
+            x += args[0];
+            y += args[1];
+            add_point( builder, x, y, 1 );
+            args = stack;
+          }
+          break;
+
+        case cff_op_hflex1:
+          {
+            FT_Pos start_y;
+
+
+            FT_TRACE4(( " hflex1" ));
+
+            args = stack;
+
+            /* adding five more points; 4 control points, 1 on-curve point */
+            /* make sure we have enough space for the start point if it    */
+            /* needs to be added..                                         */
+            if ( start_point( builder, x, y ) ||
+                 check_points( builder, 6 )   )
+              goto Memory_Error;
+
+            /* Record the starting point's y postion for later use */
+            start_y = y;
+
+            /* first control point */
+            x += args[0];
+            y += args[1];
+            add_point( builder, x, y, 0 );
+
+            /* second control point */
+            x += args[2];
+            y += args[3];
+            add_point( builder, x, y, 0 );
+
+            /* join point; on curve, with y-value the same as the last */
+            /* control point's y-value                                 */
+            x += args[4];
+            add_point( builder, x, y, 1 );
+
+            /* third control point, with y-value the same as the join */
+            /* point's y-value                                        */
+            x += args[5];
+            add_point( builder, x, y, 0 );
+
+            /* fourth control point */
+            x += args[6];
+            y += args[7];
+            add_point( builder, x, y, 0 );
+
+            /* ending point, with y-value the same as the start   */
+            x += args[8];
+            y  = start_y;
+            add_point( builder, x, y, 1 );
+
+            args = stack;
+            break;
+          }
+
+        case cff_op_hflex:
+          {
+            FT_Pos start_y;
+
+
+            FT_TRACE4(( " hflex" ));
+
+            args = stack;
+
+            /* adding six more points; 4 control points, 2 on-curve points */
+            if ( start_point( builder, x, y ) ||
+                 check_points ( builder, 6 )  )
+              goto Memory_Error;
+
+            /* record the starting point's y-position for later use */
+            start_y = y;
+
+            /* first control point */
+            x += args[0];
+            add_point( builder, x, y, 0 );
+
+            /* second control point */
+            x += args[1];
+            y += args[2];
+            add_point( builder, x, y, 0 );
+
+            /* join point; on curve, with y-value the same as the last */
+            /* control point's y-value                                 */
+            x += args[3];
+            add_point( builder, x, y, 1 );
+
+            /* third control point, with y-value the same as the join */
+            /* point's y-value                                        */
+            x += args[4];
+            add_point( builder, x, y, 0 );
+
+            /* fourth control point */
+            x += args[5];
+            y  = start_y;
+            add_point( builder, x, y, 0 );
+
+            /* ending point, with y-value the same as the start point's */
+            /* y-value -- we don't add this point, though               */
+            x += args[6];
+            add_point( builder, x, y, 1 );
+
+            args = stack;
+            break;
+          }
+
+        case cff_op_flex1:
+          {
+            FT_Pos  start_x, start_y; /* record start x, y values for alter */
+                                      /* use                                */
+            FT_Int  dx = 0, dy = 0;   /* used in horizontal/vertical        */
+                                      /* algorithm below                    */
+            FT_Int  horizontal, count;
+
+
+            FT_TRACE4(( " flex1" ));
+
+            /* adding six more points; 4 control points, 2 on-curve points */
+            if ( start_point( builder, x, y ) ||
+                 check_points( builder, 6 )   )
+               goto Memory_Error;
+
+            /* record the starting point's x, y postion for later use */
+            start_x = x;
+            start_y = y;
+
+            /* XXX: figure out whether this is supposed to be a horizontal */
+            /*      or vertical flex; the Type 2 specification is vague... */
+
+            args = stack;
+
+            /* grab up to the last argument */
+            for ( count = 5; count > 0; count-- )
+            {
+              dx += args[0];
+              dy += args[1];
+              args += 2;
+            }
+
+            /* rewind */
+            args = stack;
+
+            if ( dx < 0 ) dx = -dx;
+            if ( dy < 0 ) dy = -dy;
+
+            /* strange test, but here it is... */
+            horizontal = ( dx > dy );
+
+            for ( count = 5; count > 0; count-- )
+            {
+              x += args[0];
+              y += args[1];
+              add_point( builder, x, y, (FT_Bool)( count == 3 ) );
+              args += 2;
+            }
+
+            /* is last operand an x- or y-delta? */
+            if ( horizontal )
+            {
+              x += args[0];
+              y  = start_y;
+            }
+            else
+            {
+              x  = start_x;
+              y += args[0];
+            }
+
+            add_point( builder, x, y, 1 );
+
+            args = stack;
+            break;
+           }
+
+        case cff_op_flex:
+          {
+            FT_UInt  count;
+
+
+            FT_TRACE4(( " flex" ));
+
+            if ( start_point( builder, x, y ) ||
+                 check_points( builder, 6 )   )
+              goto Memory_Error;
+
+            args = stack;
+            for ( count = 6; count > 0; count-- )
+            {
+              x += args[0];
+              y += args[1];
+              add_point( builder, x, y,
+                         (FT_Bool)( count == 3 || count == 0 ) );
+              args += 2;
+            }
+
+            args = stack;
+          }
+          break;
+
+        case cff_op_endchar:
+          FT_TRACE4(( " endchar" ));
+
+          /* We are going to emulate the seac operator. */
+          if ( num_args == 4 )
+          {
+            error = cff_operator_seac( decoder,
+                                       args[0] >> 16, args[1] >> 16,
+                                       args[2] >> 16, args[3] >> 16 );
+            args += 4;
+          }
+
+          if ( !error )
+            error = CFF_Err_Ok;
+
+          close_contour( builder );
+
+          /* add current outline to the glyph slot */
+          FT_GlyphLoader_Add( builder->loader );
+
+          /* return now! */
+          FT_TRACE4(( "\n\n" ));
+          return error;
+
+        case cff_op_abs:
+          FT_TRACE4(( " abs" ));
+
+          if ( args[0] < 0 )
+            args[0] = -args[0];
+          args++;
+          break;
+
+        case cff_op_add:
+          FT_TRACE4(( " add" ));
+
+          args[0] += args[1];
+          args++;
+          break;
+
+        case cff_op_sub:
+          FT_TRACE4(( " sub" ));
+
+          args[0] -= args[1];
+          args++;
+          break;
+
+        case cff_op_div:
+          FT_TRACE4(( " div" ));
+
+          args[0] = FT_DivFix( args[0], args[1] );
+          args++;
+          break;
+
+        case cff_op_neg:
+          FT_TRACE4(( " neg" ));
+
+          args[0] = -args[0];
+          args++;
+          break;
+
+        case cff_op_random:
+          {
+            FT_Fixed  rand;
+
+
+            FT_TRACE4(( " rand" ));
+
+            rand = seed;
+            if ( rand >= 0x8000 )
+              rand++;
+
+            args[0] = rand;
+            seed    = FT_MulFix( seed, 0x10000L - seed );
+            if ( seed == 0 )
+              seed += 0x2873;
+            args++;
+          }
+          break;
+
+        case cff_op_mul:
+          FT_TRACE4(( " mul" ));
+
+          args[0] = FT_MulFix( args[0], args[1] );
+          args++;
+          break;
+
+        case cff_op_sqrt:
+          FT_TRACE4(( " sqrt" ));
+
+          if ( args[0] > 0 )
+          {
+            FT_Int    count = 9;
+            FT_Fixed  root  = args[0];
+            FT_Fixed  new_root;
+
+
+            for (;;)
+            {
+              new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
+              if ( new_root == root || count <= 0 )
+                break;
+              root = new_root;
+            }
+            args[0] = new_root;
+          }
+          else
+            args[0] = 0;
+          args++;
+          break;
+
+        case cff_op_drop:
+          /* nothing */
+          FT_TRACE4(( " drop" ));
+
+          break;
+
+        case cff_op_exch:
+          {
+            FT_Fixed  tmp;
+
+
+            FT_TRACE4(( " exch" ));
+
+            tmp     = args[0];
+            args[0] = args[1];
+            args[1] = tmp;
+            args   += 2;
+          }
+          break;
+
+        case cff_op_index:
+          {
+            FT_Int  index = args[0] >> 16;
+
+
+            FT_TRACE4(( " index" ));
+
+            if ( index < 0 )
+              index = 0;
+            else if ( index > num_args - 2 )
+              index = num_args - 2;
+            args[0] = args[-( index + 1 )];
+            args++;
+          }
+          break;
+
+        case cff_op_roll:
+          {
+            FT_Int  count = (FT_Int)( args[0] >> 16 );
+            FT_Int  index = (FT_Int)( args[1] >> 16 );
+
+
+            FT_TRACE4(( " roll" ));
+
+            if ( count <= 0 )
+              count = 1;
+
+            args -= count;
+            if ( args < stack )
+              goto Stack_Underflow;
+
+            if ( index >= 0 )
+            {
+              while ( index > 0 )
+              {
+                FT_Fixed  tmp = args[count - 1];
+                FT_Int    i;
+
+
+                for ( i = count - 2; i >= 0; i-- )
+                  args[i + 1] = args[i];
+                args[0] = tmp;
+                index--;
+              }
+            }
+            else
+            {
+              while ( index < 0 )
+              {
+                FT_Fixed  tmp = args[0];
+                FT_Int    i;
+
+
+                for ( i = 0; i < count - 1; i++ )
+                  args[i] = args[i + 1];
+                args[count - 1] = tmp;
+                index++;
+              }
+            }
+            args += count;
+          }
+          break;
+
+        case cff_op_dup:
+          FT_TRACE4(( " dup" ));
+
+          args[1] = args[0];
+          args++;
+          break;
+
+        case cff_op_put:
+          {
+            FT_Fixed  val   = args[0];
+            FT_Int    index = (FT_Int)( args[1] >> 16 );
+
+
+            FT_TRACE4(( " put" ));
+
+            if ( index >= 0 && index < decoder->len_buildchar )
+              decoder->buildchar[index] = val;
+          }
+          break;
+
+        case cff_op_get:
+          {
+            FT_Int   index = (FT_Int)( args[0] >> 16 );
+            FT_Fixed val   = 0;
+
+
+            FT_TRACE4(( " get" ));
+
+            if ( index >= 0 && index < decoder->len_buildchar )
+              val = decoder->buildchar[index];
+
+            args[0] = val;
+            args++;
+          }
+          break;
+
+        case cff_op_store:
+          FT_TRACE4(( " store "));
+
+          goto Unimplemented;
+
+        case cff_op_load:
+          FT_TRACE4(( " load" ));
+
+          goto Unimplemented;
+
+        case cff_op_dotsection:
+          /* this operator is deprecated and ignored by the parser */
+          FT_TRACE4(( " dotsection" ));
+          break;
+
+        case cff_op_and:
+          {
+            FT_Fixed  cond = args[0] && args[1];
+
+
+            FT_TRACE4(( " and" ));
+
+            args[0] = cond ? 0x10000L : 0;
+            args++;
+          }
+          break;
+
+        case cff_op_or:
+          {
+            FT_Fixed  cond = args[0] || args[1];
+
+
+            FT_TRACE4(( " or" ));
+
+            args[0] = cond ? 0x10000L : 0;
+            args++;
+          }
+          break;
+
+        case cff_op_eq:
+          {
+            FT_Fixed  cond = !args[0];
+
+
+            FT_TRACE4(( " eq" ));
+
+            args[0] = cond ? 0x10000L : 0;
+            args++;
+          }
+          break;
+
+        case cff_op_ifelse:
+          {
+            FT_Fixed  cond = (args[2] <= args[3]);
+
+
+            FT_TRACE4(( " ifelse" ));
+
+            if ( !cond )
+              args[0] = args[1];
+            args++;
+          }
+          break;
+
+        case cff_op_callsubr:
+          {
+            FT_UInt  index = (FT_UInt)( ( args[0] >> 16 ) +
+                                        decoder->locals_bias );
+
+
+            FT_TRACE4(( " callsubr(%d)", index ));
+
+            if ( index >= decoder->num_locals )
+            {
+              FT_ERROR(( "CFF_Parse_CharStrings:" ));
+              FT_ERROR(( "  invalid local subr index\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
+            {
+              FT_ERROR(( "CFF_Parse_CharStrings: too many nested subrs\n" ));
+              goto Syntax_Error;
+            }
+
+            zone->cursor = ip;  /* save current instruction pointer */
+
+            zone++;
+            zone->base   = decoder->locals[index];
+            zone->limit  = decoder->locals[index + 1];
+            zone->cursor = zone->base;
+
+            if ( !zone->base )
+            {
+              FT_ERROR(( "CFF_Parse_CharStrings: invoking empty subrs!\n" ));
+              goto Syntax_Error;
+            }
+
+            decoder->zone = zone;
+            ip            = zone->base;
+            limit         = zone->limit;
+          }
+          break;
+
+        case cff_op_callgsubr:
+          {
+            FT_UInt  index = (FT_UInt)( ( args[0] >> 16 ) +
+                                        decoder->globals_bias );
+
+
+            FT_TRACE4(( " callgsubr(%d)", index ));
+
+            if ( index >= decoder->num_globals )
+            {
+              FT_ERROR(( "CFF_Parse_CharStrings:" ));
+              FT_ERROR(( " invalid global subr index\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
+            {
+              FT_ERROR(( "CFF_Parse_CharStrings: too many nested subrs\n" ));
+              goto Syntax_Error;
+            }
+
+            zone->cursor = ip;  /* save current instruction pointer */
+
+            zone++;
+            zone->base   = decoder->globals[index];
+            zone->limit  = decoder->globals[index+1];
+            zone->cursor = zone->base;
+
+            if ( !zone->base )
+            {
+              FT_ERROR(( "CFF_Parse_CharStrings: invoking empty subrs!\n" ));
+              goto Syntax_Error;
+            }
+
+            decoder->zone = zone;
+            ip            = zone->base;
+            limit         = zone->limit;
+          }
+          break;
+
+        case cff_op_return:
+          FT_TRACE4(( " return" ));
+
+          if ( decoder->zone <= decoder->zones )
+          {
+            FT_ERROR(( "CFF_Parse_CharStrings: unexpected return\n" ));
+            goto Syntax_Error;
+          }
+
+          decoder->zone--;
+          zone  = decoder->zone;
+          ip    = zone->cursor;
+          limit = zone->limit;
+          break;
+
+        default:
+        Unimplemented:
+          FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
+
+          if ( ip[-1] == 12 )
+            FT_ERROR(( " %d", ip[0] ));
+          FT_ERROR(( "\n" ));
+
+          return CFF_Err_Unimplemented_Feature;
+        }
+
+      decoder->top = args;
+
+      } /* general operator processing */
+
+    } /* while ip < limit */
+
+    FT_TRACE4(( "..end..\n\n" ));
+
+    return error;
+
+  Syntax_Error:
+    FT_TRACE4(( "CFF_Parse_CharStrings: syntax error!" ));
+    return CFF_Err_Invalid_File_Format;
+
+  Stack_Underflow:
+    FT_TRACE4(( "CFF_Parse_CharStrings: stack underflow!" ));
+    return CFF_Err_Too_Few_Arguments;
+
+  Stack_Overflow:
+    FT_TRACE4(( "CFF_Parse_CharStrings: stack overflow!" ));
+    return CFF_Err_Stack_Overflow;
+
+  Memory_Error:
+    return builder->error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of computing      *********/
+  /**********    the maximum advance width of the font.  It        *********/
+  /**********    quickly processes each glyph charstring to        *********/
+  /**********    extract the value from either a `sbw' or `seac'   *********/
+  /**********    operator.                                         *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#if 0 /* unused until we support pure CFF fonts */
+
+
+  FT_LOCAL_DEF FT_Error
+  CFF_Compute_Max_Advance( TT_Face  face,
+                           FT_Int*  max_advance )
+  {
+    FT_Error     error = 0;
+    CFF_Decoder  decoder;
+    FT_Int       glyph_index;
+    CFF_Font*    cff = (CFF_Font*)face->other;
+
+
+    *max_advance = 0;
+
+    /* Initialize load decoder */
+    CFF_Init_Decoder( &decoder, face, 0, 0 );
+
+    decoder.builder.metrics_only = 1;
+    decoder.builder.load_points  = 0;
+
+    /* For each glyph, parse the glyph charstring and extract */
+    /* the advance width.                                     */
+    for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
+          glyph_index++ )
+    {
+      FT_Byte*  charstring;
+      FT_ULong  charstring_len;
+
+
+      /* now get load the unscaled outline */
+      error = CFF_Access_Element( &cff->charstrings_index, glyph_index,
+                                  &charstring, &charstring_len );
+      if ( !error )
+      {
+        CFF_Prepare_Decoder( &decoder, glyph_index );
+        error = CFF_Parse_CharStrings( &decoder, charstring, charstring_len );
+
+        CFF_Forget_Element( &cff->charstrings_index, &charstring );
+      }
+
+      /* ignore the error if one has occurred -- skip to next glyph */
+      error = 0;
+    }
+
+    *max_advance = decoder.builder.advance.x;
+
+    return CFF_Err_Ok;
+  }
+
+
+#endif /* 0 */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********               UNHINTED GLYPH LOADER                  *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of loading a      *********/
+  /**********    single outline.  It completely ignores hinting    *********/
+  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_LOCAL_DEF FT_Error
+  CFF_Load_Glyph( CFF_GlyphSlot  glyph,
+                  CFF_Size       size,
+                  FT_Int         glyph_index,
+                  FT_Int         load_flags )
+  {
+    FT_Error     error;
+    CFF_Decoder  decoder;
+    TT_Face      face = (TT_Face)glyph->root.face;
+    FT_Bool      hinting;
+    CFF_Font*    cff = (CFF_Font*)face->extra.data;
+
+    FT_Matrix    font_matrix;
+    FT_Vector    font_offset;
+
+
+    if ( load_flags & FT_LOAD_NO_RECURSE )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    glyph->x_scale = 0x10000L;
+    glyph->y_scale = 0x10000L;
+    if ( size )
+    {
+      glyph->x_scale = size->metrics.x_scale;
+      glyph->y_scale = size->metrics.y_scale;
+    }
+
+    glyph->root.outline.n_points   = 0;
+    glyph->root.outline.n_contours = 0;
+
+    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
+                       ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
+
+    glyph->root.format = ft_glyph_format_outline;  /* by default */
+
+    {
+      FT_Byte*  charstring;
+      FT_ULong  charstring_len;
+
+
+      CFF_Init_Decoder( &decoder, face, size, glyph );
+
+      decoder.builder.no_recurse =
+        (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
+
+      /* now load the unscaled outline */
+      error = CFF_Access_Element( &cff->charstrings_index, glyph_index,
+                                  &charstring, &charstring_len );
+      if ( !error )
+      {
+        CFF_Index csindex = cff->charstrings_index;
+
+
+        CFF_Prepare_Decoder( &decoder, glyph_index );
+        error = CFF_Parse_CharStrings( &decoder, charstring, charstring_len );
+
+        CFF_Forget_Element( &cff->charstrings_index, &charstring );
+
+        /* We set control_data and control_len if charstrings is loaded.  */
+        /* See how charstring loads at CFF_Access_Element() in cffload.c. */
+
+        glyph->root.control_data =
+          csindex.bytes + csindex.offsets[glyph_index] - 1;
+        glyph->root.control_len =
+          charstring_len;
+      }
+
+      /* save new glyph tables */
+      CFF_Done_Builder( &decoder.builder );
+    }
+
+    font_matrix = cff->top_font.font_dict.font_matrix;
+    font_offset = cff->top_font.font_dict.font_offset;
+
+    /* Now, set the metrics -- this is rather simple, as   */
+    /* the left side bearing is the xMin, and the top side */
+    /* bearing the yMax.                                   */
+    if ( !error )
+    {
+      /* For composite glyphs, return only left side bearing and */
+      /* advance width.                                          */
+      if ( load_flags & FT_LOAD_NO_RECURSE )
+      {
+        FT_Slot_Internal  internal = glyph->root.internal;
+
+
+        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+        glyph->root.metrics.horiAdvance  = decoder.glyph_width;
+        internal->glyph_matrix           = font_matrix;
+        internal->glyph_delta            = font_offset;
+        internal->glyph_transformed      = 1;
+      }
+      else
+      {
+        FT_BBox            cbox;
+        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
+
+
+        /* copy the _unscaled_ advance width */
+        metrics->horiAdvance                    = decoder.glyph_width;
+        glyph->root.linearHoriAdvance           = decoder.glyph_width;
+        glyph->root.internal->glyph_transformed = 0;
+
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+
+        glyph->root.linearVertAdvance = 0;
+
+        glyph->root.format = ft_glyph_format_outline;
+
+        glyph->root.outline.flags = 0;
+        if ( size && size->metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+
+        glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+        /* apply the font matrix */
+        FT_Outline_Transform( &glyph->root.outline, &font_matrix );
+
+        FT_Outline_Translate( &glyph->root.outline,
+                              font_offset.x,
+                              font_offset.y );
+
+        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        {
+          /* scale the outline and the metrics */
+          FT_Int       n;
+          FT_Outline*  cur     = &glyph->root.outline;
+          FT_Vector*   vec     = cur->points;
+          FT_Fixed     x_scale = glyph->x_scale;
+          FT_Fixed     y_scale = glyph->y_scale;
+
+
+          /* First of all, scale the points */
+          for ( n = cur->n_points; n > 0; n--, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
+
+          FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+          /* Then scale the metrics */
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
+
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+        }
+
+        /* compute the other metrics */
+        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+        /* grid fit the bounding box if necessary */
+        if ( hinting )
+        {
+          cbox.xMin &= -64;
+          cbox.yMin &= -64;
+          cbox.xMax  = ( cbox.xMax + 63 ) & -64;
+          cbox.yMax  = ( cbox.yMax + 63 ) & -64;
+        }
+
+        metrics->width  = cbox.xMax - cbox.xMin;
+        metrics->height = cbox.yMax - cbox.yMin;
+
+        metrics->horiBearingX = cbox.xMin;
+        metrics->horiBearingY = cbox.yMax;
+      }
+    }
+
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cffload.c b/libraries/freetype-2.0.5/cffload.c
new file mode 100644 (file)
index 0000000..e236fdc
--- /dev/null
@@ -0,0 +1,1244 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cffload.c                                                              */
+/*                                                                         */
+/*    OpenType and CFF data/program tables loader (body)                   */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+#include FT_TRUETYPE_TAGS_H
+
+#include "cffload.h"
+#include "cffparse.h"
+
+#include "cfferrs.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cffload
+
+  /* read a CFF offset from memory */
+  static FT_ULong
+  cff_get_offset( FT_Byte*  p,
+                  FT_Byte   off_size )
+  {
+    FT_ULong  result;
+
+
+    for ( result = 0; off_size > 0; off_size-- )
+    {
+      result <<= 8;
+      result  |= *p++;
+    }
+
+    return result;
+  }
+
+
+  static FT_Error
+  cff_new_index( CFF_Index*  index,
+                 FT_Stream   stream,
+                 FT_Bool     load )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+    FT_UShort  count;
+
+
+    MEM_Set( index, 0, sizeof ( *index ) );
+
+    index->stream = stream;
+    if ( !READ_UShort( count ) &&
+         count > 0             )
+    {
+      FT_Byte*   p;
+      FT_Byte    offsize;
+      FT_ULong   data_size;
+      FT_ULong*  poff;
+
+
+      /* there is at least one element; read the offset size,           */
+      /* then access the offset table to compute the index's total size */
+      if ( READ_Byte( offsize ) )
+        goto Exit;
+
+      index->stream   = stream;
+      index->count    = count;
+      index->off_size = offsize;
+      data_size       = (FT_ULong)( count + 1 ) * offsize;
+
+      if ( ALLOC_ARRAY( index->offsets, count + 1, FT_ULong ) ||
+           ACCESS_Frame( data_size )                          )
+        goto Exit;
+
+      poff = index->offsets;
+      p    = (FT_Byte*)stream->cursor;
+
+      for ( ; (FT_Short)count >= 0; count-- )
+      {
+        poff[0] = cff_get_offset( p, offsize );
+        poff++;
+        p += offsize;
+      }
+
+      FORGET_Frame();
+
+      index->data_offset = FILE_Pos();
+      data_size          = poff[-1] - 1;
+
+      if ( load )
+      {
+        /* load the data */
+        if ( EXTRACT_Frame( data_size, index->bytes ) )
+          goto Exit;
+      }
+      else
+      {
+        /* skip the data */
+        if ( FILE_Skip( data_size ) )
+          goto Exit;
+      }
+    }
+
+  Exit:
+    if ( error )
+      FREE( index->offsets );
+
+    return error;
+  }
+
+
+  static void
+  cff_done_index( CFF_Index*  index )
+  {
+    if ( index->stream )
+    {
+      FT_Stream  stream = index->stream;
+      FT_Memory  memory = stream->memory;
+
+
+      if ( index->bytes )
+        RELEASE_Frame( index->bytes );
+
+      FREE( index->offsets );
+      MEM_Set( index, 0, sizeof ( *index ) );
+    }
+  }
+
+
+  static FT_Error
+  cff_explicit_index( CFF_Index*  index,
+                      FT_Byte***  table )
+  {
+    FT_Error   error  = 0;
+    FT_Memory  memory = index->stream->memory;
+    FT_UInt    n, offset, old_offset;
+    FT_Byte**  t;
+
+
+    *table = 0;
+
+    if ( index->count > 0 && !ALLOC_ARRAY( t, index->count + 1, FT_Byte* ) )
+    {
+      old_offset = 1;
+      for ( n = 0; n <= index->count; n++ )
+      {
+        offset = index->offsets[n];
+        if ( !offset )
+          offset = old_offset;
+
+        t[n] = index->bytes + offset - 1;
+
+        old_offset = offset;
+      }
+      *table = t;
+    }
+
+    return error;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  CFF_Access_Element( CFF_Index*  index,
+                      FT_UInt     element,
+                      FT_Byte**   pbytes,
+                      FT_ULong*   pbyte_len )
+  {
+    FT_Error  error = 0;
+
+
+    if ( index && index->count > element )
+    {
+      /* compute start and end offsets */
+      FT_ULong  off1, off2 = 0;
+
+
+      off1 = index->offsets[element];
+      if ( off1 )
+      {
+        do
+        {
+          element++;
+          off2 = index->offsets[element];
+
+        } while ( off2 == 0 && element < index->count );
+
+        if ( !off2 )
+          off1 = 0;
+      }
+
+      /* access element */
+      if ( off1 )
+      {
+        *pbyte_len = off2 - off1;
+
+        if ( index->bytes )
+        {
+          /* this index was completely loaded in memory, that's easy */
+          *pbytes = index->bytes + off1 - 1;
+        }
+        else
+        {
+          /* this index is still on disk/file, access it through a frame */
+          FT_Stream  stream = index->stream;
+
+
+          if ( FILE_Seek( index->data_offset + off1 - 1 ) ||
+               EXTRACT_Frame( off2 - off1, *pbytes )      )
+            goto Exit;
+        }
+      }
+      else
+      {
+        /* empty index element */
+        *pbytes    = 0;
+        *pbyte_len = 0;
+      }
+    }
+    else
+      error = CFF_Err_Invalid_Argument;
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF void
+  CFF_Forget_Element( CFF_Index*  index,
+                      FT_Byte**   pbytes )
+  {
+    if ( index->bytes == 0 )
+    {
+      FT_Stream  stream = index->stream;
+
+
+      RELEASE_Frame( *pbytes );
+    }
+  }
+
+
+  FT_LOCAL_DEF FT_String*
+  CFF_Get_Name( CFF_Index*  index,
+                FT_UInt     element )
+  {
+    FT_Memory   memory = index->stream->memory;
+    FT_Byte*    bytes;
+    FT_ULong    byte_len;
+    FT_Error    error;
+    FT_String*  name = 0;
+
+
+    error = CFF_Access_Element( index, element, &bytes, &byte_len );
+    if ( error )
+      goto Exit;
+
+    if ( !ALLOC( name, byte_len + 1 ) )
+    {
+      MEM_Copy( name, bytes, byte_len );
+      name[byte_len] = 0;
+    }
+    CFF_Forget_Element( index, &bytes );
+
+  Exit:
+    return name;
+  }
+
+
+  FT_LOCAL_DEF FT_String*
+  CFF_Get_String( CFF_Index*          index,
+                  FT_UInt             sid,
+                  PSNames_Interface*  interface )
+  {
+    /* if it is not a standard string, return it */
+    if ( sid > 390 )
+      return CFF_Get_Name( index, sid - 391 );
+
+    /* that's a standard string, fetch a copy from the PSName module */
+    {
+      FT_String*   name       = 0;
+      const char*  adobe_name = interface->adobe_std_strings( sid );
+      FT_UInt      len;
+
+
+      if ( adobe_name )
+      {
+        FT_Memory memory = index->stream->memory;
+        FT_Error  error;
+
+
+        len = (FT_UInt)strlen( adobe_name );
+        if ( !ALLOC( name, len + 1 ) )
+        {
+          MEM_Copy( name, adobe_name, len );
+          name[len] = 0;
+        }
+      }
+
+      return name;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***   FD Select table support                                         ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static void
+  CFF_Done_FD_Select( CFF_FD_Select*  select,
+                      FT_Stream       stream )
+  {
+    if ( select->data )
+      RELEASE_Frame( select->data );
+
+    select->data_size   = 0;
+    select->format      = 0;
+    select->range_count = 0;
+  }
+
+
+  static FT_Error
+  CFF_Load_FD_Select( CFF_FD_Select*  select,
+                      FT_UInt         num_glyphs,
+                      FT_Stream       stream,
+                      FT_ULong        offset )
+  {
+    FT_Error  error;
+    FT_Byte   format;
+    FT_UInt   num_ranges;
+
+
+    /* read format */
+    if ( FILE_Seek( offset ) || READ_Byte( format ) )
+      goto Exit;
+
+    select->format      = format;
+    select->cache_count = 0;   /* clear cache */
+
+    switch ( format )
+    {
+    case 0:     /* format 0, that's simple */
+      select->data_size = num_glyphs;
+      goto Load_Data;
+
+    case 3:     /* format 3, a tad more complex */
+      if ( READ_UShort( num_ranges ) )
+        goto Exit;
+
+      select->data_size = num_ranges * 3 + 2;
+
+    Load_Data:
+      if ( EXTRACT_Frame( select->data_size, select->data ) )
+        goto Exit;
+      break;
+
+    default:    /* hmm... that's wrong */
+      error = CFF_Err_Invalid_File_Format;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF FT_Byte
+  CFF_Get_FD( CFF_FD_Select*  select,
+              FT_UInt         glyph_index )
+  {
+    FT_Byte  fd = 0;
+
+
+    switch ( select->format )
+    {
+    case 0:
+      fd = select->data[glyph_index];
+      break;
+
+    case 3:
+      /* first, compare to cache */
+      if ( (FT_UInt)(glyph_index-select->cache_first) < select->cache_count )
+      {
+        fd = select->cache_fd;
+        break;
+      }
+
+      /* then, lookup the ranges array */
+      {
+        FT_Byte*  p       = select->data;
+        FT_Byte*  p_limit = p + select->data_size;
+        FT_Byte   fd2;
+        FT_UInt   first, limit;
+
+
+        first = NEXT_UShort( p );
+        do
+        {
+          if ( glyph_index < first )
+            break;
+
+          fd2   = *p++;
+          limit = NEXT_UShort( p );
+
+          if ( glyph_index < limit )
+          {
+            fd = fd2;
+
+            /* update cache */
+            select->cache_first = first;
+            select->cache_count = limit-first;
+            select->cache_fd    = fd2;
+            break;
+          }
+          first = limit;
+
+        } while ( p < p_limit );
+      }
+      break;
+
+    default:
+      ;
+    }
+
+    return fd;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***   CFF font support                                                ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static void
+  CFF_Done_Encoding( CFF_Encoding*  encoding,
+                     FT_Stream      stream )
+  {
+    FT_Memory  memory = stream->memory;
+
+
+    FREE( encoding->codes );
+    FREE( encoding->sids  );
+    encoding->format = 0;
+    encoding->offset = 0;
+    encoding->codes  = 0;
+    encoding->sids   = 0;
+  }
+
+
+  static void
+  CFF_Done_Charset( CFF_Charset*  charset,
+                    FT_Stream     stream )
+  {
+    FT_Memory  memory = stream->memory;
+
+
+    FREE( charset->sids );
+    charset->format = 0;
+    charset->offset = 0;
+    charset->sids   = 0;
+  }
+
+
+  static FT_Error
+  CFF_Load_Charset( CFF_Charset*  charset,
+                    FT_UInt       num_glyphs,
+                    FT_Stream     stream,
+                    FT_ULong      base_offset,
+                    FT_ULong      offset )
+  {
+    FT_Memory  memory     = stream->memory;
+    FT_Error   error      = 0;
+    FT_UShort  glyph_sid;
+
+
+    charset->offset = base_offset + offset;
+
+    /* Get the format of the table. */
+    if ( FILE_Seek( charset->offset ) ||
+         READ_Byte( charset->format ) )
+      goto Exit;
+
+    /* If the the offset is greater than 2, we have to parse the */
+    /* charset table.                                            */
+    if ( offset > 2 )
+    {
+      FT_UInt  j;
+
+
+      /* Allocate memory for sids. */
+      if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
+        goto Exit;
+
+      /* assign the .notdef glyph */
+      charset->sids[0] = 0;
+
+      switch ( charset->format )
+      {
+      case 0:
+        for ( j = 1; j < num_glyphs; j++ )
+        {
+          if ( READ_UShort( glyph_sid ) )
+            goto Exit;
+
+          charset->sids[j] = glyph_sid;
+        }
+        break;
+
+      case 1:
+      case 2:
+        {
+          FT_UInt  nleft;
+          FT_UInt  i;
+
+
+          j = 1;
+
+          while ( j < num_glyphs )
+          {
+
+            /* Read the first glyph sid of the range. */
+            if ( READ_UShort( glyph_sid ) )
+              goto Exit;
+
+            /* Read the number of glyphs in the range.  */
+            if ( charset->format == 2 )
+            {
+              if ( READ_UShort( nleft ) )
+                goto Exit;
+            }
+            else
+            {
+              if ( READ_Byte( nleft ) )
+                goto Exit;
+            }
+
+            /* Fill in the range of sids -- `nleft + 1' glyphs. */
+            for ( i = 0; i <= nleft; i++, j++, glyph_sid++ )
+              charset->sids[j] = glyph_sid;
+          }
+        }
+        break;
+
+      default:
+        FT_ERROR(( "CFF_Load_Charset: invalid table format!\n" ));
+        error = CFF_Err_Invalid_File_Format;
+        goto Exit;
+      }
+    }
+    else
+    {
+      /* Parse default tables corresponding to offset == 0, 1, or 2.  */
+      /* CFF specification intimates the following:                   */
+      /*                                                              */
+      /* In order to use a predefined charset, the following must be  */
+      /* true: The charset constructed for the glyphs in the font's   */
+      /* charstrings dictionary must match the predefined charset in  */
+      /* the first num_glyphs, and hence must match the predefined    */
+      /* charset *exactly*.                                           */
+
+      switch ( offset )
+      {
+      case 0:
+        if ( num_glyphs != 229 )
+        {
+          FT_ERROR(("CFF_Load_Charset: implicit charset not equal to\n"
+                    "predefined charset (Adobe ISO-Latin)!\n" ));
+          error = CFF_Err_Invalid_File_Format;
+          goto Exit;
+        }
+
+        /* Allocate memory for sids. */
+        if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
+          goto Exit;
+
+        /* Copy the predefined charset into the allocated memory. */
+        MEM_Copy( charset->sids, cff_isoadobe_charset,
+                  num_glyphs * sizeof ( FT_UShort ) );
+
+        break;
+
+      case 1:
+        if ( num_glyphs != 166 )
+        {
+          FT_ERROR(( "CFF_Load_Charset: implicit charset not equal to\n"
+                     "predefined charset (Adobe Expert)!\n" ));
+          error = CFF_Err_Invalid_File_Format;
+          goto Exit;
+        }
+
+        /* Allocate memory for sids. */
+        if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
+          goto Exit;
+
+        /* Copy the predefined charset into the allocated memory.     */
+        MEM_Copy( charset->sids, cff_expert_charset,
+                  num_glyphs * sizeof ( FT_UShort ) );
+
+        break;
+
+      case 2:
+        if ( num_glyphs != 87 )
+        {
+          FT_ERROR(( "CFF_Load_Charset: implicit charset not equal to\n"
+                     "predefined charset (Adobe Expert Subset)!\n" ));
+          error = CFF_Err_Invalid_File_Format;
+          goto Exit;
+        }
+
+        /* Allocate memory for sids. */
+        if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
+          goto Exit;
+
+        /* Copy the predefined charset into the allocated memory.     */
+        MEM_Copy( charset->sids, cff_expertsubset_charset,
+                  num_glyphs * sizeof ( FT_UShort ) );
+
+        break;
+
+      default:
+        error = CFF_Err_Invalid_File_Format;
+        goto Exit;
+      }
+    }
+
+  Exit:
+
+    /* Clean up if there was an error. */
+    if ( error )
+      if ( charset->sids )
+      {
+        if ( charset->sids )
+          FREE( charset->sids );
+        charset->format = 0;
+        charset->offset = 0;
+        charset->sids   = 0;
+      }
+
+    return error;
+  }
+
+
+  static FT_Error
+  CFF_Load_Encoding( CFF_Encoding*  encoding,
+                     CFF_Charset*   charset,
+                     FT_UInt        num_glyphs,
+                     FT_Stream      stream,
+                     FT_ULong       base_offset,
+                     FT_ULong       offset )
+  {
+    FT_Memory   memory = stream->memory;
+    FT_Error    error  = 0;
+    FT_UInt     count;
+    FT_UInt     j;
+    FT_UShort   glyph_sid;
+    FT_Byte     glyph_code;
+
+
+    /* Check for charset->sids.  If we do not have this, we fail. */
+    if ( !charset->sids )
+    {
+      error = CFF_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    /* Allocate memory for sids/codes -- there are at most 256 sids/codes */
+    /* for an encoding.                                                   */
+    if ( ALLOC( encoding->sids,  256 * sizeof ( FT_UShort ) ) ||
+         ALLOC( encoding->codes, 256 * sizeof ( FT_UShort ) ) )
+      goto Exit;
+
+    /* Zero out the code to gid/sid mappings. */
+    for ( j = 0; j < 255; j++ )
+    {
+      encoding->sids [j] = 0;
+      encoding->codes[j] = 0;
+    }
+
+    /* Note: The encoding table in a CFF font is indexed by glyph index,  */
+    /* where the first encoded glyph index is 1.  Hence, we read the char */
+    /* code (`glyph_code') at index j and make the assignment:            */
+    /*                                                                    */
+    /*    encoding->codes[glyph_code] = j + 1                             */
+    /*                                                                    */
+    /* We also make the assignment:                                       */
+    /*                                                                    */
+    /*    encoding->sids[glyph_code] = charset->sids[j + 1]               */
+    /*                                                                    */
+    /* This gives us both a code to GID and a code to SID mapping.        */
+
+    if ( offset > 1 )
+    {
+
+      encoding->offset = base_offset + offset;
+
+      /* we need to parse the table to determine its size */
+      if ( FILE_Seek( encoding->offset ) ||
+           READ_Byte( encoding->format ) ||
+           READ_Byte( count )            )
+        goto Exit;
+
+      switch ( encoding->format & 0x7F )
+      {
+      case 0:
+        for ( j = 1; j <= count; j++ )
+        {
+          if ( READ_Byte( glyph_code ) )
+            goto Exit;
+
+          /* Make sure j is not too big. */
+          if ( j > num_glyphs )
+            goto Exit;
+
+          /* Assign code to GID mapping. */
+          encoding->codes[glyph_code] = (FT_UShort)j;
+
+          /* Assign code to SID mapping. */
+          encoding->sids[glyph_code] = charset->sids[j];
+        }
+
+        break;
+
+      case 1:
+        {
+          FT_Byte  nleft;
+          FT_UInt  i = 1;
+          FT_UInt  k;
+
+
+          /* Parse the Format1 ranges. */
+          for ( j = 0;  j < count; j++, i += nleft )
+          {
+            /* Read the first glyph code of the range. */
+            if ( READ_Byte( glyph_code ) )
+              goto Exit;
+
+            /* Read the number of codes in the range. */
+            if ( READ_Byte( nleft ) )
+              goto Exit;
+
+            /* Increment nleft, so we read `nleft + 1' codes/sids. */
+            nleft++;
+
+            /* Fill in the range of codes/sids. */
+            for ( k = i; k < nleft + i; k++, glyph_code++ )
+            {
+              /* Make sure k is not too big. */
+              if ( k > num_glyphs )
+                goto Exit;
+
+              /* Assign code to GID mapping. */
+              encoding->codes[glyph_code] = (FT_UShort)k;
+
+              /* Assign code to SID mapping. */
+              encoding->sids[glyph_code] = charset->sids[k];
+            }
+          }
+        }
+        break;
+
+      default:
+        FT_ERROR(( "CFF_Load_Encoding: invalid table format!\n" ));
+        error = CFF_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      /* Parse supplemental encodings, if any. */
+      if ( encoding->format & 0x80 )
+      {
+        FT_UInt glyph_id;
+
+
+        /* count supplements */
+        if ( READ_Byte( count ) )
+          goto Exit;
+
+        for ( j = 0; j < count; j++ )
+        {
+          /* Read supplemental glyph code. */
+          if ( READ_Byte( glyph_code ) )
+            goto Exit;
+
+          /* Read the SID associated with this glyph code. */
+          if ( READ_UShort( glyph_sid ) )
+            goto Exit;
+
+          /* Assign code to SID mapping. */
+          encoding->sids[glyph_code] = glyph_sid;
+
+          /* First, lookup GID which has been assigned to */
+          /* SID glyph_sid.                               */
+          for ( glyph_id = 0; glyph_id < num_glyphs; glyph_id++ )
+          {
+            if ( charset->sids[glyph_id] == glyph_sid )
+              break;
+          }
+
+          /* Now, make the assignment. */
+          encoding->codes[glyph_code] = (FT_UShort)glyph_id;
+        }
+      }
+    }
+    else
+    {
+      FT_UInt i;
+
+
+      /* We take into account the fact a CFF font can use a predefined  */
+      /* encoding without containing all of the glyphs encoded by this  */
+      /* encoding (see the note at the end of section 12 in the CFF     */
+      /* specification).                                                */
+
+      switch ( offset )
+      {
+      case 0:
+        /* First, copy the code to SID mapping. */
+        MEM_Copy( encoding->sids, cff_standard_encoding,
+                  256 * sizeof ( FT_UShort ) );
+
+        /* Construct code to GID mapping from code */
+        /* to SID mapping and charset.             */
+        for ( j = 0; j < 256; j++ )
+        {
+          /* If j is encoded, find the GID for it. */
+          if ( encoding->sids[j] )
+          {
+            for ( i = 1; i < num_glyphs; i++ )
+              /* We matched, so break. */
+              if ( charset->sids[i] == encoding->sids[j] )
+                break;
+
+            /* i will be equal to num_glyphs if we exited the above */
+            /* loop without a match.  In this case, we also have to */
+            /* fix the code to SID mapping.                         */
+            if ( i == num_glyphs )
+            {
+              encoding->codes[j] = 0;
+              encoding->sids [j] = 0;
+            }
+            else
+              encoding->codes[j] = (FT_UShort)i;
+          }
+        }
+        break;
+
+      case 1:
+        /* First, copy the code to SID mapping. */
+        MEM_Copy( encoding->sids, cff_expert_encoding,
+                  256 * sizeof ( FT_UShort ) );
+
+        /* Construct code to GID mapping from code to SID mapping */
+        /* and charset.                                           */
+        for ( j = 0; j < 256; j++ )
+        {
+          /* If j is encoded, find the GID for it. */
+          if ( encoding->sids[j] )
+          {
+            for ( i = 1; i < num_glyphs; i++ )
+              /* We matched, so break. */
+              if ( charset->sids[i] == encoding->sids[j] )
+                break;
+
+            /* i will be equal to num_glyphs if we exited the above */
+            /* loop without a match.  In this case, we also have to */
+            /* fix the code to SID mapping.                         */
+            if ( i == num_glyphs )
+            {
+              encoding->codes[j] = 0;
+              encoding->sids [j] = 0;
+            }
+            else
+              encoding->codes[j] = (FT_UShort)i;
+          }
+        }
+        break;
+
+      default:
+        FT_ERROR(( "CFF_Load_Encoding: invalid table format!\n" ));
+        error = CFF_Err_Invalid_File_Format;
+        goto Exit;
+      }
+    }
+
+  Exit:
+
+    /* Clean up if there was an error. */
+    if ( error )
+    {
+      if ( encoding->sids || encoding->codes )
+      {
+        if ( encoding->sids )
+          FREE( encoding->sids );
+
+        if ( encoding->codes )
+          FREE( encoding->codes );
+
+        charset->format = 0;
+        charset->offset = 0;
+        charset->sids   = 0;
+      }
+    }
+
+    return error;
+  }
+
+
+  static FT_Error
+  CFF_Load_SubFont( CFF_SubFont*  font,
+                    CFF_Index*    index,
+                    FT_UInt       font_index,
+                    FT_Stream     stream,
+                    FT_ULong      base_offset )
+  {
+    FT_Error        error;
+    CFF_Parser      parser;
+    FT_Byte*        dict;
+    FT_ULong        dict_len;
+    CFF_Font_Dict*  top  = &font->font_dict;
+    CFF_Private*    priv = &font->private_dict;
+
+
+    CFF_Parser_Init( &parser, CFF_CODE_TOPDICT, &font->font_dict );
+
+    /* set defaults */
+    MEM_Set( top, 0, sizeof ( *top ) );
+
+    top->underline_position  = -100;
+    top->underline_thickness = 50;
+    top->charstring_type     = 2;
+    top->font_matrix.xx      = 0x10000L;
+    top->font_matrix.yy      = 0x10000L;
+    top->cid_count           = 8720;
+
+    error = CFF_Access_Element( index, font_index, &dict, &dict_len ) ||
+            CFF_Parser_Run( &parser, dict, dict + dict_len );
+
+    CFF_Forget_Element( index, &dict );
+
+    if ( error )
+      goto Exit;
+
+    /* if it is a CID font, we stop there */
+    if ( top->cid_registry )
+      goto Exit;
+
+    /* parse the private dictionary, if any */
+    if ( top->private_offset && top->private_size )
+    {
+      /* set defaults */
+      MEM_Set( priv, 0, sizeof ( *priv ) );
+
+      priv->blue_shift       = 7;
+      priv->blue_fuzz        = 1;
+      priv->lenIV            = -1;
+      priv->expansion_factor = (FT_Fixed)0.06 * 0x10000L;
+      priv->blue_scale       = (FT_Fixed)0.039625 * 0x10000L;
+
+      CFF_Parser_Init( &parser, CFF_CODE_PRIVATE, priv );
+
+      if ( FILE_Seek( base_offset + font->font_dict.private_offset ) ||
+           ACCESS_Frame( font->font_dict.private_size )              )
+        goto Exit;
+
+      error = CFF_Parser_Run( &parser,
+                             (FT_Byte*)stream->cursor,
+                             (FT_Byte*)stream->limit );
+      FORGET_Frame();
+      if ( error )
+        goto Exit;
+    }
+
+    /* read the local subrs, if any */
+    if ( priv->local_subrs_offset )
+    {
+      if ( FILE_Seek( base_offset + top->private_offset +
+                      priv->local_subrs_offset ) )
+        goto Exit;
+
+      error = cff_new_index( &font->local_subrs_index, stream, 1 );
+      if ( error )
+        goto Exit;
+
+      font->num_local_subrs = font->local_subrs_index.count;
+      error = cff_explicit_index( &font->local_subrs_index,
+                                     &font->local_subrs );
+      if ( error )
+        goto Exit;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static void
+  CFF_Done_SubFont( FT_Memory     memory,
+                    CFF_SubFont*  subfont )
+  {
+    if ( subfont )
+    {
+      cff_done_index( &subfont->local_subrs_index );
+      FREE( subfont->local_subrs );
+    }
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  CFF_Load_Font( FT_Stream  stream,
+                 FT_Int     face_index,
+                 CFF_Font*  font )
+  {
+    static const FT_Frame_Field  cff_header_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  CFF_Font
+
+      FT_FRAME_START( 4 ),
+        FT_FRAME_BYTE( version_major ),
+        FT_FRAME_BYTE( version_minor ),
+        FT_FRAME_BYTE( header_size ),
+        FT_FRAME_BYTE( absolute_offsize ),
+      FT_FRAME_END
+    };
+
+    FT_Error        error;
+    FT_Memory       memory = stream->memory;
+    FT_ULong        base_offset;
+    CFF_Font_Dict*  dict;
+
+
+    MEM_Set( font, 0, sizeof ( *font ) );
+
+    font->stream = stream;
+    font->memory = memory;
+    dict         = &font->top_font.font_dict;
+    base_offset  = FILE_Pos();
+
+    /* read CFF font header */
+    if ( READ_Fields( cff_header_fields, font ) )
+      goto Exit;
+
+    /* check format */
+    if ( font->version_major   != 1 ||
+         font->header_size      < 4 ||
+         font->absolute_offsize > 4 )
+    {
+      FT_TRACE2(( "[not a CFF font header!]\n" ));
+      error = CFF_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    /* skip the rest of the header */
+    if ( FILE_Skip( font->header_size - 4 ) )
+      goto Exit;
+
+    /* read the name, top dict, string and global subrs index */
+    if ( FT_SET_ERROR( cff_new_index( &font->name_index,         stream, 0 )) ||
+         FT_SET_ERROR( cff_new_index( &font->font_dict_index,    stream, 0 )) ||
+         FT_SET_ERROR( cff_new_index( &font->string_index,       stream, 0 )) ||
+         FT_SET_ERROR( cff_new_index( &font->global_subrs_index, stream, 1 )) )
+      goto Exit;
+
+    /* well, we don't really forget the `disabled' fonts... */
+    font->num_faces = font->name_index.count;
+    if ( face_index >= (FT_Int)font->num_faces )
+    {
+      FT_ERROR(( "CFF_Load_Font: incorrect face index = %d\n",
+                 face_index ));
+      error = CFF_Err_Invalid_Argument;
+    }
+
+    /* in case of a font format check, simply exit now */
+    if ( face_index < 0 )
+      goto Exit;
+
+    /* now, parse the top-level font dictionary */
+    error = CFF_Load_SubFont( &font->top_font,
+                              &font->font_dict_index,
+                              face_index,
+                              stream,
+                              base_offset );
+    if ( error )
+      goto Exit;
+
+    /* now, check for a CID font */
+    if ( dict->cid_registry )
+    {
+      CFF_Index     fd_index;
+      CFF_SubFont*  sub;
+      FT_UInt       index;
+
+
+      /* this is a CID-keyed font, we must now allocate a table of */
+      /* sub-fonts, then load each of them separately              */
+      if ( FILE_Seek( base_offset + dict->cid_fd_array_offset ) )
+        goto Exit;
+
+      error = cff_new_index( &fd_index, stream, 0 );
+      if ( error )
+        goto Exit;
+
+      if ( fd_index.count > CFF_MAX_CID_FONTS )
+      {
+        FT_ERROR(( "CFF_Load_Font: FD array too large in CID font\n" ));
+        goto Fail_CID;
+      }
+
+      /* allocate & read each font dict independently */
+      font->num_subfonts = fd_index.count;
+      if ( ALLOC_ARRAY( sub, fd_index.count, CFF_SubFont ) )
+        goto Fail_CID;
+
+      /* setup pointer table */
+      for ( index = 0; index < fd_index.count; index++ )
+        font->subfonts[index] = sub + index;
+
+      /* now load each sub font independently */
+      for ( index = 0; index < fd_index.count; index++ )
+      {
+        sub = font->subfonts[index];
+        error = CFF_Load_SubFont( sub, &fd_index, index,
+                                  stream, base_offset );
+        if ( error )
+          goto Fail_CID;
+      }
+
+      /* now load the FD Select array */
+      error = CFF_Load_FD_Select( &font->fd_select,
+                                  dict->cid_count,
+                                  stream,
+                                  base_offset + dict->cid_fd_select_offset );
+
+    Fail_CID:
+      cff_done_index( &fd_index );
+
+      if ( error )
+        goto Exit;
+    }
+    else
+      font->num_subfonts = 0;
+
+    /* read the charstrings index now */
+    if ( dict->charstrings_offset == 0 )
+    {
+      FT_ERROR(( "CFF_Load_Font: no charstrings offset!\n" ));
+      error = CFF_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    if ( FILE_Seek( base_offset + dict->charstrings_offset ) )
+      goto Exit;
+
+    error = cff_new_index( &font->charstrings_index, stream, 0 );
+    if ( error )
+      goto Exit;
+
+    /* explicit the global subrs */
+    font->num_global_subrs = font->global_subrs_index.count;
+    font->num_glyphs       = font->charstrings_index.count;
+
+    error = cff_explicit_index( &font->global_subrs_index,
+                                &font->global_subrs ) ;
+
+    if ( error )
+      goto Exit;
+
+    /* read the Charset and Encoding tables when available */
+    error = CFF_Load_Charset( &font->charset, font->num_glyphs, stream,
+                              base_offset, dict->charset_offset );
+    if ( error )
+      goto Exit;
+
+    error = CFF_Load_Encoding( &font->encoding,
+                               &font->charset,
+                               font->num_glyphs,
+                               stream,
+                               base_offset,
+                               dict->encoding_offset );
+    if ( error )
+      goto Exit;
+
+    /* get the font name */
+    font->font_name = CFF_Get_Name( &font->name_index, face_index );
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF void
+  CFF_Done_Font( CFF_Font*  font )
+  {
+    FT_Memory  memory = font->memory;
+    FT_UInt    index;
+
+
+    cff_done_index( &font->global_subrs_index );
+    cff_done_index( &font->string_index );
+    cff_done_index( &font->font_dict_index );
+    cff_done_index( &font->name_index );
+    cff_done_index( &font->charstrings_index );
+
+    /* release font dictionaries */
+    for ( index = 0; index < font->num_subfonts; index++ )
+      CFF_Done_SubFont( memory, font->subfonts[index] );
+
+    CFF_Done_Encoding( &font->encoding, font->stream );
+    CFF_Done_Charset( &font->charset, font->stream );
+
+    CFF_Done_SubFont( memory, &font->top_font );
+
+    CFF_Done_FD_Select( &font->fd_select, font->stream );
+
+    FREE( font->global_subrs );
+    FREE( font->font_name );
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cffobjs.c b/libraries/freetype-2.0.5/cffobjs.c
new file mode 100644 (file)
index 0000000..1041ec2
--- /dev/null
@@ -0,0 +1,598 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cffobjs.c                                                              */
+/*                                                                         */
+/*    OpenType objects manager (body).                                     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_ERRORS_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+#include "cffobjs.h"
+#include "cffload.h"
+
+#include "cfferrs.h"
+
+#include <string.h>         /* for strlen() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cffobjs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                           FACE  FUNCTIONS                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static FT_String*
+  CFF_StrCopy( FT_Memory         memory,
+               const FT_String*  source )
+  {
+    FT_Error    error;
+    FT_String*  result = 0;
+    FT_Int      len = (FT_Int)strlen( source );
+
+
+    if ( !ALLOC( result, len + 1 ) )
+    {
+      MEM_Copy( result, source, len );
+      result[len] = 0;
+    }
+    return result;
+  }
+
+
+#if 0
+
+  /* this function is used to build a Unicode charmap from the glyph names */
+  /* in a file                                                             */
+  static FT_Error
+  CFF_Build_Unicode_Charmap( CFF_Face            face,
+                             FT_ULong            base_offset,
+                             PSNames_Interface*  psnames )
+  {
+    CFF_Font*       font = (CFF_Font*)face->extra.data;
+    FT_Memory       memory = FT_FACE_MEMORY(face);
+    FT_UInt         n, num_glyphs = face->root.num_glyphs;
+    const char**    glyph_names;
+    FT_Error        error;
+    CFF_Font_Dict*  dict = &font->top_font.font_dict;
+    FT_ULong        charset_offset;
+    FT_Byte         format;
+    FT_Stream       stream = face->root.stream;
+
+
+    charset_offset = dict->charset_offset;
+    if ( !charset_offset )
+    {
+      FT_ERROR(( "CFF_Build_Unicode_Charmap: charset table is missing\n" ));
+      error = CFF_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    /* allocate the charmap */
+    if ( ALLOC( face->charmap, ...
+
+    /* seek to charset table and allocate glyph names table */
+    if ( FILE_Seek( base_offset + charset_offset )           ||
+         ALLOC_ARRAY( glyph_names, num_glyphs, const char* ) )
+      goto Exit;
+
+    /* now, read each glyph name and store it in the glyph name table */
+    if ( READ_Byte( format ) )
+      goto Fail;
+
+    switch ( format )
+    {
+    case 0:  /* format 0 - one SID per glyph */
+      {
+        const char**  gname = glyph_names;
+        const char**  limit = gname + num_glyphs;
+
+
+        if ( ACCESS_Frame( num_glyphs * 2 ) )
+          goto Fail;
+
+        for ( ; gname < limit; gname++ )
+          gname[0] = CFF_Get_String( &font->string_index,
+                                     GET_UShort(),
+                                     psnames );
+        FORGET_Frame();
+        break;
+      }
+
+    case 1:  /* format 1 - sequential ranges                    */
+    case 2:  /* format 2 - sequential ranges with 16-bit counts */
+      {
+        const char**  gname = glyph_names;
+        const char**  limit = gname + num_glyphs;
+        FT_UInt       len = 3;
+
+
+        if ( format == 2 )
+          len++;
+
+        while ( gname < limit )
+        {
+          FT_UInt  first;
+          FT_UInt  count;
+
+
+          if ( ACCESS_Frame( len ) )
+            goto Fail;
+
+          first = GET_UShort();
+          if ( format == 3 )
+            count = GET_UShort();
+          else
+            count = GET_Byte();
+
+          FORGET_Frame();
+
+          for ( ; count > 0; count-- )
+          {
+            gname[0] = CFF_Get_String( &font->string_index,
+                                       first,
+                                       psnames );
+            gname++;
+            first++;
+          }
+        }
+        break;
+      }
+
+    default:   /* unknown charset format! */
+      FT_ERROR(( "CFF_Build_Unicode_Charmap: unknown charset format!\n" ));
+      error = CFF_Err_Invalid_File_Format;
+      goto Fail;
+    }
+
+    /* all right, the glyph names were loaded; we now need to create */
+    /* the corresponding unicode charmap                             */
+
+  Fail:
+    for ( n = 0; n < num_glyphs; n++ )
+      FREE( glyph_names[n] );
+
+    FREE( glyph_names );
+
+  Exit:
+    return error;
+  }
+
+#endif /* 0 */
+
+
+  static FT_Encoding
+  find_encoding( int  platform_id,
+                 int  encoding_id )
+  {
+    typedef struct  TEncoding
+    {
+      int          platform_id;
+      int          encoding_id;
+      FT_Encoding  encoding;
+
+    } TEncoding;
+
+    static
+    const TEncoding  tt_encodings[] =
+    {
+      { TT_PLATFORM_ISO,           -1,                  ft_encoding_unicode },
+
+      { TT_PLATFORM_APPLE_UNICODE, -1,                  ft_encoding_unicode },
+
+      { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     ft_encoding_apple_roman },
+
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, ft_encoding_unicode },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       ft_encoding_sjis },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     ft_encoding_gb2312 },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      ft_encoding_big5 },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    ft_encoding_wansung },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      ft_encoding_johab }
+    };
+
+    const TEncoding  *cur, *limit;
+
+
+    cur   = tt_encodings;
+    limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
+
+    for ( ; cur < limit; cur++ )
+    {
+      if ( cur->platform_id == platform_id )
+      {
+        if ( cur->encoding_id == encoding_id ||
+             cur->encoding_id == -1          )
+          return cur->encoding;
+      }
+    }
+
+    return ft_encoding_none;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CFF_Init_Face                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given OpenType face object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     :: The source font stream.                              */
+  /*                                                                       */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*                                                                       */
+  /*    num_params :: Number of additional generic parameters.  Ignored.   */
+  /*                                                                       */
+  /*    params     :: Additional generic parameters.  Ignored.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The newly built face object.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  CFF_Init_Face( FT_Stream      stream,
+                 CFF_Face       face,
+                 FT_Int         face_index,
+                 FT_Int         num_params,
+                 FT_Parameter*  params )
+  {
+    FT_Error            error;
+    SFNT_Interface*     sfnt;
+    PSNames_Interface*  psnames;
+    FT_Bool             pure_cff    = 1;
+    FT_Bool             sfnt_format = 0;
+
+
+    sfnt = (SFNT_Interface*)FT_Get_Module_Interface(
+             face->root.driver->root.library, "sfnt" );
+    if ( !sfnt )
+      goto Bad_Format;
+
+    psnames = (PSNames_Interface*)FT_Get_Module_Interface(
+                face->root.driver->root.library, "psnames" );
+
+    /* create input stream from resource */
+    if ( FILE_Seek( 0 ) )
+      goto Exit;
+
+    /* check that we have a valid OpenType file */
+    error = sfnt->init_face( stream, face, face_index, num_params, params );
+    if ( !error )
+    {
+      if ( face->format_tag != 0x4F54544FL )  /* `OTTO'; OpenType/CFF font */
+      {
+        FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));
+        goto Bad_Format;
+      }
+
+      /* if we are performing a simple font format check, exit immediately */
+      if ( face_index < 0 )
+        return CFF_Err_Ok;
+
+      sfnt_format = 1;
+
+      /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
+      /* font in the later case; it doesn't have a `head' table          */
+      error = face->goto_table( face, TTAG_head, stream, 0 );
+      if ( !error )
+      {
+        pure_cff = 0;
+
+        /* load font directory */
+        error = sfnt->load_face( stream, face,
+                                 face_index, num_params, params );
+        if ( error )
+          goto Exit;
+      }
+      else
+      {
+        /* load the `cmap' table by hand */
+        error = sfnt->load_charmaps( face, stream );
+        if ( error )
+          goto Exit;
+
+        /* XXX: we don't load the GPOS table, as OpenType Layout     */
+        /* support will be added later to a layout library on top of */
+        /* FreeType 2                                                */
+      }
+
+      /* now, load the CFF part of the file */
+      error = face->goto_table( face, TTAG_CFF, stream, 0 );
+      if ( error )
+        goto Exit;
+    }
+    else
+    {
+      /* rewind to start of file; we are going to load a pure-CFF font */
+      if ( FILE_Seek( 0 ) )
+        goto Exit;
+      error = CFF_Err_Ok;
+    }
+
+    /* now load and parse the CFF table in the file */
+    {
+      CFF_Font*  cff;
+      FT_Memory  memory = face->root.memory;
+      FT_Face    root;
+      FT_UInt    flags;
+
+
+      if ( ALLOC( cff, sizeof ( *cff ) ) )
+        goto Exit;
+
+      face->extra.data = cff;
+      error = CFF_Load_Font( stream, face_index, cff );
+      if ( error )
+        goto Exit;
+
+      /* Complement the root flags with some interesting information. */
+      /* Note that this is only necessary for pure CFF and CEF fonts. */
+
+      root = &face->root;
+      if ( pure_cff )
+      {
+        CFF_Font_Dict*  dict = &cff->top_font.font_dict;
+
+
+        /* we need the `PSNames' module for pure-CFF and CEF formats */
+        if ( !psnames )
+        {
+          FT_ERROR(( "CFF_Init_Face:" ));
+          FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
+          FT_ERROR(( "             " ));
+          FT_ERROR(( " without the `PSNames' module\n" ));
+          goto Bad_Format;
+        }
+
+        /* Set up num_faces. */
+        root->num_faces = cff->num_faces;
+
+        /* compute number of glyphs */
+        if ( dict->cid_registry )
+          root->num_glyphs = dict->cid_count;
+        else
+          root->num_glyphs = cff->charstrings_index.count;
+
+        /* set global bbox, as well as EM size */
+        root->bbox      = dict->font_bbox;
+        root->ascender  = (FT_Short)( root->bbox.yMax >> 16 );
+        root->descender = (FT_Short)( root->bbox.yMin >> 16 );
+        root->height    = (FT_Short)(
+          ( ( root->ascender - root->descender ) * 12 ) / 10 );
+
+        if ( dict->units_per_em )
+          root->units_per_EM = dict->units_per_em;
+        else
+          root->units_per_EM = 1000;
+
+        /* retrieve font family & style name */
+        root->family_name  = CFF_Get_Name( &cff->name_index, face_index );
+        if ( dict->cid_registry )
+          root->style_name = CFF_StrCopy( memory, "Regular" );  /* XXXX */
+        else
+          root->style_name = CFF_Get_String( &cff->string_index,
+                                             dict->weight,
+                                             psnames );
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Compute face flags.                                             */
+        /*                                                                 */
+        flags = FT_FACE_FLAG_SCALABLE  |    /* scalable outlines */
+                FT_FACE_FLAG_HORIZONTAL;    /* horizontal data   */
+
+        if ( sfnt_format )
+          flags |= FT_FACE_FLAG_SFNT;
+
+        /* fixed width font? */
+        if ( dict->is_fixed_pitch )
+          flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+  /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
+#if 0
+        /* kerning available? */
+        if ( face->kern_pairs )
+          flags |= FT_FACE_FLAG_KERNING;
+#endif
+
+#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
+        flags |= FT_FACE_FLAG_GLYPH_NAMES;
+#endif
+
+        root->face_flags = flags;
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Compute style flags.                                            */
+        /*                                                                 */
+        flags = 0;
+
+        if ( dict->italic_angle )
+          flags |= FT_STYLE_FLAG_ITALIC;
+
+        /* XXX: may not be correct */
+        if ( cff->top_font.private_dict.force_bold )
+          flags |= FT_STYLE_FLAG_BOLD;
+
+        root->style_flags = flags;
+
+        /* set the charmaps if any */
+        if ( sfnt_format )
+        {
+          /*****************************************************************/
+          /*                                                               */
+          /* Polish the charmaps.                                          */
+          /*                                                               */
+          /*   Try to set the charmap encoding according to the platform & */
+          /*   encoding ID of each charmap.                                */
+          /*                                                               */
+          TT_CharMap  charmap;
+          FT_Int      n;
+
+
+          charmap            = face->charmaps;
+          root->num_charmaps = face->num_charmaps;
+
+          /* allocate table of pointers */
+          if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) )
+            goto Exit;
+
+          for ( n = 0; n < root->num_charmaps; n++, charmap++ )
+          {
+            FT_Int  platform = charmap->cmap.platformID;
+            FT_Int  encoding = charmap->cmap.platformEncodingID;
+
+
+            charmap->root.face        = (FT_Face)face;
+            charmap->root.platform_id = (FT_UShort)platform;
+            charmap->root.encoding_id = (FT_UShort)encoding;
+            charmap->root.encoding    = find_encoding( platform, encoding );
+
+            /* now, set root->charmap with a unicode charmap */
+            /* wherever available                            */
+            if ( !root->charmap                                &&
+                 charmap->root.encoding == ft_encoding_unicode )
+              root->charmap = (FT_CharMap)charmap;
+
+            root->charmaps[n] = (FT_CharMap)charmap;
+          }
+        }
+      }
+    }
+
+  Exit:
+    return error;
+
+  Bad_Format:
+    error = CFF_Err_Unknown_File_Format;
+    goto Exit;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CFF_Done_Face                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given face object.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A pointer to the face object to destroy.                   */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  CFF_Done_Face( CFF_Face  face )
+  {
+    FT_Memory        memory = face->root.memory;
+    SFNT_Interface*  sfnt   = (SFNT_Interface*)face->sfnt;
+
+
+    if ( sfnt )
+      sfnt->done_face( face );
+
+    {
+      CFF_Font*  cff = (CFF_Font*)face->extra.data;
+
+
+      if ( cff )
+      {
+        CFF_Done_Font( cff );
+        FREE( face->extra.data );
+      }
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CFF_Init_Driver                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given OpenType driver object.                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  CFF_Init_Driver( CFF_Driver  driver )
+  {
+    /* init extension registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+
+    return TT_Init_Extensions( driver );
+
+#else
+
+    FT_UNUSED( driver );
+
+    return CFF_Err_Ok;
+
+#endif
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CFF_Done_Driver                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given OpenType driver.                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target OpenType driver.                  */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  CFF_Done_Driver( CFF_Driver  driver )
+  {
+    /* destroy extensions registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+
+    TT_Done_Extensions( driver );
+
+#else
+
+    FT_UNUSED( driver );
+
+#endif
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cffparse.c b/libraries/freetype-2.0.5/cffparse.c
new file mode 100644 (file)
index 0000000..287545a
--- /dev/null
@@ -0,0 +1,677 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cffparse.c                                                             */
+/*                                                                         */
+/*    CFF token stream parser (body)                                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "cffparse.h"
+#include FT_INTERNAL_STREAM_H
+
+#include "cfferrs.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cffparse
+
+
+  enum
+  {
+    cff_kind_none = 0,
+    cff_kind_num,
+    cff_kind_fixed,
+    cff_kind_string,
+    cff_kind_bool,
+    cff_kind_delta,
+    cff_kind_callback,
+
+    cff_kind_max  /* do not remove */
+  };
+
+
+  /* now generate handlers for the most simple fields */
+  typedef FT_Error  (*CFF_Field_Reader)( CFF_Parser*  parser );
+
+  typedef struct  CFF_Field_Handler_
+  {
+    int               kind;
+    int               code;
+    FT_UInt           offset;
+    FT_Byte           size;
+    CFF_Field_Reader  reader;
+    FT_UInt           array_max;
+    FT_UInt           count_offset;
+
+  } CFF_Field_Handler;
+
+
+  FT_LOCAL_DEF void
+  CFF_Parser_Init( CFF_Parser*  parser,
+                   FT_UInt      code,
+                   void*        object )
+  {
+    MEM_Set( parser, 0, sizeof ( *parser ) );
+
+    parser->top         = parser->stack;
+    parser->object_code = code;
+    parser->object      = object;
+  }
+
+
+  /* read an integer */
+  static FT_Long
+  cff_parse_integer( FT_Byte*  start,
+                     FT_Byte*  limit )
+  {
+    FT_Byte*  p   = start;
+    FT_Int    v   = *p++;
+    FT_Long   val = 0;
+
+
+    if ( v == 28 )
+    {
+      if ( p + 2 > limit )
+        goto Bad;
+
+      val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );
+      p  += 2;
+    }
+    else if ( v == 29 )
+    {
+      if ( p + 4 > limit )
+        goto Bad;
+
+      val = ( (FT_Long)p[0] << 24 ) |
+            ( (FT_Long)p[1] << 16 ) |
+            ( (FT_Long)p[2] <<  8 ) |
+                       p[3];
+      p += 4;
+    }
+    else if ( v < 247 )
+    {
+      val = v - 139;
+    }
+    else if ( v < 251 )
+    {
+      if ( p + 1 > limit )
+        goto Bad;
+
+      val = ( v - 247 ) * 256 + p[0] + 108;
+      p++;
+    }
+    else
+    {
+      if ( p + 1 > limit )
+        goto Bad;
+
+      val = -( v - 251 ) * 256 - p[0] - 108;
+      p++;
+    }
+
+  Exit:
+    return val;
+
+  Bad:
+    val = 0;
+    goto Exit;
+  }
+
+
+  /* read a real */
+  static FT_Fixed
+  cff_parse_real( FT_Byte*  start,
+                  FT_Byte*  limit,
+                  FT_Int    power_ten )
+  {
+    FT_Byte*  p    = start;
+    FT_Long   num, divider, result, exp;
+    FT_Int    sign = 0, exp_sign = 0;
+    FT_UInt   nib;
+    FT_UInt   phase;
+
+
+    result  = 0;
+    num     = 0;
+    divider = 1;
+
+    /* first of all, read the integer part */
+    phase = 4;
+
+    for (;;)
+    {
+      /* If we entered this iteration with phase == 4, we need to */
+      /* read a new byte.  This also skips past the intial 0x1E.  */
+      if ( phase )
+      {
+        p++;
+
+        /* Make sure we don't read past the end. */
+        if ( p >= limit )
+          goto Bad;
+      }
+
+      /* Get the nibble. */
+      nib   = ( p[0] >> phase ) & 0xF;
+      phase = 4 - phase;
+
+      if ( nib == 0xE )
+        sign = 1;
+      else if ( nib > 9 )
+        break;
+      else
+        result = result * 10 + nib;
+    }
+
+    /* read decimal part, if any */
+    if ( nib == 0xa )
+      for (;;)
+      {
+        /* If we entered this iteration with phase == 4, we need */
+        /* to read a new byte.                                   */
+        if ( phase )
+        {
+          p++;
+
+          /* Make sure we don't read past the end. */
+          if ( p >= limit )
+            goto Bad;
+        }
+
+        /* Get the nibble. */
+        nib   = ( p[0] >> phase ) & 0xF;
+        phase = 4 - phase;
+        if ( nib >= 10 )
+          break;
+
+        if ( divider < 10000000L )
+        {
+          num      = num * 10 + nib;
+          divider *= 10;
+        }
+      }
+
+    /* read exponent, if any */
+    if ( nib == 12 )
+    {
+      exp_sign = 1;
+      nib      = 11;
+    }
+
+    if ( nib == 11 )
+    {
+      exp = 0;
+
+      for (;;)
+      {
+        /* If we entered this iteration with phase == 4, we need */
+        /* to read a new byte.                                   */
+        if ( phase )
+        {
+          p++;
+
+          /* Make sure we don't read past the end. */
+          if ( p >= limit )
+            goto Bad;
+        }
+
+        /* Get the nibble. */
+        nib   = ( p[0] >> phase ) & 0xF;
+        phase = 4 - phase;
+        if ( nib >= 10 )
+          break;
+
+        exp = exp * 10 + nib;
+      }
+
+      if ( exp_sign )
+        exp = -exp;
+
+      power_ten += exp;
+    }
+
+    /* raise to power of ten if needed */
+    while ( power_ten > 0 )
+    {
+      result = result * 10;
+      num    = num * 10;
+
+      power_ten--;
+    }
+
+    while ( power_ten < 0 )
+    {
+      result  = result / 10;
+      divider = divider * 10;
+
+      power_ten++;
+    }
+
+    /* Move the integer part into the high 16 bits. */
+    result <<= 16;
+
+    /* Place the decimal part into the low 16 bits. */
+    if ( num )
+      result |= FT_DivFix( num, divider );
+
+    if ( sign )
+      result = -result;
+
+  Exit:
+    return result;
+
+  Bad:
+    result = 0;
+    goto Exit;
+  }
+
+
+  /* read a number, either integer or real */
+  static FT_Long
+  cff_parse_num( FT_Byte**  d )
+  {
+    return ( **d == 30 ? ( cff_parse_real   ( d[0], d[1], 0 ) >> 16 )
+                       :   cff_parse_integer( d[0], d[1] ) );
+  }
+
+
+  /* read a floating point number, either integer or real */
+  static FT_Fixed
+  cff_parse_fixed( FT_Byte**  d )
+  {
+    return ( **d == 30 ? cff_parse_real   ( d[0], d[1], 0 )
+                       : cff_parse_integer( d[0], d[1] ) << 16 );
+  }
+
+  /* read a floating point number, either integer or real, */
+  /* but return 1000 times the number read in.             */
+  static FT_Fixed
+  cff_parse_fixed_thousand( FT_Byte**  d )
+  {
+    return **d ==
+      30 ? cff_parse_real     ( d[0], d[1], 3 )
+         : (FT_Fixed)FT_MulFix( cff_parse_integer( d[0], d[1] ) << 16, 1000 );
+  }
+
+  static FT_Error
+  cff_parse_font_matrix( CFF_Parser*  parser )
+  {
+    CFF_Font_Dict*  dict   = (CFF_Font_Dict*)parser->object;
+    FT_Matrix*      matrix = &dict->font_matrix;
+    FT_Vector*      offset = &dict->font_offset;
+    FT_UShort*      upm    = &dict->units_per_em;
+    FT_Byte**       data   = parser->stack;
+    FT_Error        error;
+    FT_Fixed        temp;
+
+
+    error = CFF_Err_Stack_Underflow;
+
+    if ( parser->top >= parser->stack + 6 )
+    {
+      matrix->xx = cff_parse_fixed_thousand( data++ );
+      matrix->yx = cff_parse_fixed_thousand( data++ );
+      matrix->xy = cff_parse_fixed_thousand( data++ );
+      matrix->yy = cff_parse_fixed_thousand( data++ );
+      offset->x  = cff_parse_fixed_thousand( data++ );
+      offset->y  = cff_parse_fixed_thousand( data   );
+
+      temp = ABS( matrix->yy );
+
+      *upm = (FT_UShort)FT_DivFix( 0x10000L, FT_DivFix( temp, 1000 ) );
+
+      if ( temp != 0x10000L )
+      {
+        matrix->xx = FT_DivFix( matrix->xx, temp );
+        matrix->yx = FT_DivFix( matrix->yx, temp );
+        matrix->xy = FT_DivFix( matrix->xy, temp );
+        matrix->yy = FT_DivFix( matrix->yy, temp );
+        offset->x  = FT_DivFix( offset->x,  temp );
+        offset->y  = FT_DivFix( offset->y,  temp );
+      }
+
+      /* note that the offsets must be expressed in integer font units */
+      offset->x >>= 16;
+      offset->y >>= 16;
+
+      error = CFF_Err_Ok;
+    }
+
+    return error;
+  }
+
+
+  static FT_Error
+  cff_parse_font_bbox( CFF_Parser*  parser )
+  {
+    CFF_Font_Dict*  dict = (CFF_Font_Dict*)parser->object;
+    FT_BBox*        bbox = &dict->font_bbox;
+    FT_Byte**       data = parser->stack;
+    FT_Error        error;
+
+
+    error = CFF_Err_Stack_Underflow;
+
+    if ( parser->top >= parser->stack + 4 )
+    {
+      bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );
+      bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
+      bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
+      bbox->yMax = FT_RoundFix( cff_parse_fixed( data   ) );
+      error = CFF_Err_Ok;
+    }
+
+    return error;
+  }
+
+
+  static FT_Error
+  cff_parse_private_dict( CFF_Parser*  parser )
+  {
+    CFF_Font_Dict*  dict = (CFF_Font_Dict*)parser->object;
+    FT_Byte**       data = parser->stack;
+    FT_Error        error;
+
+
+    error = CFF_Err_Stack_Underflow;
+
+    if ( parser->top >= parser->stack + 2 )
+    {
+      dict->private_size   = cff_parse_num( data++ );
+      dict->private_offset = cff_parse_num( data   );
+      error = CFF_Err_Ok;
+    }
+
+    return error;
+  }
+
+
+  static FT_Error
+  cff_parse_cid_ros( CFF_Parser*  parser )
+  {
+    CFF_Font_Dict*  dict = (CFF_Font_Dict*)parser->object;
+    FT_Byte**       data = parser->stack;
+    FT_Error        error;
+
+
+    error = CFF_Err_Stack_Underflow;
+
+    if ( parser->top >= parser->stack + 3 )
+    {
+      dict->cid_registry   = (FT_UInt)cff_parse_num ( data++ );
+      dict->cid_ordering   = (FT_UInt)cff_parse_num ( data++ );
+      dict->cid_supplement = (FT_ULong)cff_parse_num( data );
+      error = CFF_Err_Ok;
+    }
+
+    return error;
+  }
+
+
+#define CFF_FIELD_NUM( code, name ) \
+          CFF_FIELD( code, name, cff_kind_num )
+#define CFF_FIELD_FIXED( code, name ) \
+          CFF_FIELD( code, name, cff_kind_fixed )
+#define CFF_FIELD_STRING( code, name ) \
+          CFF_FIELD( code, name, cff_kind_string )
+#define CFF_FIELD_BOOL( code, name ) \
+          CFF_FIELD( code, name, cff_kind_bool )
+#define CFF_FIELD_DELTA( code, name, max ) \
+          CFF_FIELD( code, name, cff_kind_delta )
+
+#define CFF_FIELD_CALLBACK( code, name ) \
+          {                              \
+            cff_kind_callback,           \
+            code | CFFCODE,              \
+            0, 0,                        \
+            cff_parse_ ## name,          \
+            0, 0                         \
+          },
+
+#undef  CFF_FIELD
+#define CFF_FIELD( code, name, kind ) \
+          {                          \
+            kind,                    \
+            code | CFFCODE,          \
+            FT_FIELD_OFFSET( name ), \
+            FT_FIELD_SIZE( name ),   \
+            0, 0, 0                  \
+          },
+
+#undef  CFF_FIELD_DELTA
+#define CFF_FIELD_DELTA( code, name, max ) \
+        {                                  \
+          cff_kind_delta,                  \
+          code | CFFCODE,                  \
+          FT_FIELD_OFFSET( name ),         \
+          FT_FIELD_SIZE_DELTA( name ),     \
+          0,                               \
+          max,                             \
+          FT_FIELD_OFFSET( num_ ## name )  \
+        },
+
+#define CFFCODE_TOPDICT  0x1000
+#define CFFCODE_PRIVATE  0x2000
+
+  static const CFF_Field_Handler  cff_field_handlers[] =
+  {
+
+#include "cfftoken.h"
+
+    { 0, 0, 0, 0, 0, 0, 0 }
+  };
+
+
+  FT_LOCAL_DEF FT_Error
+  CFF_Parser_Run( CFF_Parser*  parser,
+                  FT_Byte*     start,
+                  FT_Byte*     limit )
+  {
+    FT_Byte*  p     = start;
+    FT_Error  error = CFF_Err_Ok;
+
+
+    parser->top    = parser->stack;
+    parser->start  = start;
+    parser->limit  = limit;
+    parser->cursor = start;
+
+    while ( p < limit )
+    {
+      FT_UInt  v = *p;
+
+
+      if ( v >= 27 && v != 31 )
+      {
+        /* it's a number; we will push its position on the stack */
+        if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
+          goto Stack_Overflow;
+
+        *parser->top ++ = p;
+
+        /* now, skip it */
+        if ( v == 30 )
+        {
+          /* skip real number */
+          p++;
+          for (;;)
+          {
+            if ( p >= limit )
+              goto Syntax_Error;
+            v = p[0] >> 4;
+            if ( v == 15 )
+              break;
+            v = p[0] & 0xF;
+            if ( v == 15 )
+              break;
+            p++;
+          }
+        }
+        else if ( v == 28 )
+          p += 2;
+        else if ( v == 29 )
+          p += 4;
+        else if ( v > 246 )
+          p += 1;
+      }
+      else
+      {
+        /* This is not a number, hence it's an operator.  Compute its code */
+        /* and look for it in our current list.                            */
+
+        FT_UInt                   code;
+        FT_UInt                   num_args = (FT_UInt)
+                                             ( parser->top - parser->stack );
+        const CFF_Field_Handler*  field;
+
+
+        /* first of all, a trivial check */
+        if ( num_args < 1 )
+          goto Stack_Underflow;
+
+        *parser->top = p;
+        code = v;
+        if ( v == 12 )
+        {
+          /* two byte operator */
+          p++;
+          code = 0x100 | p[0];
+        }
+        code = code | parser->object_code;
+
+        for ( field = cff_field_handlers; field->kind; field++ )
+        {
+          if ( field->code == (FT_Int)code )
+          {
+            /* we found our field's handler; read it */
+            FT_Long   val;
+            FT_Byte*  q = (FT_Byte*)parser->object + field->offset;
+
+
+            switch ( field->kind )
+            {
+            case cff_kind_bool:
+            case cff_kind_string:
+            case cff_kind_num:
+              val = cff_parse_num( parser->stack );
+              goto Store_Number;
+
+            case cff_kind_fixed:
+              val = cff_parse_fixed( parser->stack );
+
+            Store_Number:
+              switch ( field->size )
+              {
+              case 1:
+                *(FT_Byte*)q = (FT_Byte)val;
+                break;
+
+              case 2:
+                *(FT_Short*)q = (FT_Short)val;
+                break;
+
+              case 4:
+                *(FT_Int32*)q = (FT_Int)val;
+                break;
+
+              default:  /* for 64-bit systems where long is 8 bytes */
+                *(FT_Long*)q = val;
+              }
+              break;
+
+            case cff_kind_delta:
+              {
+                FT_Byte*   qcount = (FT_Byte*)parser->object +
+                                      field->count_offset;
+
+                FT_Byte**  data = parser->stack;
+
+
+                if ( num_args > field->array_max )
+                  num_args = field->array_max;
+
+                /* store count */
+                *qcount = (FT_Byte)num_args;
+
+                val = 0;
+                while ( num_args > 0 )
+                {
+                  val += cff_parse_num( data++ );
+                  switch ( field->size )
+                  {
+                  case 1:
+                    *(FT_Byte*)q = (FT_Byte)val;
+                    break;
+
+                  case 2:
+                    *(FT_Short*)q = (FT_Short)val;
+                    break;
+
+                  case 4:
+                    *(FT_Int32*)q = (FT_Int)val;
+                    break;
+
+                  default:  /* for 64-bit systems */
+                    *(FT_Long*)q = val;
+                  }
+
+                  q += field->size;
+                  num_args--;
+                }
+              }
+              break;
+
+            default:  /* callback */
+              error = field->reader( parser );
+              if ( error )
+                goto Exit;
+            }
+            goto Found;
+          }
+        }
+
+        /* this is an unknown operator, or it is unsupported; */
+        /* we will ignore it for now.                         */
+
+      Found:
+        /* clear stack */
+        parser->top = parser->stack;
+      }
+      p++;
+    }
+
+  Exit:
+    return error;
+
+  Stack_Overflow:
+    error = CFF_Err_Invalid_Argument;
+    goto Exit;
+
+  Stack_Underflow:
+    error = CFF_Err_Invalid_Argument;
+    goto Exit;
+
+  Syntax_Error:
+    error = CFF_Err_Invalid_Argument;
+    goto Exit;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cidgload.c b/libraries/freetype-2.0.5/cidgload.c
new file mode 100644 (file)
index 0000000..c1c4f45
--- /dev/null
@@ -0,0 +1,356 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidgload.c                                                             */
+/*                                                                         */
+/*    CID-keyed Type1 Glyph Loader (body).                                 */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "cidload.h"
+#include "cidgload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_OUTLINE_H
+
+#include "ciderrs.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cidgload
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  cid_load_glyph( T1_Decoder*  decoder,
+                  FT_UInt      glyph_index )
+  {
+    CID_Face   face = (CID_Face)decoder->builder.face;
+    CID_Info*  cid  = &face->cid;
+    FT_Byte*   p;
+    FT_UInt    entry_len = cid->fd_bytes + cid->gd_bytes;
+    FT_UInt    fd_select;
+    FT_ULong   off1, glyph_len;
+    FT_Stream  stream = face->root.stream;
+    FT_Error   error  = 0;
+
+
+    /* read the CID font dict index and charstring offset from the CIDMap */
+    if ( FILE_Seek( cid->data_offset + cid->cidmap_offset +
+                    glyph_index * entry_len )               ||
+         ACCESS_Frame( 2 * entry_len )                      )
+      goto Exit;
+
+    p = (FT_Byte*)stream->cursor;
+    fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
+    off1      = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
+    p        += cid->fd_bytes;
+    glyph_len = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1;
+
+    FORGET_Frame();
+
+    /* now, if the glyph is not empty, set up the subrs array, and parse */
+    /* the charstrings                                                   */
+    if ( glyph_len > 0 )
+    {
+      CID_FontDict*  dict;
+      CID_Subrs*     cid_subrs = face->subrs + fd_select;
+      FT_Byte*       charstring;
+      FT_Memory      memory = face->root.memory;
+
+
+      /* setup subrs */
+      decoder->num_subrs = cid_subrs->num_subrs;
+      decoder->subrs     = cid_subrs->code;
+      decoder->subrs_len = 0;
+
+      /* setup font matrix */
+      dict                 = cid->font_dicts + fd_select;
+
+      decoder->font_matrix = dict->font_matrix;
+      decoder->font_offset = dict->font_offset;
+      decoder->lenIV       = dict->private_dict.lenIV;
+
+      /* the charstrings are encoded (stupid!)  */
+      /* load the charstrings, then execute it  */
+
+      if ( ALLOC( charstring, glyph_len ) )
+        goto Exit;
+
+      if ( !FILE_Read_At( cid->data_offset + off1, charstring, glyph_len ) )
+      {
+        FT_Int cs_offset;
+
+
+        /* Adjustment for seed bytes. */
+        cs_offset = ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
+
+        /* Decrypt only if lenIV >= 0. */
+        if ( decoder->lenIV >= 0 )
+          cid_decrypt( charstring, glyph_len, 4330 );
+
+        error = decoder->funcs.parse_charstrings( decoder,
+                                                  charstring + cs_offset,
+                                                  glyph_len  - cs_offset  );
+      }
+
+      FREE( charstring );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+#if 0
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of computing      *********/
+  /**********    the maximum advance width of the font.  It        *********/
+  /**********    quickly processes each glyph charstring to        *********/
+  /**********    extract the value from either a `sbw' or `seac'   *********/
+  /**********    operator.                                         *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_LOCAL_DEF FT_Error
+  CID_Compute_Max_Advance( CID_Face  face,
+                           FT_Int*   max_advance )
+  {
+    FT_Error    error;
+    T1_Decoder  decoder;
+    FT_Int      glyph_index;
+
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+
+    *max_advance = 0;
+
+    /* Initialize load decoder */
+    error = psaux->t1_decoder_funcs->init( &decoder,
+                                           (FT_Face)face,
+                                           0, /* size       */
+                                           0, /* glyph slot */
+                                           0, /* glyph names! XXX */
+                                           0, /* blend == 0 */
+                                           cid_load_glyph );
+    if ( error )
+      return error;
+
+    decoder.builder.metrics_only = 1;
+    decoder.builder.load_points  = 0;
+
+    /* for each glyph, parse the glyph charstring and extract */
+    /* the advance width                                      */
+    for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
+          glyph_index++ )
+    {
+      /* now get load the unscaled outline */
+      error = cid_load_glyph( &decoder, glyph_index );
+      /* ignore the error if one occurred - skip to next glyph */
+    }
+
+    *max_advance = decoder.builder.advance.x;
+
+    return CID_Err_Ok;
+  }
+
+
+#endif /* 0 */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********                                                      *********/
+  /**********               UNHINTED GLYPH LOADER                  *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of loading a      *********/
+  /**********    single outline.  It completely ignores hinting    *********/
+  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_LOCAL_DEF FT_Error
+  CID_Load_Glyph( CID_GlyphSlot  glyph,
+                  CID_Size       size,
+                  FT_Int         glyph_index,
+                  FT_Int         load_flags )
+  {
+    FT_Error    error;
+    T1_Decoder  decoder;
+    CID_Face    face = (CID_Face)glyph->root.face;
+    FT_Bool     hinting;
+
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+    FT_Matrix         font_matrix;
+    FT_Vector         font_offset;
+
+
+    if ( load_flags & FT_LOAD_NO_RECURSE )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    glyph->x_scale = size->root.metrics.x_scale;
+    glyph->y_scale = size->root.metrics.y_scale;
+
+    glyph->root.outline.n_points   = 0;
+    glyph->root.outline.n_contours = 0;
+
+    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
+                       ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
+
+    glyph->root.format = ft_glyph_format_outline;
+
+    {
+      error = psaux->t1_decoder_funcs->init( &decoder,
+                                             (FT_Face)face,
+                                             (FT_Size)size,
+                                             (FT_GlyphSlot)glyph,
+                                             0, /* glyph names -- XXX */
+                                             0, /* blend == 0 */
+                                             cid_load_glyph );
+
+      /* set up the decoder */
+      decoder.builder.no_recurse = FT_BOOL(
+        ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) );
+
+      error = cid_load_glyph( &decoder, glyph_index );
+
+      font_matrix = decoder.font_matrix;
+      font_offset = decoder.font_offset;
+
+      /* save new glyph tables */
+      psaux->t1_decoder_funcs->done( &decoder );
+    }
+
+    /* now, set the metrics -- this is rather simple, as   */
+    /* the left side bearing is the xMin, and the top side */
+    /* bearing the yMax                                    */
+    if ( !error )
+    {
+      glyph->root.outline.flags &= ft_outline_owner;
+      glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+      /* for composite glyphs, return only left side bearing and */
+      /* advance width                                           */
+      if ( load_flags & FT_LOAD_NO_RECURSE )
+      {
+        FT_Slot_Internal  internal = glyph->root.internal;
+
+
+        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+        glyph->root.metrics.horiAdvance  = decoder.builder.advance.x;
+
+        internal->glyph_matrix         = font_matrix;
+        internal->glyph_delta          = font_offset;
+        internal->glyph_transformed    = 1;
+      }
+      else
+      {
+        FT_BBox            cbox;
+        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
+
+
+        /* copy the _unscaled_ advance width */
+        metrics->horiAdvance          = decoder.builder.advance.x;
+        glyph->root.linearHoriAdvance = decoder.builder.advance.x;
+        glyph->root.internal->glyph_transformed = 0;
+
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+
+        glyph->root.linearVertAdvance = 0;
+        glyph->root.format = ft_glyph_format_outline;
+
+        if ( size && size->root.metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+
+        /* apply the font matrix */
+        FT_Outline_Transform( &glyph->root.outline, &font_matrix );
+
+        FT_Outline_Translate( &glyph->root.outline,
+                              font_offset.x,
+                              font_offset.y );
+
+        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        {
+          /* scale the outline and the metrics */
+          FT_Int       n;
+          FT_Outline*  cur = decoder.builder.base;
+          FT_Vector*   vec = cur->points;
+          FT_Fixed     x_scale = glyph->x_scale;
+          FT_Fixed     y_scale = glyph->y_scale;
+
+
+          /* First of all, scale the points */
+          for ( n = cur->n_points; n > 0; n--, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
+
+          FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+          /* Then scale the metrics */
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
+
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+        }
+
+        /* compute the other metrics */
+        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+        /* grid fit the bounding box if necessary */
+        if ( hinting )
+        {
+          cbox.xMin &= -64;
+          cbox.yMin &= -64;
+          cbox.xMax  = ( cbox.xMax + 63 ) & -64;
+          cbox.yMax  = ( cbox.yMax + 63 ) & -64;
+        }
+
+        metrics->width  = cbox.xMax - cbox.xMin;
+        metrics->height = cbox.yMax - cbox.yMin;
+
+        metrics->horiBearingX = cbox.xMin;
+        metrics->horiBearingY = cbox.yMax;
+      }
+    }
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cidload.c b/libraries/freetype-2.0.5/cidload.c
new file mode 100644 (file)
index 0000000..ad39013
--- /dev/null
@@ -0,0 +1,549 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidload.c                                                              */
+/*                                                                         */
+/*    CID-keyed Type1 font loader (body).                                  */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_CONFIG_CONFIG_H
+#include FT_MULTIPLE_MASTERS_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+#include "cidload.h"
+
+#include "ciderrs.h"
+
+#include <stdio.h>
+#include <ctype.h>  /* for isspace(), isalnum() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cidload
+
+
+  /* read a single offset */
+  FT_LOCAL_DEF FT_Long
+  cid_get_offset( FT_Byte**  start,
+                  FT_Byte    offsize )
+  {
+    FT_Long   result;
+    FT_Byte*  p = *start;
+
+
+    for ( result = 0; offsize > 0; offsize-- )
+    {
+      result <<= 8;
+      result  |= *p++;
+    }
+
+    *start = p;
+    return result;
+  }
+
+
+  FT_LOCAL_DEF void
+  cid_decrypt( FT_Byte*   buffer,
+               FT_Offset  length,
+               FT_UShort  seed )
+  {
+    while ( length > 0 )
+    {
+      FT_Byte  plain;
+
+
+      plain     = (FT_Byte)( *buffer ^ ( seed >> 8 ) );
+      seed      = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 );
+      *buffer++ = plain;
+      length--;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    TYPE 1 SYMBOL PARSING                      *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static FT_Error
+  cid_load_keyword( CID_Face         face,
+                    CID_Loader*      loader,
+                    const T1_Field*  keyword )
+  {
+    FT_Error     error;
+    CID_Parser*  parser = &loader->parser;
+    FT_Byte*     object;
+    void*        dummy_object;
+    CID_Info*    cid = &face->cid;
+
+
+    /* if the keyword has a dedicated callback, call it */
+    if ( keyword->type == t1_field_callback )
+    {
+      keyword->reader( (FT_Face)face, parser );
+      error = parser->root.error;
+      goto Exit;
+    }
+
+    /* we must now compute the address of our target object */
+    switch ( keyword->location )
+    {
+    case t1_field_cid_info:
+      object = (FT_Byte*)cid;
+      break;
+
+    case t1_field_font_info:
+      object = (FT_Byte*)&cid->font_info;
+      break;
+
+    default:
+      {
+        CID_FontDict*  dict;
+
+
+        if ( parser->num_dict < 0 )
+        {
+          FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
+                     keyword->ident ));
+          error = CID_Err_Syntax_Error;
+          goto Exit;
+        }
+
+        dict = cid->font_dicts + parser->num_dict;
+        switch ( keyword->location )
+        {
+        case t1_field_private:
+          object = (FT_Byte*)&dict->private_dict;
+          break;
+
+        default:
+          object = (FT_Byte*)dict;
+        }
+      }
+    }
+
+    dummy_object = object;
+
+    /* now, load the keyword data in the object's field(s) */
+    if ( keyword->type == t1_field_integer_array ||
+         keyword->type == t1_field_fixed_array   )
+      error = CID_Load_Field_Table( &loader->parser, keyword,
+                                    &dummy_object );
+    else
+      error = CID_Load_Field( &loader->parser, keyword, &dummy_object );
+  Exit:
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  parse_font_bbox( CID_Face     face,
+                   CID_Parser*  parser )
+  {
+    FT_Fixed  temp[4];
+    FT_BBox*  bbox = &face->cid.font_bbox;
+
+
+    (void)CID_ToFixedArray( parser, 4, temp, 0 );
+    bbox->xMin = FT_RoundFix( temp[0] );
+    bbox->yMin = FT_RoundFix( temp[1] );
+    bbox->xMax = FT_RoundFix( temp[2] );
+    bbox->yMax = FT_RoundFix( temp[3] );
+
+    return CID_Err_Ok;       /* this is a callback function; */
+                            /* we must return an error code */
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  parse_font_matrix( CID_Face     face,
+                     CID_Parser*  parser )
+  {
+    FT_Matrix*     matrix;
+    FT_Vector*     offset;
+    CID_FontDict*  dict;
+    FT_Face        root = (FT_Face)&face->root;
+    FT_Fixed       temp[6];
+    FT_Fixed       temp_scale;
+
+
+    if ( parser->num_dict >= 0 )
+    {
+      dict   = face->cid.font_dicts + parser->num_dict;
+      matrix = &dict->font_matrix;
+      offset = &dict->font_offset;
+
+      (void)CID_ToFixedArray( parser, 6, temp, 3 );
+
+      temp_scale = ABS( temp[3] );
+
+      /* Set Units per EM based on FontMatrix values.  We set the value to */
+      /* `1000/temp_scale', because temp_scale was already multiplied by   */
+      /* 1000 (in t1_tofixed(), from psobjs.c).                            */
+      root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L,
+                                        FT_DivFix( temp_scale, 1000 ) ) );
+
+      /* we need to scale the values by 1.0/temp[3] */
+      if ( temp_scale != 0x10000L )
+      {
+        temp[0] = FT_DivFix( temp[0], temp_scale );
+        temp[1] = FT_DivFix( temp[1], temp_scale );
+        temp[2] = FT_DivFix( temp[2], temp_scale );
+        temp[4] = FT_DivFix( temp[4], temp_scale );
+        temp[5] = FT_DivFix( temp[5], temp_scale );
+        temp[3] = 0x10000L;
+      }
+
+      matrix->xx = temp[0];
+      matrix->yx = temp[1];
+      matrix->xy = temp[2];
+      matrix->yy = temp[3];
+
+      /* note that the font offsets are expressed in integer font units */
+      offset->x  = temp[4] >> 16;
+      offset->y  = temp[5] >> 16;
+    }
+
+    return CID_Err_Ok;       /* this is a callback function; */
+                            /* we must return an error code */
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  parse_fd_array( CID_Face     face,
+                  CID_Parser*  parser )
+  {
+    CID_Info*  cid    = &face->cid;
+    FT_Memory  memory = face->root.memory;
+    FT_Error   error  = CID_Err_Ok;
+    FT_Long    num_dicts;
+
+
+    num_dicts = CID_ToInt( parser );
+
+    if ( !cid->font_dicts )
+    {
+      FT_Int  n;
+
+
+      if ( ALLOC_ARRAY( cid->font_dicts, num_dicts, CID_FontDict ) )
+        goto Exit;
+
+      cid->num_dicts = (FT_UInt)num_dicts;
+
+      /* don't forget to set a few defaults */
+      for ( n = 0; n < cid->num_dicts; n++ )
+      {
+        CID_FontDict*  dict = cid->font_dicts + n;
+
+
+        /* default value for lenIV */
+        dict->private_dict.lenIV = 4;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  const T1_Field  cid_field_records[] =
+  {
+
+#include "cidtoken.h"
+
+    T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
+    T1_FIELD_CALLBACK( "FDArray", parse_fd_array )
+    T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
+    { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
+  };
+
+
+  static int
+  is_alpha( char  c )
+  {
+    return ( isalnum( (int)c ) ||
+             c == '.'          ||
+             c == '_'          );
+  }
+
+
+  static FT_Error
+  cid_parse_dict( CID_Face     face,
+                  CID_Loader*  loader,
+                  FT_Byte*     base,
+                  FT_Long      size )
+  {
+    CID_Parser*  parser = &loader->parser;
+
+
+    parser->root.cursor = base;
+    parser->root.limit  = base + size;
+    parser->root.error  = 0;
+
+    {
+      FT_Byte*  cur   = base;
+      FT_Byte*  limit = cur + size;
+
+
+      for ( ;cur < limit; cur++ )
+      {
+        /* look for `%ADOBeginFontDict' */
+        if ( *cur == '%' && cur + 20 < limit &&
+             strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
+        {
+          cur += 17;
+
+          /* if /FDArray was found, then cid->num_dicts is > 0, and */
+          /* we can start increasing parser->num_dict               */
+          if ( face->cid.num_dicts > 0 )
+            parser->num_dict++;
+        }
+        /* look for immediates */
+        else if ( *cur == '/' && cur + 2 < limit )
+        {
+          FT_Byte*  cur2;
+          FT_Int    len;
+
+
+          cur++;
+
+          cur2 = cur;
+          while ( cur2 < limit && is_alpha( *cur2 ) )
+            cur2++;
+
+          len = (FT_Int)( cur2 - cur );
+          if ( len > 0 && len < 22 )
+          {
+            /* now compare the immediate name to the keyword table */
+            const T1_Field*  keyword = cid_field_records;
+
+
+            for (;;)
+            {
+              FT_Byte*  name;
+
+
+              name = (FT_Byte*)keyword->ident;
+              if ( !name )
+                break;
+
+              if ( cur[0] == name[0]                          &&
+                   len == (FT_Int)strlen( (const char*)name ) )
+              {
+                FT_Int  n;
+
+
+                for ( n = 1; n < len; n++ )
+                  if ( cur[n] != name[n] )
+                    break;
+
+                if ( n >= len )
+                {
+                  /* we found it - run the parsing callback */
+                  parser->root.cursor = cur2;
+                  CID_Skip_Spaces( parser );
+                  parser->root.error = cid_load_keyword( face,
+                                                         loader,
+                                                         keyword );
+                  if ( parser->root.error )
+                    return parser->root.error;
+
+                  cur = parser->root.cursor;
+                  break;
+                }
+              }
+              keyword++;
+            }
+          }
+        }
+      }
+    }
+    return parser->root.error;
+  }
+
+
+  /* read the subrmap and the subrs of each font dict */
+  static FT_Error
+  cid_read_subrs( CID_Face  face )
+  {
+    CID_Info*   cid    = &face->cid;
+    FT_Memory   memory = face->root.memory;
+    FT_Stream   stream = face->root.stream;
+    FT_Error    error;
+    FT_Int      n;
+    CID_Subrs*  subr;
+    FT_UInt     max_offsets = 0;
+    FT_ULong*   offsets = 0;
+
+
+    if ( ALLOC_ARRAY( face->subrs, cid->num_dicts, CID_Subrs ) )
+      goto Exit;
+
+    subr = face->subrs;
+    for ( n = 0; n < cid->num_dicts; n++, subr++ )
+    {
+      CID_FontDict*  dict  = cid->font_dicts + n;
+      FT_Int         lenIV = dict->private_dict.lenIV;
+      FT_UInt        count, num_subrs = dict->num_subrs;
+      FT_ULong       data_len;
+      FT_Byte*       p;
+
+
+      /* reallocate offsets array if needed */
+      if ( num_subrs + 1 > max_offsets )
+      {
+        FT_UInt  new_max = ( num_subrs + 1 + 3 ) & -4;
+
+
+        if ( REALLOC_ARRAY( offsets, max_offsets, new_max, FT_ULong ) )
+          goto Fail;
+
+        max_offsets = new_max;
+      }
+
+      /* read the subrmap's offsets */
+      if ( FILE_Seek( cid->data_offset + dict->subrmap_offset ) ||
+           ACCESS_Frame( ( num_subrs + 1 ) * dict->sd_bytes )   )
+        goto Fail;
+
+      p = (FT_Byte*)stream->cursor;
+      for ( count = 0; count <= num_subrs; count++ )
+        offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
+
+      FORGET_Frame();
+
+      /* now, compute the size of subrs charstrings, */
+      /* allocate, and read them                     */
+      data_len = offsets[num_subrs] - offsets[0];
+
+      if ( ALLOC_ARRAY( subr->code, num_subrs + 1, FT_Byte* ) ||
+           ALLOC( subr->code[0], data_len )                   )
+        goto Fail;
+
+      if ( FILE_Seek( cid->data_offset + offsets[0] ) ||
+           FILE_Read( subr->code[0], data_len )  )
+        goto Exit;
+
+      /* set up pointers */
+      for ( count = 1; count <= num_subrs; count++ )
+      {
+        FT_UInt  len;
+
+
+        len               = offsets[count] - offsets[count - 1];
+        subr->code[count] = subr->code[count - 1] + len;
+      }
+
+      /* decrypt subroutines, but only if lenIV >= 0 */
+      if ( lenIV >= 0 )
+      {
+        for ( count = 0; count < num_subrs; count++ )
+        {
+          FT_UInt  len;
+
+
+          len = offsets[count + 1] - offsets[count];
+          cid_decrypt( subr->code[count], len, 4330 );
+        }
+      }
+
+      subr->num_subrs = num_subrs;
+    }
+
+  Exit:
+    FREE( offsets );
+    return error;
+
+  Fail:
+    if ( face->subrs )
+    {
+      for ( n = 0; n < cid->num_dicts; n++ )
+      {
+        if ( face->subrs[n].code )
+          FREE( face->subrs[n].code[0] );
+
+        FREE( face->subrs[n].code );
+      }
+      FREE( face->subrs );
+    }
+    goto Exit;
+  }
+
+
+  static void
+  t1_init_loader( CID_Loader*  loader,
+                  CID_Face     face )
+  {
+    FT_UNUSED( face );
+
+    MEM_Set( loader, 0, sizeof ( *loader ) );
+  }
+
+
+  static void
+  t1_done_loader( CID_Loader*  loader )
+  {
+    CID_Parser*  parser = &loader->parser;
+
+
+    /* finalize parser */
+    CID_Done_Parser( parser );
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  CID_Open_Face( CID_Face  face )
+  {
+    CID_Loader  loader;
+    CID_Parser* parser;
+    FT_Error   error;
+
+
+    t1_init_loader( &loader, face );
+
+    parser = &loader.parser;
+    error = CID_New_Parser( parser, face->root.stream, face->root.memory,
+                            (PSAux_Interface*)face->psaux );
+    if ( error )
+      goto Exit;
+
+    error = cid_parse_dict( face, &loader,
+                            parser->postscript,
+                            parser->postscript_len );
+    if ( error )
+      goto Exit;
+
+    face->cid.data_offset = loader.parser.data_offset;
+    error = cid_read_subrs( face );
+
+  Exit:
+    t1_done_loader( &loader );
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cidobjs.c b/libraries/freetype-2.0.5/cidobjs.c
new file mode 100644 (file)
index 0000000..77c25ed
--- /dev/null
@@ -0,0 +1,383 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidobjs.c                                                              */
+/*                                                                         */
+/*    CID objects manager (body).                                          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include "cidgload.h"
+#include "cidload.h"
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+#include "ciderrs.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cidobjs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                           FACE  FUNCTIONS                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Done_Face                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given face object.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A pointer to the face object to destroy.                   */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  CID_Done_Face( CID_Face  face )
+  {
+    FT_Memory  memory;
+
+
+    if ( face )
+    {
+      CID_Info*     cid  = &face->cid;
+      T1_FontInfo*  info = &cid->font_info;
+
+
+      memory = face->root.memory;
+
+      /* release FontInfo strings */
+      FREE( info->version );
+      FREE( info->notice );
+      FREE( info->full_name );
+      FREE( info->family_name );
+      FREE( info->weight );
+
+      /* release font dictionaries */
+      FREE( cid->font_dicts );
+      cid->num_dicts = 0;
+
+      /* release other strings */
+      FREE( cid->cid_font_name );
+      FREE( cid->registry );
+      FREE( cid->ordering );
+
+      face->root.family_name = 0;
+      face->root.style_name  = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Init_Face                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given CID face object.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     :: The source font stream.                              */
+  /*                                                                       */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*                                                                       */
+  /*    num_params :: Number of additional generic parameters.  Ignored.   */
+  /*                                                                       */
+  /*    params     :: Additional generic parameters.  Ignored.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The newly built face object.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  CID_Init_Face( FT_Stream      stream,
+                 CID_Face       face,
+                 FT_Int         face_index,
+                 FT_Int         num_params,
+                 FT_Parameter*  params )
+  {
+    FT_Error            error;
+    PSNames_Interface*  psnames;
+    PSAux_Interface*    psaux;
+
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+    FT_UNUSED( face_index );
+    FT_UNUSED( stream );
+
+
+    face->root.num_faces = 1;
+
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( !psnames )
+    {
+      psnames = (PSNames_Interface*)FT_Get_Module_Interface(
+                  FT_FACE_LIBRARY( face ), "psnames" );
+
+      face->psnames = psnames;
+    }
+
+    psaux = (PSAux_Interface*)face->psaux;
+    if ( !psaux )
+    {
+      psaux = (PSAux_Interface*)FT_Get_Module_Interface(
+                  FT_FACE_LIBRARY( face ), "psaux" );
+
+      face->psaux = psaux;
+    }
+
+    /* open the tokenizer; this will also check the font format */
+    if ( FILE_Seek( 0 ) )
+      goto Exit;
+
+    error = CID_Open_Face( face );
+    if ( error )
+      goto Exit;
+
+    /* if we just wanted to check the format, leave successfully now */
+    if ( face_index < 0 )
+      goto Exit;
+
+    /* check the face index */
+    if ( face_index != 0 )
+    {
+      FT_ERROR(( "CID_Init_Face: invalid face index\n" ));
+      error = CID_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* Now, load the font program into the face object */
+    {
+      /* Init the face object fields */
+      /* Now set up root face fields */
+      {
+        FT_Face  root = (FT_Face)&face->root;
+
+
+        root->num_glyphs   = face->cid.cid_count;
+        root->num_charmaps = 0;
+
+        root->face_index = face_index;
+        root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+        root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+        if ( face->cid.font_info.is_fixed_pitch )
+          root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+        /* XXX: TODO: add kerning with .afm support */
+
+        /* get style name -- be careful, some broken fonts only */
+        /* have a /FontName dictionary entry!                   */
+        root->family_name = face->cid.font_info.family_name;
+        if ( root->family_name )
+        {
+          char*  full   = face->cid.font_info.full_name;
+          char*  family = root->family_name;
+
+          while ( *family && *full == *family )
+          {
+            family++;
+            full++;
+          }
+
+          root->style_name = ( *full == ' ' ) ? full + 1
+                                              : (char *)"Regular";
+        }
+        else
+        {
+          /* do we have a `/FontName'? */
+          if ( face->cid.cid_font_name )
+          {
+            root->family_name = face->cid.cid_font_name;
+            root->style_name  = (char *)"Regular";
+          }
+        }
+
+        /* no embedded bitmap support */
+        root->num_fixed_sizes = 0;
+        root->available_sizes = 0;
+
+        root->bbox = face->cid.font_bbox;
+        if ( !root->units_per_EM )
+          root->units_per_EM  = 1000;
+
+        root->ascender  = (FT_Short)( face->cid.font_bbox.yMax >> 16 );
+        root->descender = (FT_Short)( face->cid.font_bbox.yMin >> 16 );
+        root->height    = (FT_Short)(
+          ( ( root->ascender + root->descender ) * 12 ) / 10 );
+
+
+#if 0
+
+        /* now compute the maximum advance width */
+
+        root->max_advance_width = face->type1.private_dict.standard_width[0];
+
+        /* compute max advance width for proportional fonts */
+        if ( !face->type1.font_info.is_fixed_pitch )
+        {
+          FT_Int  max_advance;
+
+
+          error = CID_Compute_Max_Advance( face, &max_advance );
+
+          /* in case of error, keep the standard width */
+          if ( !error )
+            root->max_advance_width = max_advance;
+          else
+            error = 0;   /* clear error */
+        }
+
+        root->max_advance_height = root->height;
+
+#endif /* 0 */
+
+        root->underline_position  = face->cid.font_info.underline_position;
+        root->underline_thickness = face->cid.font_info.underline_thickness;
+
+        root->internal->max_points   = 0;
+        root->internal->max_contours = 0;
+      }
+    }
+
+#if 0
+
+    /* charmap support - synthetize unicode charmap when possible */
+    {
+      FT_Face      root    = &face->root;
+      FT_CharMap   charmap = face->charmaprecs;
+
+
+      /* synthesize a Unicode charmap if there is support in the `psnames' */
+      /* module                                                            */
+      if ( face->psnames )
+      {
+        PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
+
+
+        if ( psnames->unicode_value )
+        {
+          error = psnames->build_unicodes(
+                             root->memory,
+                             face->type1.num_glyphs,
+                             (const char**)face->type1.glyph_names,
+                             &face->unicode_map );
+          if ( !error )
+          {
+            root->charmap        = charmap;
+            charmap->face        = (FT_Face)face;
+            charmap->encoding    = ft_encoding_unicode;
+            charmap->platform_id = 3;
+            charmap->encoding_id = 1;
+            charmap++;
+          }
+
+          /* simply clear the error in case of failure (which really */
+          /* means that out of memory or no unicode glyph names)     */
+          error = 0;
+        }
+      }
+
+      /* now, support either the standard, expert, or custom encodings */
+      charmap->face        = (FT_Face)face;
+      charmap->platform_id = 7;  /* a new platform id for Adobe fonts? */
+
+      switch ( face->type1.encoding_type )
+      {
+      case t1_encoding_standard:
+        charmap->encoding    = ft_encoding_adobe_standard;
+        charmap->encoding_id = 0;
+        break;
+
+      case t1_encoding_expert:
+        charmap->encoding    = ft_encoding_adobe_expert;
+        charmap->encoding_id = 1;
+        break;
+
+      default:
+        charmap->encoding    = ft_encoding_adobe_custom;
+        charmap->encoding_id = 2;
+        break;
+      }
+
+      root->charmaps     = face->charmaps;
+      root->num_charmaps = charmap - face->charmaprecs + 1;
+      face->charmaps[0]  = &face->charmaprecs[0];
+      face->charmaps[1]  = &face->charmaprecs[1];
+    }
+
+#endif /* 0 */
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Init_Driver                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given CID driver object.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  CID_Init_Driver( CID_Driver  driver )
+  {
+    FT_UNUSED( driver );
+
+    return CID_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    CID_Done_Driver                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given CID driver.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target CID driver.                       */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  CID_Done_Driver( CID_Driver  driver )
+  {
+    FT_UNUSED( driver );
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cidparse.c b/libraries/freetype-2.0.5/cidparse.c
new file mode 100644 (file)
index 0000000..f87e09d
--- /dev/null
@@ -0,0 +1,157 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidparse.c                                                             */
+/*                                                                         */
+/*    CID-keyed Type1 parser (body).                                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_STREAM_H
+
+#include "cidparse.h"
+
+#include "ciderrs.h"
+
+#include <string.h>     /* for strncmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cidparse
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    INPUT STREAM PARSER                        *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_LOCAL_DEF FT_Error
+  CID_New_Parser( CID_Parser*       parser,
+                  FT_Stream         stream,
+                  FT_Memory         memory,
+                  PSAux_Interface*  psaux )
+  {
+    FT_Error  error;
+    FT_ULong  base_offset, offset, ps_len;
+    FT_Byte   buffer[256 + 10];
+    FT_Int    buff_len;
+
+
+    MEM_Set( parser, 0, sizeof ( *parser ) );
+    psaux->t1_parser_funcs->init( &parser->root, 0, 0, memory );
+
+    parser->stream = stream;
+
+    base_offset = FILE_Pos();
+
+    /* first of all, check the font format in the  header */
+    if ( ACCESS_Frame( 31 ) )
+      goto Exit;
+
+    if ( strncmp( (char *)stream->cursor,
+                  "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
+    {
+      FT_TRACE2(( "[not a valid CID-keyed font]\n" ));
+      error = CID_Err_Unknown_File_Format;
+    }
+
+    FORGET_Frame();
+    if ( error )
+      goto Exit;
+
+    /* now, read the rest of the file, until we find a `StartData' */
+    buff_len = 256;
+    for (;;)
+    {
+      FT_Byte   *p, *limit = buffer + 256;
+      FT_ULong  top_position;
+
+
+      /* fill input buffer */
+      buff_len -= 256;
+      if ( buff_len > 0 )
+        MEM_Move( buffer, limit, buff_len );
+
+      p = buffer + buff_len;
+
+      if ( FILE_Read( p, 256 + 10 - buff_len ) )
+        goto Exit;
+
+      top_position = FILE_Pos() - buff_len;
+      buff_len = 256 + 10;
+
+      /* look for `StartData' */
+      for ( p = buffer; p < limit; p++ )
+      {
+        if ( p[0] == 'S' && strncmp( (char*)p, "StartData", 9 ) == 0 )
+        {
+          /* save offset of binary data after `StartData' */
+          offset = (FT_ULong)( top_position - ( limit - p ) + 10 );
+          goto Found;
+        }
+      }
+    }
+
+  Found:
+    /* we have found the start of the binary data.  We will now        */
+    /* rewind and extract the frame of corresponding to the Postscript */
+    /* section                                                         */
+
+    ps_len = offset - base_offset;
+    if ( FILE_Seek( base_offset )                    ||
+         EXTRACT_Frame( ps_len, parser->postscript ) )
+      goto Exit;
+
+    parser->data_offset    = offset;
+    parser->postscript_len = ps_len;
+    parser->root.base      = parser->postscript;
+    parser->root.cursor    = parser->postscript;
+    parser->root.limit     = parser->root.cursor + ps_len;
+    parser->num_dict       = -1;
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF void
+  CID_Done_Parser( CID_Parser*  parser )
+  {
+    /* always free the private dictionary */
+    if ( parser->postscript )
+    {
+      FT_Stream  stream = parser->stream;
+
+
+      RELEASE_Frame( parser->postscript );
+    }
+    parser->root.funcs.done( &parser->root );
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/cidriver.c b/libraries/freetype-2.0.5/cidriver.c
new file mode 100644 (file)
index 0000000..8de7852
--- /dev/null
@@ -0,0 +1,265 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidriver.c                                                             */
+/*                                                                         */
+/*    CID driver interface (body).                                         */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "cidriver.h"
+#include "cidgload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+
+#include "ciderrs.h"
+
+#include <string.h>         /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ciddriver
+
+
+
+  static const char*
+  cid_get_postscript_name( CID_Face  face )
+  {
+    return (const char*)face->cid.cid_font_name;
+  }
+
+
+  static FT_Module_Interface
+  CID_Get_Interface( FT_Driver         driver,
+                     const FT_String*  interface )
+  {
+    FT_UNUSED( driver );
+    FT_UNUSED( interface );
+
+    if ( strcmp( (const char*)interface, "postscript_name" ) == 0 )
+      return (FT_Module_Interface)cid_get_postscript_name;
+
+    return 0;
+  }
+
+
+#if 0 /* unimplemented yet */
+
+  static FT_Error
+  cid_Get_Kerning( T1_Face     face,
+                   FT_UInt     left_glyph,
+                   FT_UInt     right_glyph,
+                   FT_Vector*  kerning )
+  {
+    CID_AFM*  afm;
+
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    afm = (CID_AFM*)face->afm_data;
+    if ( afm )
+      CID_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+    return CID_Err_Ok;
+  }
+
+
+#endif /* 0 */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Cid_Get_Char_Index                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*                                                                       */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static FT_UInt
+  CID_Get_Char_Index( FT_CharMap  charmap,
+                      FT_Long     charcode )
+  {
+    T1_Face             face;
+    FT_UInt             result = 0;
+    PSNames_Interface*  psnames;
+
+
+    face = (T1_Face)charmap->face;
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( psnames )
+      switch ( charmap->encoding )
+      {
+        /*******************************************************************/
+        /*                                                                 */
+        /* Unicode encoding support                                        */
+        /*                                                                 */
+      case ft_encoding_unicode:
+        /* use the `PSNames' module to synthetize the Unicode charmap */
+        result = psnames->lookup_unicode( &face->unicode_map,
+                                          (FT_ULong)charcode );
+
+        /* the function returns 0xFFFF if the Unicode charcode has */
+        /* no corresponding glyph.                                 */
+        if ( result == 0xFFFF )
+          result = 0;
+        goto Exit;
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Custom Type 1 encoding                                          */
+        /*                                                                 */
+      case ft_encoding_adobe_custom:
+        {
+          T1_Encoding*  encoding = &face->type1.encoding;
+
+
+          if ( charcode >= encoding->code_first &&
+               charcode <= encoding->code_last  )
+            result = encoding->char_index[charcode];
+          goto Exit;
+        }
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Adobe Standard & Expert encoding support                        */
+        /*                                                                 */
+      default:
+        if ( charcode < 256 )
+        {
+          FT_UInt      code;
+          FT_Int       n;
+          const char*  glyph_name;
+
+
+          code = psnames->adobe_std_encoding[charcode];
+          if ( charmap->encoding == ft_encoding_adobe_expert )
+            code = psnames->adobe_expert_encoding[charcode];
+
+          glyph_name = psnames->adobe_std_strings( code );
+          if ( !glyph_name )
+            break;
+
+          for ( n = 0; n < face->type1.num_glyphs; n++ )
+          {
+            const char*  gname = face->type1.glyph_names[n];
+
+
+            if ( gname && gname[0] == glyph_name[0] &&
+                 strcmp( gname, glyph_name ) == 0   )
+            {
+              result = n;
+              break;
+            }
+          }
+        }
+      }
+
+  Exit:
+    return result;
+  }
+
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Driver_Class  t1cid_driver_class =
+  {
+    /* first of all, the FT_Module_Class fields */
+    {
+      ft_module_font_driver | ft_module_driver_scalable,
+      sizeof( FT_DriverRec ),
+      "t1cid",   /* module name           */
+      0x10000L,  /* version 1.0 of driver */
+      0x20000L,  /* requires FreeType 2.0 */
+
+      0,
+
+      (FT_Module_Constructor)CID_Init_Driver,
+      (FT_Module_Destructor) CID_Done_Driver,
+      (FT_Module_Requester)  CID_Get_Interface
+    },
+
+    /* then the other font drivers fields */
+    sizeof( CID_FaceRec ),
+    sizeof( CID_SizeRec ),
+    sizeof( CID_GlyphSlotRec ),
+
+    (FTDriver_initFace)     CID_Init_Face,
+    (FTDriver_doneFace)     CID_Done_Face,
+
+    (FTDriver_initSize)     0,
+    (FTDriver_doneSize)     0,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) 0,
+    (FTDriver_setPixelSizes)0,
+
+    (FTDriver_loadGlyph)    CID_Load_Glyph,
+    (FTDriver_getCharIndex) CID_Get_Char_Index,
+
+    (FTDriver_getKerning)   0,
+    (FTDriver_attachFile)   0,
+
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverClass                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the TrueType driver as a      */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+  FT_EXPORT_DEF( const FT_Driver_Class* )
+  getDriverClass( void )
+  {
+    return &t1cid_driver_class;
+  }
+
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftbase.c b/libraries/freetype-2.0.5/ftbase.c
new file mode 100644 (file)
index 0000000..e6b7869
--- /dev/null
@@ -0,0 +1,35 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftbase.c                                                               */
+/*                                                                         */
+/*    Single object library component (body only).                         */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+
+#define  FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include "ftcalc.c"
+#include "fttrigon.c"
+#include "ftobjs.c"
+#include "ftstream.c"
+#include "ftlist.c"
+#include "ftoutln.c"
+#include "ftnames.c"
+
+#if 0
+#include "ftextend.c"
+#endif
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftbbox.c b/libraries/freetype-2.0.5/ftbbox.c
new file mode 100644 (file)
index 0000000..f30b8fb
--- /dev/null
@@ -0,0 +1,653 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftbbox.c                                                               */
+/*                                                                         */
+/*    FreeType bbox computation (body).                                    */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used        */
+/*  modified and distributed under the terms of the FreeType project       */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This component has a _single_ role: to compute exact outline bounding */
+  /* boxes.                                                                */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_BBOX_H
+#include FT_IMAGE_H
+#include FT_OUTLINE_H
+#include FT_INTERNAL_CALC_H
+
+
+  typedef struct  TBBox_Rec_
+  {
+    FT_Vector  last;
+    FT_BBox    bbox;
+
+  } TBBox_Rec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    BBox_Move_To                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used as a `move_to' and `line_to' emitter during  */
+  /*    FT_Outline_Decompose().  It simply records the destination point   */
+  /*    in `user->last'; no further computations are necessary since we    */
+  /*    the cbox as the starting bbox which must be refined.               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    to   :: A pointer to the destination vector.                       */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    user :: A pointer to the current walk context.                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Always 0.  Needed for the interface only.                          */
+  /*                                                                       */
+  static int
+  BBox_Move_To( FT_Vector*  to,
+                TBBox_Rec*  user )
+  {
+    user->last = *to;
+
+    return 0;
+  }
+
+
+#define CHECK_X( p, bbox )  \
+          ( p->x < bbox.xMin || p->x > bbox.xMax )
+
+#define CHECK_Y( p, bbox )  \
+          ( p->y < bbox.yMin || p->y > bbox.yMax )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    BBox_Conic_Check                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finds the extrema of a 1-dimensional conic Bezier curve and update */
+  /*    a bounding range.  This version uses direct computation, as it     */
+  /*    doesn't need square roots.                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    y1  :: The start coordinate.                                       */
+  /*    y2  :: The coordinate of the control point.                        */
+  /*    y3  :: The end coordinate.                                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    min :: The address of the current minimum.                         */
+  /*    max :: The address of the current maximum.                         */
+  /*                                                                       */
+  static void
+  BBox_Conic_Check( FT_Pos   y1,
+                    FT_Pos   y2,
+                          FT_Pos   y3,
+                          FT_Pos*  min,
+                          FT_Pos*  max )
+  {
+    if ( y1 <= y3 )
+    {
+      if ( y2 == y1 )               /* Flat arc */
+        goto Suite;
+    }
+    else if ( y1 < y3 )
+    {
+      if ( y2 >= y1 && y2 <= y3 )   /* Ascending arc */
+        goto Suite;
+    }
+    else
+    {
+      if ( y2 >= y3 && y2 <= y1 )   /* Descending arc */
+      {
+        y2 = y1;
+        y1 = y3;
+        y3 = y2;
+        goto Suite;
+      }
+    }
+
+    y1 = y3 = y1 - FT_MulDiv( y2 - y1, y2 - y1, y1 - 2*y2 + y3 );
+
+  Suite:
+    if ( y1 < *min ) *min = y1;
+    if ( y3 > *max ) *max = y3;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    BBox_Conic_To                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used as a `conic_to' emitter during               */
+  /*    FT_Raster_Decompose().  It checks a conic Bezier curve with the    */
+  /*    current bounding box, and computes its extrema if necessary to     */
+  /*    update it.                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    control :: A pointer to a control point.                           */
+  /*    to      :: A pointer to the destination vector.                    */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    user    :: The address of the current walk context.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Always 0.  Needed for the interface only.                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    In the case of a non-monotonous arc, we compute directly the       */
+  /*    extremum coordinates, as it is sufficiently fast.                  */
+  /*                                                                       */
+  static int
+  BBox_Conic_To( FT_Vector*  control,
+                 FT_Vector*  to,
+                 TBBox_Rec*  user )
+  {
+    /* we don't need to check `to' since it is always an `on' point, thus */
+    /* within the bbox                                                    */
+
+    if ( CHECK_X( control, user->bbox ) )
+
+      BBox_Conic_Check( user->last.x,
+                        control->x,
+                        to->x,
+                        &user->bbox.xMin,
+                        &user->bbox.xMax );
+
+    if ( CHECK_Y( control, user->bbox ) )
+
+      BBox_Conic_Check( user->last.y,
+                        control->y,
+                        to->y,
+                        &user->bbox.yMin,
+                        &user->bbox.yMax );
+
+    user->last = *to;
+
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    BBox_Cubic_Check                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finds the extrema of a 1-dimensional cubic Bezier curve and        */
+  /*    updates a bounding range.  This version uses splitting because we  */
+  /*    don't want to use square roots and extra accuracies.               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    p1  :: The start coordinate.                                       */
+  /*    p2  :: The coordinate of the first control point.                  */
+  /*    p3  :: The coordinate of the second control point.                 */
+  /*    p4  :: The end coordinate.                                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    min :: The address of the current minimum.                         */
+  /*    max :: The address of the current maximum.                         */
+  /*                                                                       */
+#if 0
+  static void
+  BBox_Cubic_Check( FT_Pos   p1,
+                    FT_Pos   p2,
+                    FT_Pos   p3,
+                    FT_Pos   p4,
+                    FT_Pos*  min,
+                    FT_Pos*  max )
+  {
+    FT_Pos  stack[32*3 + 1], *arc;
+
+
+    arc = stack;
+
+    arc[0] = p1;
+    arc[1] = p2;
+    arc[2] = p3;
+    arc[3] = p4;
+
+    do
+    {
+      FT_Pos  y1 = arc[0];
+      FT_Pos  y2 = arc[1];
+      FT_Pos  y3 = arc[2];
+      FT_Pos  y4 = arc[3];
+
+
+      if ( y1 == y4 )
+      {
+        if ( y1 == y2 && y1 == y3 )                         /* Flat */
+          goto Test;
+      }
+      else if ( y1 < y4 )
+      {
+        if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* Ascending */
+          goto Test;
+      }
+      else
+      {
+        if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* Descending */
+        {
+          y2 = y1;
+          y1 = y4;
+          y4 = y2;
+          goto Test;
+        }
+      }
+
+      /* Unknown direction -- split the arc in two */
+      arc[6] = y4;
+      arc[1] = y1 = ( y1 + y2 ) / 2;
+      arc[5] = y4 = ( y4 + y3 ) / 2;
+      y2 = ( y2 + y3 ) / 2;
+      arc[2] = y1 = ( y1 + y2 ) / 2;
+      arc[4] = y4 = ( y4 + y2 ) / 2;
+      arc[3] = ( y1 + y4 ) / 2;
+
+      arc += 3;
+      goto Suite;
+
+   Test:
+      if ( y1 < *min ) *min = y1;
+      if ( y4 > *max ) *max = y4;
+      arc -= 3;
+
+    Suite:
+      ;
+    } while ( arc >= stack );
+  }
+#else
+
+  static void
+  test_cubic_extrema( FT_Pos    y1,
+                      FT_Pos    y2,
+                      FT_Pos    y3,
+                      FT_Pos    y4,
+                      FT_Fixed  u,
+                      FT_Pos*   min,
+                      FT_Pos*   max )
+  {
+ /* FT_Pos    a = y4 - 3*y3 + 3*y2 - y1; */
+    FT_Pos    b = y3 - 2*y2 + y1;
+    FT_Pos    c = y2 - y1;
+    FT_Pos    d = y1;
+    FT_Pos    y;
+    FT_Fixed  uu;
+
+    FT_UNUSED ( y4 );
+
+
+    /* The polynom is                       */
+    /*                                      */
+    /*   a*x^3 + 3b*x^2 + 3c*x + d      .   */
+    /*                                      */
+    /* However, we also have                */
+    /*                                      */
+    /*   dP/dx(u) = 0       ,               */
+    /*                                      */
+    /* which implies that                   */
+    /*                                      */
+    /*   P(u) = b*u^2 + 2c*u + d            */
+
+    if ( u > 0 && u < 0x10000L )
+    {
+      uu = FT_MulFix( u, u );
+      y  = d + FT_MulFix( c, 2*u ) + FT_MulFix( b, uu );
+
+      if ( y < *min ) *min = y;
+      if ( y > *max ) *max = y;
+    }
+  }
+
+
+  static void
+  BBox_Cubic_Check( FT_Pos   y1,
+                    FT_Pos   y2,
+                    FT_Pos   y3,
+                    FT_Pos   y4,
+                    FT_Pos*  min,
+                    FT_Pos*  max )
+  {
+    /* always compare first and last points */
+    if      ( y1 < *min )  *min = y1;
+    else if ( y1 > *max )  *max = y1;
+
+    if      ( y4 < *min )  *min = y4;
+    else if ( y4 > *max )  *max = y4;
+
+    /* now, try to see if there are split points here */
+    if ( y1 <= y4 )
+    {
+      /* flat or ascending arc test */
+      if ( y1 <= y2 && y2 <= y4 && y1 <= y3 && y3 <= y4 )
+        return;
+    }
+    else /* y1 > y4 */
+    {
+      /* descending arc test */
+      if ( y1 >= y2 && y2 >= y4 && y1 >= y3 && y3 >= y4 )
+        return;
+    }
+
+    /* There are some split points.  Find them. */
+    {
+      FT_Pos    a = y4 - 3*y3 + 3*y2 - y1;
+      FT_Pos    b = y3 - 2*y2 + y1;
+      FT_Pos    c = y2 - y1;
+      FT_Pos    d;
+      FT_Fixed  t;
+
+
+      /* We need to solve "ax^2+2bx+c" here, without floating points!      */
+      /* The trick is to normalize to a different representation in order  */
+      /* to use our 16.16 fixed point routines.                            */
+      /*                                                                   */
+      /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after the            */
+      /* the normalization.  These values must fit into a single 16.16     */
+      /* value.                                                            */
+      /*                                                                   */
+      /* We normalize a, b, and c to "8.16" fixed float values to ensure   */
+      /* that their product is held in a "16.16" value.                    */
+      /*                                                                   */
+      {
+        FT_ULong  t1, t2;
+        int       shift = 0;
+
+
+        /* Technical explanation of what's happening there.            */
+        /*                                                             */
+        /*   The following computation is based on the fact that for   */
+        /*   any value "y", if "n" is the position of the most         */
+        /*   significant bit of "abs(y)" (starting from 0 for the      */
+        /*   least significant bit), then y is in the range            */
+        /*                                                             */
+        /*                  "-2^n..2^n-1"                              */
+        /*                                                             */
+        /*   We want to shift "a", "b" and "c" concurrently in order   */
+        /*   to ensure that they all fit in 8.16 values, which maps    */
+        /*   to the integer range "-2^23..2^23-1".                     */
+        /*                                                             */
+        /*   Necessarily, we need to shift "a", "b" and "c" so that    */
+        /*   the most significant bit of their absolute values is at   */
+        /*   _most_ at position 23.                                    */
+        /*                                                             */
+        /*   We begin by computing "t1" as the bitwise "or" of the     */
+        /*   absolute values of "a", "b", "c".                         */
+        /*                                                             */
+        t1  = (FT_ULong)((a >= 0) ? a : -a );
+        t2  = (FT_ULong)((b >= 0) ? b : -b );
+        t1 |= t2;
+        t2  = (FT_ULong)((c >= 0) ? c : -c );
+        t1 |= t2;
+
+        /*   Now, the most significant bit of "t1" is sure to be the   */
+        /*   msb of one of "a", "b", "c", depending on which one is    */
+        /*   expressed in the greatest integer range.                  */
+        /*                                                             */
+        /*   We now compute the "shift", by shifting "t1" as many      */
+        /*   times as necessary to move its msb to position 23.        */
+        /*                                                             */
+        /*   This corresponds to a value of t1 that is in the range    */
+        /*   0x40_0000..0x7F_FFFF.                                     */
+        /*                                                             */
+        /*   Finally, we shift "a", "b" and "c" by the same amount.    */
+        /*   This ensures that all values are now in the range         */
+        /*   -2^23..2^23, i.e. that they are now expressed as 8.16     */
+        /*   fixed float numbers.                                      */
+        /*                                                             */
+        /*   This also means that we are using 24 bits of precision    */
+        /*   to compute the zeros, independently of the range of       */
+        /*   the original polynom coefficients.                        */
+        /*                                                             */
+        /*   This should ensure reasonably accurate values for the     */
+        /*   zeros.  Note that the latter are only expressed with      */
+        /*   16 bits when computing the extrema (the zeros need to     */
+        /*   be in 0..1 exclusive to be considered part of the arc).   */
+        /*                                                             */
+        if ( t1 == 0 )  /* all coefficients are 0! */
+          return;
+
+        if ( t1 > 0x7FFFFFUL )
+        {
+          do
+          {
+            shift++;
+            t1 >>= 1;
+          } while ( t1 > 0x7FFFFFUL );
+
+          /* losing some bits of precision, but we use 24 of them */
+          /* for the computation anyway.                          */
+          a >>= shift;
+          b >>= shift;
+          c >>= shift;
+        }
+        else if ( t1 < 0x400000UL )
+        {
+          do
+          {
+            shift++;
+            t1 <<= 1;
+          } while ( t1 < 0x400000UL );
+
+          a <<= shift;
+          b <<= shift;
+          c <<= shift;
+        }
+      }
+
+      /* handle a == 0 */
+      if ( a == 0 )
+      {
+        if ( b != 0 )
+        {
+          t = - FT_DivFix( c, b ) / 2;
+          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
+        }
+      }
+      else
+      {
+        /* solve the equation now */
+        d = FT_MulFix( b, b ) - FT_MulFix( a, c );
+        if ( d < 0 )
+          return;
+
+        if ( d == 0 )
+        {
+          /* there is a single split point at -b/a */
+          t = - FT_DivFix( b, a );
+          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
+        }
+        else
+        {
+          /* there are two solutions; we need to filter them though */
+          d = FT_SqrtFixed( (FT_Int32)d );
+          t = - FT_DivFix( b - d, a );
+          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
+
+          t = - FT_DivFix( b + d, a );
+          test_cubic_extrema( y1, y2, y3, y4, t, min, max );
+        }
+      }
+    }
+  }
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    BBox_Cubic_To                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used as a `cubic_to' emitter during               */
+  /*    FT_Raster_Decompose().  It checks a cubic Bezier curve with the    */
+  /*    current bounding box, and computes its extrema if necessary to     */
+  /*    update it.                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    control1 :: A pointer to the first control point.                  */
+  /*    control2 :: A pointer to the second control point.                 */
+  /*    to       :: A pointer to the destination vector.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    user     :: The address of the current walk context.               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Always 0.  Needed for the interface only.                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    In the case of a non-monotonous arc, we don't compute directly     */
+  /*    extremum coordinates, we subdivise instead.                        */
+  /*                                                                       */
+  static int
+  BBox_Cubic_To( FT_Vector*  control1,
+                 FT_Vector*  control2,
+                 FT_Vector*  to,
+                 TBBox_Rec*  user )
+  {
+    /* we don't need to check `to' since it is always an `on' point, thus */
+    /* within the bbox                                                    */
+
+    if ( CHECK_X( control1, user->bbox ) ||
+         CHECK_X( control2, user->bbox ) )
+
+        BBox_Cubic_Check( user->last.x,
+                          control1->x,
+                          control2->x,
+                          to->x,
+                          &user->bbox.xMin,
+                          &user->bbox.xMax );
+
+    if ( CHECK_Y( control1, user->bbox ) ||
+         CHECK_Y( control2, user->bbox ) )
+
+        BBox_Cubic_Check( user->last.y,
+                          control1->y,
+                          control2->y,
+                          to->y,
+                          &user->bbox.yMin,
+                          &user->bbox.yMax );
+
+    user->last = *to;
+
+    return 0;
+  }
+
+
+  /* documentation is in ftbbox.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_Get_BBox( FT_Outline*  outline,
+                       FT_BBox     *abbox )
+  {
+    FT_BBox     cbox;
+    FT_BBox     bbox;
+    FT_Vector*  vec;
+    FT_UShort   n;
+
+
+    if ( !abbox )
+      return FT_Err_Invalid_Argument;
+
+    if ( !outline )
+      return FT_Err_Invalid_Outline;
+
+    /* if outline is empty, return (0,0,0,0) */
+    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+    {
+      abbox->xMin = abbox->xMax = 0;
+      abbox->yMin = abbox->yMax = 0;
+      return 0;
+    }
+
+    /* We compute the control box as well as the bounding box of  */
+    /* all `on' points in the outline.  Then, if the two boxes    */
+    /* coincide, we exit immediately.                             */
+
+    vec = outline->points;
+    bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x;
+    bbox.yMin = bbox.yMax = cbox.yMin = cbox.yMax = vec->y;
+    vec++;
+
+    for ( n = 1; n < outline->n_points; n++ )
+    {
+      FT_Pos  x = vec->x;
+      FT_Pos  y = vec->y;
+
+
+      /* update control box */
+      if ( x < cbox.xMin ) cbox.xMin = x;
+      if ( x > cbox.xMax ) cbox.xMax = x;
+
+      if ( y < cbox.yMin ) cbox.yMin = y;
+      if ( y > cbox.yMax ) cbox.yMax = y;
+
+      if ( FT_CURVE_TAG( outline->tags[n] ) == FT_Curve_Tag_On )
+      {
+        /* update bbox for `on' points only */
+        if ( x < bbox.xMin ) bbox.xMin = x;
+        if ( x > bbox.xMax ) bbox.xMax = x;
+
+        if ( y < bbox.yMin ) bbox.yMin = y;
+        if ( y > bbox.yMax ) bbox.yMax = y;
+      }
+
+      vec++;
+    }
+
+    /* test two boxes for equality */
+    if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax ||
+         cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax )
+    {
+      /* the two boxes are different, now walk over the outline to */
+      /* get the Bezier arc extrema.                               */
+
+      static const FT_Outline_Funcs  interface =
+      {
+        (FT_Outline_MoveTo_Func) BBox_Move_To,
+        (FT_Outline_LineTo_Func) BBox_Move_To,
+        (FT_Outline_ConicTo_Func)BBox_Conic_To,
+        (FT_Outline_CubicTo_Func)BBox_Cubic_To,
+        0, 0
+      };
+
+      FT_Error   error;
+      TBBox_Rec  user;
+
+
+      user.bbox = bbox;
+
+      error = FT_Outline_Decompose( outline, &interface, &user );
+      if ( error )
+        return error;
+
+      *abbox = user.bbox;
+    }
+    else
+      *abbox = bbox;
+
+    return FT_Err_Ok;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftcache.c b/libraries/freetype-2.0.5/ftcache.c
new file mode 100644 (file)
index 0000000..63f7f8e
--- /dev/null
@@ -0,0 +1,30 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcache.c                                                              */
+/*                                                                         */
+/*    The FreeType Caching sub-system (body only).                         */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ftlru.c"
+#include "ftcmanag.c"
+#include "ftcglyph.c"
+#include "ftcchunk.c"
+#include "ftcimage.c"
+#include "ftcsbits.c"
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftcalc.c b/libraries/freetype-2.0.5/ftcalc.c
new file mode 100644 (file)
index 0000000..247ee03
--- /dev/null
@@ -0,0 +1,649 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcalc.c                                                               */
+/*                                                                         */
+/*    Arithmetic computations (body).                                      */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Support for 1-complement arithmetic has been totally dropped in this  */
+  /* release.  You can still write your own code if you need it.           */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Implementing basic computation routines.                              */
+  /*                                                                       */
+  /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(),   */
+  /* and FT_FloorFix() are declared in freetype.h.                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+/* we need to define a 64-bits data type here */
+#ifndef FT_CONFIG_OPTION_OLD_CALCS
+
+#ifdef FT_LONG64
+
+  typedef FT_INT64  FT_Int64;
+
+#else
+
+  typedef struct  FT_Int64_
+  {
+    FT_UInt32  lo;
+    FT_UInt32  hi;
+
+  } FT_Int64;
+
+#endif /* FT_LONG64 */
+
+#endif /* !FT_CONFIG_OPTION_OLD_CALCS */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_calc
+
+
+  /* The following three functions are available regardless of whether */
+  /* FT_LONG64 or FT_CONFIG_OPTION_OLD_CALCS is defined.               */
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Fixed )
+  FT_RoundFix( FT_Fixed  a )
+  {
+    return ( a >= 0 ) ?   ( a + 0x8000L ) & -0x10000L
+                      : -((-a + 0x8000L ) & -0x10000L );
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Fixed )
+  FT_CeilFix( FT_Fixed  a )
+  {
+    return ( a >= 0 ) ?   ( a + 0xFFFFL ) & -0x10000L
+                      : -((-a + 0xFFFFL ) & -0x10000L );
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Fixed )
+  FT_FloorFix( FT_Fixed  a )
+  {
+    return ( a >= 0 ) ?   a & -0x10000L
+                      : -((-a) & -0x10000L );
+  }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+  static const FT_Long  ft_square_roots[63] =
+  {
+       1L,    1L,    2L,     3L,     4L,     5L,     8L,    11L,
+      16L,   22L,   32L,    45L,    64L,    90L,   128L,   181L,
+     256L,  362L,  512L,   724L,  1024L,  1448L,  2048L,  2896L,
+    4096L, 5892L, 8192L, 11585L, 16384L, 23170L, 32768L, 46340L,
+
+      65536L,   92681L,  131072L,   185363L,   262144L,   370727L,
+     524288L,  741455L, 1048576L,  1482910L,  2097152L,  2965820L,
+    4194304L, 5931641L, 8388608L, 11863283L, 16777216L, 23726566L,
+
+      33554432L,   47453132L,   67108864L,   94906265L,
+     134217728L,  189812531L,  268435456L,  379625062L,
+     536870912L,  759250125L, 1073741824L, 1518500250L,
+    2147483647L
+  };
+
+#else
+
+  /* documentation is in ftcalc.h */
+
+  FT_EXPORT_DEF( FT_Int32 )
+  FT_Sqrt32( FT_Int32  x )
+  {
+    FT_ULong  val, root, newroot, mask;
+
+
+    root = 0;
+    mask = 0x40000000L;
+    val  = (FT_ULong)x;
+
+    do
+    {
+      newroot = root + mask;
+      if ( newroot <= val )
+      {
+        val -= newroot;
+        root = newroot + mask;
+      }
+
+      root >>= 1;
+      mask >>= 2;
+
+    } while ( mask != 0 );
+
+    return root;
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#ifdef FT_LONG64
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Long )
+  FT_MulDiv( FT_Long  a,
+             FT_Long  b,
+             FT_Long  c )
+  {
+    FT_Int   s;
+    FT_Long  d;
+
+
+    s = 1;
+    if ( a < 0 ) { a = -a; s = -1; }
+    if ( b < 0 ) { b = -b; s = -s; }
+    if ( c < 0 ) { c = -c; s = -s; }
+
+    d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
+                         : 0x7FFFFFFFL );
+
+    return ( s > 0 ) ? d : -d;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Long )
+  FT_MulFix( FT_Long  a,
+             FT_Long  b )
+  {
+    FT_Int   s = 1;
+    FT_Long  c;
+
+
+    if ( a < 0 ) { a = -a; s = -1; }
+    if ( b < 0 ) { b = -b; s = -s; }
+
+    c = (FT_Long)( ( (FT_Int64)a * b + 0x8000 ) >> 16 );
+    return ( s > 0 ) ? c : -c ;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Long )
+  FT_DivFix( FT_Long  a,
+             FT_Long  b )
+  {
+    FT_Int32   s;
+    FT_UInt32  q;
+
+    s = 1;
+    if ( a < 0 ) { a = -a; s = -1; }
+    if ( b < 0 ) { b = -b; s = -s; }
+
+    if ( b == 0 )
+      /* check for division by 0 */
+      q = 0x7FFFFFFFL;
+    else
+      /* compute result directly */
+      q = (FT_UInt32)( ( ( (FT_Int64)a << 16 ) + ( b >> 1 ) ) / b );
+
+    return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
+  }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+  /* a helper function for FT_Sqrt64() */
+
+  static int
+  ft_order64( FT_Int64  z )
+  {
+    int  j = 0;
+
+
+    while ( z )
+    {
+      z = (unsigned FT_INT64)z >> 1;
+      j++;
+    }
+    return j - 1;
+  }
+
+
+  /* documentation is in ftcalc.h */
+
+  FT_EXPORT_DEF( FT_Int32 )
+  FT_Sqrt64( FT_Int64  l )
+  {
+    FT_Int64  r, s;
+
+
+    if ( l <= 0 ) return 0;
+    if ( l == 1 ) return 1;
+
+    r = ft_square_roots[ft_order64( l )];
+
+    do
+    {
+      s = r;
+      r = ( r + l / r ) >> 1;
+
+    } while ( r > s || r * r > l );
+
+    return (FT_Int32)r;
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#else /* FT_LONG64 */
+
+
+  static void
+  ft_multo64( FT_UInt32  x,
+              FT_UInt32  y,
+              FT_Int64  *z )
+  {
+    FT_UInt32  lo1, hi1, lo2, hi2, lo, hi, i1, i2;
+
+
+    lo1 = x & 0x0000FFFFU;  hi1 = x >> 16;
+    lo2 = y & 0x0000FFFFU;  hi2 = y >> 16;
+
+    lo = lo1 * lo2;
+    i1 = lo1 * hi2;
+    i2 = lo2 * hi1;
+    hi = hi1 * hi2;
+
+    /* Check carry overflow of i1 + i2 */
+    i1 += i2;
+    hi += (FT_UInt32)( i1 < i2 ) << 16;
+
+    hi += i1 >> 16;
+    i1  = i1 << 16;
+
+    /* Check carry overflow of i1 + lo */
+    lo += i1;
+    hi += ( lo < i1 );
+
+    z->lo = lo;
+    z->hi = hi;
+  }
+
+
+  static FT_UInt32
+  ft_div64by32( FT_UInt32  hi,
+                FT_UInt32  lo,
+                FT_UInt32  y )
+  {
+    FT_UInt32  r, q;
+    FT_Int     i;
+
+
+    q = 0;
+    r = hi;
+
+    if ( r >= y )
+      return (FT_UInt32)0x7FFFFFFFL;
+
+    i = 32;
+    do
+    {
+      r <<= 1;
+      q <<= 1;
+      r  |= lo >> 31;
+
+      if ( r >= (FT_UInt32)y )
+      {
+        r -= y;
+        q |= 1;
+      }
+      lo <<= 1;
+    } while ( --i );
+
+    return q;
+  }
+
+
+  /* documentation is in ftcalc.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Add64( FT_Int64*  x,
+            FT_Int64*  y,
+            FT_Int64  *z )
+  {
+    register FT_UInt32  lo, hi, max;
+
+
+    max = x->lo > y->lo ? x->lo : y->lo;
+    lo  = x->lo + y->lo;
+    hi  = x->hi + y->hi + ( lo < max );
+
+    z->lo = lo;
+    z->hi = hi;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Long )
+  FT_MulDiv( FT_Long  a,
+             FT_Long  b,
+             FT_Long  c )
+  {
+    long  s;
+
+
+    if ( a == 0 || b == c )
+      return a;
+
+    s  = a; a = ABS( a );
+    s ^= b; b = ABS( b );
+    s ^= c; c = ABS( c );
+
+    if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )
+    {
+      a = ( a * b + ( c >> 1 ) ) / c;
+    }
+    else if ( c > 0 )
+    {
+      FT_Int64  temp, temp2;
+
+
+      ft_multo64( a, b, &temp );
+
+      temp2.hi = 0;
+      temp2.lo = (FT_UInt32)(c >> 1);
+      FT_Add64( &temp, &temp2, &temp );
+      a = ft_div64by32( temp.hi, temp.lo, c );
+    }
+    else
+      a = 0x7FFFFFFFL;
+
+    return ( s < 0 ? -a : a );
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Long )
+  FT_MulFix( FT_Long  a,
+             FT_Long  b )
+  {
+    FT_Long   s;
+    FT_ULong  ua, ub;
+
+
+    if ( a == 0 || b == 0x10000L )
+      return a;
+
+    s  = a; a = ABS(a);
+    s ^= b; b = ABS(b);
+
+    ua = (FT_ULong)a;
+    ub = (FT_ULong)b;
+
+    if ( ua <= 2048 && ub <= 1048576L )
+    {
+      ua = ( ua * ub + 0x8000 ) >> 16;
+    }
+    else
+    {
+      FT_ULong  al = ua & 0xFFFF;
+
+
+      ua = ( ua >> 16 ) * ub +  al * ( ub >> 16 ) +
+           ( ( al * ( ub & 0xFFFF ) + 0x8000 ) >> 16 );
+    }
+
+    return ( s < 0 ? -(FT_Long)ua : ua );
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Long )
+  FT_DivFix( FT_Long  a,
+             FT_Long  b )
+  {
+    FT_Int32   s;
+    FT_UInt32  q;
+
+
+    s  = a; a = ABS(a);
+    s ^= b; b = ABS(b);
+
+    if ( b == 0 )
+    {
+      /* check for division by 0 */
+      q = 0x7FFFFFFFL;
+    }
+    else if ( ( a >> 16 ) == 0 )
+    {
+      /* compute result directly */
+      q = (FT_UInt32)( (a << 16) + (b >> 1) ) / (FT_UInt32)b;
+    }
+    else
+    {
+      /* we need more bits; we have to do it by hand */
+      FT_Int64  temp, temp2;
+
+      temp.hi  = (FT_Int32) (a >> 16);
+      temp.lo  = (FT_UInt32)(a << 16);
+      temp2.hi = 0;
+      temp2.lo = (FT_UInt32)( b >> 1 );
+      FT_Add64( &temp, &temp2, &temp );
+      q = ft_div64by32( temp.hi, temp.lo, b );
+    }
+
+    return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+  }
+
+
+  /* documentation is in ftcalc.h */
+
+  FT_EXPORT_DEF( void )
+  FT_MulTo64( FT_Int32   x,
+              FT_Int32   y,
+              FT_Int64  *z )
+  {
+    FT_Int32  s;
+
+
+    s  = x; x = ABS( x );
+    s ^= y; y = ABS( y );
+
+    ft_multo64( x, y, z );
+
+    if ( s < 0 )
+    {
+      z->lo = (FT_UInt32)-(FT_Int32)z->lo;
+      z->hi = ~z->hi + !( z->lo );
+    }
+  }
+
+
+  /* documentation is in ftcalc.h */
+
+  FT_EXPORT_DEF( FT_Int32 )
+  FT_Div64by32( FT_Int64*  x,
+                FT_Int32   y )
+  {
+    FT_Int32   s;
+    FT_UInt32  q;
+
+
+    s  = x->hi;
+    if ( s < 0 )
+    {
+      x->lo = (FT_UInt32)-(FT_Int32)x->lo;
+      x->hi = ~x->hi + !( x->lo );
+    }
+    s ^= y;  y = ABS( y );
+
+    /* Shortcut */
+    if ( x->hi == 0 )
+    {
+      if ( y > 0 )
+        q = ( x->lo + ( y >> 1 ) ) / y;
+      else
+        q = 0x7FFFFFFFL;
+
+      return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+    }
+
+    q = ft_div64by32( x->hi, x->lo, y );
+
+    return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
+  }
+
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+
+  /* two helper functions for FT_Sqrt64() */
+
+  static void
+  FT_Sub64( FT_Int64*  x,
+            FT_Int64*  y,
+            FT_Int64*  z )
+  {
+    register FT_UInt32  lo, hi;
+
+
+    lo = x->lo - y->lo;
+    hi = x->hi - y->hi - ( (FT_Int32)lo < 0 );
+
+    z->lo = lo;
+    z->hi = hi;
+  }
+
+
+  static int
+  ft_order64( FT_Int64*  z )
+  {
+    FT_UInt32  i;
+    int        j;
+
+
+    i = z->lo;
+    j = 0;
+    if ( z->hi )
+    {
+      i = z->hi;
+      j = 32;
+    }
+
+    while ( i > 0 )
+    {
+      i >>= 1;
+      j++;
+    }
+    return j - 1;
+  }
+
+
+  /* documentation is in ftcalc.h */
+
+  FT_EXPORT_DEF( FT_Int32 )
+  FT_Sqrt64( FT_Int64*  l )
+  {
+    FT_Int64  l2;
+    FT_Int32  r, s;
+
+
+    if ( (FT_Int32)l->hi < 0          ||
+         ( l->hi == 0 && l->lo == 0 ) )
+      return 0;
+
+    s = ft_order64( l );
+    if ( s == 0 )
+      return 1;
+
+    r = ft_square_roots[s];
+    do
+    {
+      s = r;
+      r = ( r + FT_Div64by32( l, r ) ) >> 1;
+      FT_MulTo64( r, r,   &l2 );
+      FT_Sub64  ( l, &l2, &l2 );
+
+    } while ( r > s || (FT_Int32)l2.hi < 0 );
+
+    return r;
+  }
+
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+#endif /* FT_LONG64 */
+
+
+  /* a not-so-fast but working 16.16 fixed point square root function */
+
+  FT_EXPORT_DEF( FT_Int32 )
+  FT_SqrtFixed( FT_Int32  x )
+  {
+    FT_UInt32  root, rem_hi, rem_lo, test_div;
+    FT_Int     count;
+
+
+    root = 0;
+
+    if ( x > 0 )
+    {
+      rem_hi = 0;
+      rem_lo = x;
+      count  = 24;
+      do
+      {
+        rem_hi   = ( rem_hi << 2 ) | ( rem_lo >> 30 );
+        rem_lo <<= 2;
+        root   <<= 1;
+        test_div = ( root << 1 ) + 1;
+
+        if ( rem_hi >= test_div )
+        {
+          rem_hi -= test_div;
+          root   += 1;
+        }
+      } while ( --count );
+    }
+
+    return (FT_Int32)root;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftcchunk.c b/libraries/freetype-2.0.5/ftcchunk.c
new file mode 100644 (file)
index 0000000..7e60393
--- /dev/null
@@ -0,0 +1,452 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcchunk.c                                                             */
+/*                                                                         */
+/*    FreeType chunk cache cache (body).                                   */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_INTERNAL_CHUNK_H
+#include FT_LIST_H
+#include FT_ERRORS_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "ftcerror.h"
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      GLYPH NODES                              *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* create a new chunk node, setting its cache index and ref count */
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ChunkNode_Init( FTC_ChunkNode  node,
+                      FTC_ChunkSet   cset,
+                      FT_UInt        index,
+                      FT_Bool        alloc )
+  {
+    FTC_Chunk_Cache      cache = cset->cache;
+    FTC_CacheNode_Data*  data  = FTC_CACHENODE_TO_DATA_P( &node->root );
+    FT_Error             error = 0;
+
+
+    data->cache_index  = (FT_UShort)cache->root.cache_index;
+    data->ref_count    = (FT_Short) 0;
+    node->cset         = cset;
+    node->cset_index   = (FT_UShort)index;
+    node->num_elements = (unsigned short)(
+                          ( index + 1 < cset->num_chunks )
+                            ? cset->element_count
+                            : cset->element_max - cset->element_count*index );
+    if ( alloc )
+    {
+      /* allocate elements array */
+      FT_Memory   memory;
+
+
+      memory = cache->root.memory;
+      error  = MEM_Alloc( node->elements,
+                          cset->element_size * cset->element_count );
+    }
+
+    return error;
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FTC_ChunkNode_Destroy( FTC_ChunkNode  node )
+  {
+    FTC_ChunkSet  cset = node->cset;
+
+
+    /* remove from parent set table */
+    cset->chunks[node->cset_index] = 0;
+
+    /* destroy the node */
+    cset->clazz->destroy_node( node );
+  }
+
+
+  FT_EXPORT_DEF( FT_ULong )
+  FTC_ChunkNode_Size( FTC_ChunkNode  node )
+  {
+    FTC_ChunkSet  cset = node->cset;
+
+
+    return cset->clazz->size_node( node );
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_CacheNode_Class  ftc_chunk_cache_node_class =
+  {
+    (FTC_CacheNode_SizeFunc)   FTC_ChunkNode_Size,
+    (FTC_CacheNode_DestroyFunc)FTC_ChunkNode_Destroy
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      CHUNK SETS                               *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ChunkSet_New( FTC_Chunk_Cache  cache,
+                    FT_Pointer       type,
+                    FTC_ChunkSet    *aset )
+  {
+    FT_Error      error;
+    FT_Memory     memory  = cache->root.memory;
+    FTC_Manager   manager = cache->root.manager;
+    FTC_ChunkSet  cset    = 0;
+
+    FTC_Chunk_Cache_Class*  ccache_class;
+    FTC_ChunkSet_Class*     clazz;
+
+
+    ccache_class = (FTC_Chunk_Cache_Class*)cache->root.clazz;
+    clazz        = ccache_class->cset_class;
+
+    *aset = 0;
+
+    if ( ALLOC( cset, clazz->cset_byte_size ) )
+      goto Exit;
+
+    cset->cache   = cache;
+    cset->manager = manager;
+    cset->memory  = memory;
+    cset->clazz   = clazz;
+
+    /* now compute element_max, element_count and element_size */
+    error = clazz->sizes( cset, type );
+    if ( error )
+      goto Exit;
+
+    /* compute maximum number of nodes */
+    cset->num_chunks = ( cset->element_max + cset->element_count - 1 ) /
+                       cset->element_count;
+
+    /* allocate chunk pointers table */
+    if ( ALLOC_ARRAY( cset->chunks, cset->num_chunks, FTC_ChunkNode ) )
+      goto Exit;
+
+    /* initialize set by type if needed */
+    if ( clazz->init )
+    {
+      error = clazz->init( cset, type );
+      if ( error )
+        goto Exit;
+    }
+
+    *aset = cset;
+
+  Exit:
+    if ( error && cset )
+    {
+      FREE( cset->chunks );
+      FREE( cset );
+    }
+
+    return error;
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FTC_ChunkSet_Destroy( FTC_ChunkSet  cset )
+  {
+    FTC_Chunk_Cache      cache        = cset->cache;
+    FTC_Manager          manager      = cache->root.manager;
+    FT_List              glyphs_lru   = &manager->global_lru;
+    FTC_ChunkNode*       bucket       = cset->chunks;
+    FTC_ChunkNode*       bucket_limit = bucket + cset->num_chunks;
+    FT_Memory            memory       = cache->root.memory;
+
+    FTC_ChunkSet_Class*  clazz        = cset->clazz;
+
+
+    /* for each bucket, free the list of glyph nodes */
+    for ( ; bucket < bucket_limit; bucket++ )
+    {
+      FTC_ChunkNode  node = bucket[0];
+      FT_ListNode    lrunode;
+
+
+      if ( node )
+      {
+        lrunode = FTC_CHUNKNODE_TO_LRUNODE( node );
+
+        manager->num_bytes -= clazz->size_node( node );
+        manager->num_nodes--;
+
+        FT_List_Remove( glyphs_lru, lrunode );
+
+        clazz->destroy_node( node );
+
+        bucket[0] = 0;
+      }
+    }
+
+    if ( clazz->done )
+      clazz->done( cset );
+
+    FREE( cset->chunks );
+    FREE( cset );
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ChunkSet_Lookup_Node( FTC_ChunkSet    cset,
+                            FT_UInt         glyph_index,
+                            FTC_ChunkNode  *anode,
+                            FT_UInt        *anindex )
+  {
+    FTC_Chunk_Cache      cache   = cset->cache;
+    FTC_Manager          manager = cache->root.manager;
+    FT_Error             error   = 0;
+
+    FTC_ChunkSet_Class*  clazz   = cset->clazz;
+
+
+    *anode = 0;
+
+    if ( glyph_index >= cset->element_max )
+      error = FTC_Err_Invalid_Argument;
+    else
+    {
+      FT_UInt         chunk_size  = cset->element_count;
+      FT_UInt         chunk_index = glyph_index / chunk_size;
+      FTC_ChunkNode*  pnode       = cset->chunks + chunk_index;
+      FTC_ChunkNode   node        = *pnode;
+
+
+      if ( !node )
+      {
+        /* we didn't found the glyph image; we will now create a new one */
+        error = clazz->new_node( cset, chunk_index, &node );
+        if ( error )
+          goto Exit;
+
+        /* store the new chunk in the cset's table */
+        *pnode = node;
+
+        /* insert the node at the start the global LRU glyph list */
+        FT_List_Insert( &manager->global_lru,
+                        FTC_CHUNKNODE_TO_LRUNODE( node ) );
+
+        manager->num_bytes += clazz->size_node( node );
+        manager->num_nodes++;
+
+        if ( manager->num_bytes > manager->max_bytes )
+        {
+          FTC_ChunkNode_Ref   ( node );
+          FTC_Manager_Compress( manager );
+          FTC_ChunkNode_Unref ( node );
+        }
+      }
+
+      *anode   = node;
+      *anindex = glyph_index - chunk_index * chunk_size;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   CHUNK SETS LRU CALLBACKS                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define FTC_CSET_LRU_GET_CACHE( lru )   \
+          ( (FTC_Chunk_Cache)((lru)->user_data) )
+
+#define FTC_CSET_LRU_GET_MANAGER( lru ) \
+          FTC_CSET_LRU_GET_CACHE( lru )->manager
+
+#define FTC_LRUNODE_CSET( node )        \
+          ( (FTC_ChunkSet)(node)->root.data )
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_chunk_set_lru_init( FT_Lru      lru,
+                          FT_LruNode  node )
+  {
+    FTC_Chunk_Cache  cache = FTC_CSET_LRU_GET_CACHE( lru );
+    FT_Error         error;
+    FTC_ChunkSet     cset;
+
+
+    error = FTC_ChunkSet_New( cache,
+                              (FT_Pointer)node->key,
+                              &cset );
+    if ( !error )
+    {
+      /* good, now set the set index within the set object */
+      cset->cset_index = (FT_UInt)( node - lru->nodes );
+      node->root.data  = cset;
+    }
+
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  ftc_chunk_set_lru_done( FT_Lru      lru,
+                          FT_LruNode  node )
+  {
+    FTC_ChunkSet  cset = FTC_LRUNODE_CSET( node );
+
+    FT_UNUSED( lru );
+
+
+    FTC_ChunkSet_Destroy( cset );
+  }
+
+
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_chunk_set_lru_compare( FT_LruNode  node,
+                             FT_LruKey   key )
+  {
+    FTC_ChunkSet  cset = FTC_LRUNODE_CSET( node );
+
+
+    return cset->clazz->compare( cset, (FT_Pointer)key );
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Lru_Class  ftc_chunk_set_lru_class =
+  {
+    sizeof( FT_LruRec ),
+    ftc_chunk_set_lru_init,
+    ftc_chunk_set_lru_done,
+    0,  /* no flush */
+    ftc_chunk_set_lru_compare
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   CHUNK CACHE OBJECTS                         *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Chunk_Cache_Init( FTC_Chunk_Cache  cache )
+  {
+    FT_Memory  memory = cache->root.memory;
+    FT_Error   error;
+
+    FTC_Chunk_Cache_Class*  ccache_clazz;
+
+
+    /* set up root node_class to be used by manager */
+    cache->root.node_clazz =
+      (FTC_CacheNode_Class*)&ftc_chunk_cache_node_class;
+
+    /* setup `compare' shortcut */
+    ccache_clazz   = (FTC_Chunk_Cache_Class*)cache->root.clazz;
+    cache->compare = ccache_clazz->cset_class->compare;
+
+    error = FT_Lru_New( &ftc_chunk_set_lru_class,
+                        FTC_MAX_CHUNK_SETS,
+                        cache,
+                        memory,
+                        1, /* pre_alloc == TRUE */
+                        &cache->csets_lru );
+    return error;
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FTC_Chunk_Cache_Done( FTC_Chunk_Cache  cache )
+  {
+    /* discard glyph sets */
+    FT_Lru_Done( cache->csets_lru );
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Chunk_Cache_Lookup( FTC_Chunk_Cache  cache,
+                          FT_Pointer       type,
+                          FT_UInt          gindex,
+                          FTC_ChunkNode   *anode,
+                          FT_UInt         *aindex )
+  {
+    FT_Error       error;
+    FTC_ChunkSet   cset;
+    FTC_ChunkNode  node;
+    FT_UInt        cindex;
+    FTC_Manager    manager;
+
+
+    /* check for valid `desc' delayed to FT_Lru_Lookup() */
+
+    if ( !cache || !anode || !aindex )
+      return FTC_Err_Invalid_Argument;
+
+    *anode  = 0;
+    *aindex = 0;
+    cset    = cache->last_cset;
+
+    if ( !cset || !cache->compare( cset, type ) )
+    {
+      error = FT_Lru_Lookup( cache->csets_lru,
+                             (FT_LruKey)type,
+                             (FT_Pointer*)&cset );
+      cache->last_cset = cset;
+      if ( error )
+        goto Exit;
+    }
+
+    error = FTC_ChunkSet_Lookup_Node( cset, gindex, &node, &cindex );
+    if ( error )
+      goto Exit;
+
+    /* now compress the manager's cache pool if needed */
+    manager = cache->root.manager;
+    if ( manager->num_bytes > manager->max_bytes )
+    {
+      FTC_ChunkNode_Ref   ( node );
+      FTC_Manager_Compress( manager );
+      FTC_ChunkNode_Unref ( node );
+    }
+
+    *anode  = node;
+    *aindex = cindex;
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftcglyph.c b/libraries/freetype-2.0.5/ftcglyph.c
new file mode 100644 (file)
index 0000000..c524b53
--- /dev/null
@@ -0,0 +1,481 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcglyph.c                                                             */
+/*                                                                         */
+/*    FreeType Glyph Image (FT_Glyph) cache (body).                        */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_INTERNAL_GLYPH_H
+#include FT_ERRORS_H
+#include FT_LIST_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "ftcerror.h"
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      GLYPH NODES                              *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* create a new glyph node, setting its cache index and ref count */
+  FT_EXPORT_DEF( void )
+  FTC_GlyphNode_Init( FTC_GlyphNode  node,
+                      FTC_GlyphSet   gset,
+                      FT_UInt        gindex )
+  {
+    FTC_Glyph_Cache      cache = gset->cache;
+    FTC_CacheNode_Data*  data  = FTC_CACHENODE_TO_DATA_P( &node->root );
+
+
+    data->cache_index = (FT_UShort)cache->root.cache_index;
+    data->ref_count   = (FT_Short) 0;
+    node->gset_index  = (FT_UShort)gset->gset_index;
+    node->glyph_index = (FT_UShort)gindex;
+  }
+
+
+  /* Important: This function is called from the cache manager to */
+  /* destroy a given cache node during `cache compression'.  The  */
+  /* second argument is always `cache.cache_data'.  Thus be       */
+  /* certain that the function FTC_Glyph_Cache_New() does indeed  */
+  /* set its `cache_data' field correctly, otherwise bad things   */
+  /* will happen!                                                 */
+
+  FT_EXPORT_DEF( void )
+  FTC_GlyphNode_Destroy( FTC_GlyphNode    node,
+                         FTC_Glyph_Cache  cache )
+  {
+    FT_LruNode    gset_lru = cache->gsets_lru->nodes + node->gset_index;
+    FTC_GlyphSet  gset     = (FTC_GlyphSet)gset_lru->root.data;
+    FT_UInt       hash     = node->glyph_index % gset->hash_size;
+
+
+    /* remove the node from its gset's bucket list */
+    {
+      FTC_GlyphNode*  pnode = gset->buckets + hash;
+      FTC_GlyphNode   cur;
+
+
+      for (;;)
+      {
+        cur = *pnode;
+        if ( !cur )
+        {
+          /* this should never happen */
+          FT_ERROR(( "FTC_GlyphNode_Destroy:"
+                     " trying to delete an unlisted node!" ));
+          return;
+        }
+
+        if ( cur == node )
+        {
+          *pnode = cur->gset_next;
+          break;
+        }
+        pnode = &cur->gset_next;
+      }
+    }
+
+    /* destroy the node */
+    gset->clazz->destroy_node( node, gset );
+  }
+
+
+  /* Important: This function is called from the cache manager to */
+  /* size a given cache node during `cache compression'.  The     */
+  /* second argument is always `cache.user_data'.  Thus be        */
+  /* certain that the function FTC_Glyph_Cache_New() does indeed  */
+  /* set its `user_data' field correctly, otherwise bad things    */
+  /* will happen!                                                 */
+
+  FT_EXPORT_DEF( FT_ULong )
+  FTC_GlyphNode_Size( FTC_GlyphNode    node,
+                      FTC_Glyph_Cache  cache )
+  {
+    FT_LruNode    gset_lru = cache->gsets_lru->nodes + node->gset_index;
+    FTC_GlyphSet  gset     = (FTC_GlyphSet)gset_lru->root.data;
+
+
+    return gset->clazz->size_node( node, gset );
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_CacheNode_Class  ftc_glyph_cache_node_class =
+  {
+    (FTC_CacheNode_SizeFunc)   FTC_GlyphNode_Size,
+    (FTC_CacheNode_DestroyFunc)FTC_GlyphNode_Destroy
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      GLYPH SETS                               *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_GlyphSet_New( FTC_Glyph_Cache  cache,
+                    FT_Pointer       type,
+                    FTC_GlyphSet    *aset )
+  {
+    FT_Error                error;
+    FT_Memory               memory  = cache->root.memory;
+    FTC_Manager             manager = cache->root.manager;
+    FTC_GlyphSet            gset    = 0;
+
+    FTC_Glyph_Cache_Class*  gcache_class;
+    FTC_GlyphSet_Class*     clazz;
+
+
+    gcache_class = (FTC_Glyph_Cache_Class*)cache->root.clazz;
+    clazz        = gcache_class->gset_class;
+
+    *aset = 0;
+
+    if ( ALLOC( gset, clazz->gset_byte_size ) )
+      goto Exit;
+
+    gset->cache     = cache;
+    gset->manager   = manager;
+    gset->memory    = memory;
+    gset->hash_size = FTC_GSET_HASH_SIZE_DEFAULT;
+    gset->clazz     = clazz;
+
+    /* allocate buckets table */
+    if ( ALLOC_ARRAY( gset->buckets, gset->hash_size, FTC_GlyphNode ) )
+      goto Exit;
+
+    /* initialize gset by type if needed */
+    if ( clazz->init )
+    {
+      error = clazz->init( gset, type );
+      if ( error )
+        goto Exit;
+    }
+
+    *aset = gset;
+
+  Exit:
+    if ( error && gset )
+    {
+      FREE( gset->buckets );
+      FREE( gset );
+    }
+
+    return error;
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FTC_GlyphSet_Destroy( FTC_GlyphSet  gset )
+  {
+    FTC_Glyph_Cache      cache        = gset->cache;
+    FTC_Manager          manager      = cache->root.manager;
+    FT_List              glyphs_lru   = &manager->global_lru;
+    FTC_GlyphNode*       bucket       = gset->buckets;
+    FTC_GlyphNode*       bucket_limit = bucket + gset->hash_size;
+    FT_Memory            memory       = cache->root.memory;
+
+    FTC_GlyphSet_Class*  clazz        = gset->clazz;
+
+
+    /* for each bucket, free the list of glyph nodes */
+    for ( ; bucket < bucket_limit; bucket++ )
+    {
+      FTC_GlyphNode   node = bucket[0];
+      FTC_GlyphNode   next = 0;
+      FT_ListNode     lrunode;
+
+
+      for ( ; node; node = next )
+      {
+        next    = node->gset_next;
+        lrunode = FTC_GLYPHNODE_TO_LRUNODE( node );
+
+        manager->num_bytes -= clazz->size_node( node, gset );
+        manager->num_nodes--;
+
+        FT_List_Remove( glyphs_lru, lrunode );
+
+        clazz->destroy_node( node, gset );
+      }
+
+      bucket[0] = 0;
+    }
+
+    if ( clazz->done )
+      clazz->done( gset );
+
+    FREE( gset->buckets );
+    FREE( gset );
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_GlyphSet_Lookup_Node( FTC_GlyphSet    gset,
+                            FT_UInt         glyph_index,
+                            FTC_GlyphNode  *anode )
+  {
+    FTC_Glyph_Cache      cache      = gset->cache;
+    FTC_Manager          manager    = cache->root.manager;
+    FT_UInt              hash_index = glyph_index % gset->hash_size;
+    FTC_GlyphNode*       bucket     = gset->buckets + hash_index;
+    FTC_GlyphNode*       pnode      = bucket;
+    FTC_GlyphNode        node;
+    FT_Error             error;
+
+    FTC_GlyphSet_Class*  clazz      = gset->clazz;
+
+
+    *anode = 0;
+
+    for ( ;; )
+    {
+      node = *pnode;
+      if ( !node )
+        break;
+
+      if ( (FT_UInt)node->glyph_index == glyph_index )
+      {
+        /* we found it! -- move glyph to start of the lists */
+        *pnode          = node->gset_next;
+        node->gset_next = bucket[0];
+        bucket[0]       = node;
+
+        FT_List_Up( &manager->global_lru, FTC_GLYPHNODE_TO_LRUNODE( node ) );
+        *anode = node;
+        return 0;
+      }
+      /* go to next node in bucket */
+      pnode = &node->gset_next;
+    }
+
+    /* we didn't found the glyph image, we will now create a new one */
+    error = clazz->new_node( gset, glyph_index, &node );
+    if ( error )
+      goto Exit;
+
+    /* insert the node at the start of our bucket list */
+    node->gset_next = bucket[0];
+    bucket[0]       = node;
+
+    /* insert the node at the start the global LRU glyph list */
+    FT_List_Insert( &manager->global_lru, FTC_GLYPHNODE_TO_LRUNODE( node ) );
+
+    manager->num_bytes += clazz->size_node( node, gset );
+    manager->num_nodes++;
+
+    if ( manager->num_bytes > manager->max_bytes )
+    {
+      FTC_GlyphNode_Ref   ( node );
+      FTC_Manager_Compress( manager );
+      FTC_GlyphNode_Unref ( node );
+    }
+
+    *anode = node;
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   GLYPH SETS LRU CALLBACKS                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define FTC_GSET_LRU_GET_CACHE( lru )   \
+          ( (FTC_Glyph_Cache)(lru)->user_data )
+
+#define FTC_GSET_LRU_GET_MANAGER( lru ) \
+          FTC_GSET_LRU_GET_CACHE( lru )->manager
+
+#define FTC_LRUNODE_GSET( node )        \
+          ( (FTC_GlyphSet)(node)->root.data )
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_glyph_set_lru_init( FT_Lru      lru,
+                          FT_LruNode  node )
+  {
+    FTC_Glyph_Cache  cache = FTC_GSET_LRU_GET_CACHE( lru );
+    FT_Error         error;
+    FTC_GlyphSet     gset;
+
+
+    error = FTC_GlyphSet_New( cache, (FT_Pointer)node->key, &gset );
+    if ( !error )
+    {
+      /* good, now set the gset index within the gset object */
+      gset->gset_index = (FT_UInt)( node - lru->nodes );
+      node->root.data  = gset;
+    }
+
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  ftc_glyph_set_lru_done( FT_Lru      lru,
+                          FT_LruNode  node )
+  {
+    FTC_GlyphSet  gset = FTC_LRUNODE_GSET( node );
+
+    FT_UNUSED( lru );
+
+
+    FTC_GlyphSet_Destroy( gset );
+  }
+
+
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_glyph_set_lru_compare( FT_LruNode  node,
+                             FT_LruKey   key )
+  {
+    FTC_GlyphSet  gset = FTC_LRUNODE_GSET( node );
+
+
+    return gset->clazz->compare( gset, (FT_Pointer)key );
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Lru_Class  ftc_glyph_set_lru_class =
+  {
+    sizeof( FT_LruRec ),
+    ftc_glyph_set_lru_init,
+    ftc_glyph_set_lru_done,
+    0,  /* no flush */
+    ftc_glyph_set_lru_compare
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      GLYPH CACHE OBJECTS                      *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Glyph_Cache_Init( FTC_Glyph_Cache  cache )
+  {
+    FT_Memory  memory = cache->root.memory;
+    FT_Error   error;
+
+    FTC_Glyph_Cache_Class*  gcache_clazz;
+
+
+    /* set up root node_class to be used by manager */
+    cache->root.node_clazz =
+      (FTC_CacheNode_Class*)&ftc_glyph_cache_node_class;
+
+    /* setup the `compare' shortcut */
+    gcache_clazz   = (FTC_Glyph_Cache_Class*)cache->root.clazz;
+    cache->compare = gcache_clazz->gset_class->compare;
+
+    /* The following is extremely important for ftc_destroy_glyph_image() */
+    /* to work properly, as the second parameter that is sent to it       */
+    /* through the cache manager is `cache_data' and must be set to       */
+    /* `cache' here.                                                      */
+    /*                                                                    */
+    cache->root.cache_data = cache;
+
+    error = FT_Lru_New( &ftc_glyph_set_lru_class,
+                        FTC_MAX_GLYPH_SETS,
+                        cache,
+                        memory,
+                        1, /* pre_alloc == TRUE */
+                        &cache->gsets_lru );
+    return error;
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FTC_Glyph_Cache_Done( FTC_Glyph_Cache  cache )
+  {
+    /* discard glyph sets */
+    FT_Lru_Done( cache->gsets_lru );
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Glyph_Cache_Lookup( FTC_Glyph_Cache  cache,
+                          FT_Pointer       type,
+                          FT_UInt          gindex,
+                          FTC_GlyphNode   *anode )
+  {
+    FT_Error       error;
+    FTC_GlyphSet   gset;
+    FTC_GlyphNode  node;
+    FTC_Manager    manager;
+
+
+    /* check for valid `desc' delayed to FT_Lru_Lookup() */
+
+    if ( !cache || !anode )
+      return FTC_Err_Invalid_Argument;
+
+    *anode = 0;
+    gset   = cache->last_gset;
+
+    if ( !gset || !cache->compare( gset, type ) )
+    {
+      error = FT_Lru_Lookup( cache->gsets_lru,
+                             (FT_LruKey)type,
+                             (FT_Pointer*)&gset );
+      cache->last_gset = gset;
+      if ( error )
+        goto Exit;
+    }
+
+    error = FTC_GlyphSet_Lookup_Node( gset, gindex, &node );
+    if ( error )
+      goto Exit;
+
+    /* now compress the manager's cache pool if needed */
+    manager = cache->root.manager;
+    if ( manager->num_bytes > manager->max_bytes )
+    {
+      FTC_GlyphNode_Ref   ( node );
+      FTC_Manager_Compress( manager );
+      FTC_GlyphNode_Unref ( node );
+    }
+
+    *anode = node;
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftcimage.c b/libraries/freetype-2.0.5/ftcimage.c
new file mode 100644 (file)
index 0000000..2c93a23
--- /dev/null
@@ -0,0 +1,308 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcimage.c                                                             */
+/*                                                                         */
+/*    FreeType Image cache (body).                                         */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_IMAGE_H
+#include FT_INTERNAL_MEMORY_H
+
+#include "ftcerror.h"
+
+#include <string.h>     /* memcmp() */
+#include <stdlib.h>     /* labs()   */
+
+
+  /* the FT_Glyph image `glyph node' type */
+  typedef struct  FTC_GlyphImageRec_
+  {
+    FTC_GlyphNodeRec  root;
+    FT_Glyph          ft_glyph;
+
+  } FTC_GlyphImageRec, *FTC_GlyphImage;
+
+
+  /* the glyph image queue type */
+  typedef struct  FTC_ImageSetRec_
+  {
+    FTC_GlyphSetRec  root;
+    FTC_Image_Desc   description;
+
+  } FTC_ImageSetRec, *FTC_ImageSet;
+
+
+  typedef struct  FTC_Image_CacheRec_
+  {
+    FTC_Glyph_CacheRec  root;
+
+  } FTC_Image_CacheRec;
+
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    GLYPH IMAGE NODES                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_DEF( void )
+  ftc_glyph_image_node_destroy( FTC_GlyphImage  node,
+                                FTC_GlyphSet    gset )
+  {
+    FT_Memory  memory = gset->memory;
+
+
+    FT_Done_Glyph( node->ft_glyph );
+    FREE( node );
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_glyph_image_node_new( FTC_GlyphSet     gset,
+                            FT_UInt          glyph_index,
+                            FTC_GlyphImage  *anode )
+  {
+    FT_Memory       memory   = gset->memory;
+    FTC_ImageSet    imageset = (FTC_ImageSet)gset;
+    FT_Error        error;
+    FTC_GlyphImage  node = 0;
+    FT_Face         face;
+    FT_Size         size;
+
+
+    /* allocate node */
+    if ( ALLOC( node, sizeof ( *node ) ) )
+      goto Exit;
+
+    /* initialize its inner fields */
+    FTC_GlyphNode_Init( FTC_GLYPHNODE( node ), gset, glyph_index );
+
+    /* we will now load the glyph image */
+    error = FTC_Manager_Lookup_Size( gset->manager,
+                                     &imageset->description.font,
+                                     &face, &size );
+    if ( !error )
+    {
+      FT_UInt  gindex = node->root.glyph_index;
+      FT_UInt  load_flags  = FT_LOAD_DEFAULT;
+      FT_UInt  image_type  = imageset->description.image_type;
+
+
+      if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap )
+      {
+        load_flags |= FT_LOAD_RENDER;
+        if ( image_type & ftc_image_flag_monochrome )
+          load_flags |= FT_LOAD_MONOCHROME;
+
+        /* disable embedded bitmaps loading if necessary */
+        if ( image_type & ftc_image_flag_no_sbits )
+          load_flags |= FT_LOAD_NO_BITMAP;
+      }
+      else if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_outline )
+      {
+        /* disable embedded bitmaps loading */
+        load_flags |= FT_LOAD_NO_BITMAP;
+
+        if ( image_type & ftc_image_flag_unscaled )
+          load_flags |= FT_LOAD_NO_SCALE;
+      }
+
+      if ( image_type & ftc_image_flag_unhinted )
+        load_flags |= FT_LOAD_NO_HINTING;
+
+      if ( image_type & ftc_image_flag_autohinted )
+        load_flags |= FT_LOAD_FORCE_AUTOHINT;
+
+      error = FT_Load_Glyph( face, gindex, load_flags );
+      if ( !error )
+      {
+        if ( face->glyph->format == ft_glyph_format_bitmap  ||
+             face->glyph->format == ft_glyph_format_outline )
+        {
+          /* ok, copy it */
+          FT_Glyph  glyph;
+
+
+          error = FT_Get_Glyph( face->glyph, &glyph );
+          if ( !error )
+            node->ft_glyph = glyph;
+        }
+        else
+          error = FTC_Err_Invalid_Argument;
+      }
+    }
+
+  Exit:
+    if ( error && node )
+      FREE( node );
+
+    *anode = node;
+    return error;
+  }
+
+
+  /* this function is important because it is both part of */
+  /* an FTC_GlyphSet_Class and an FTC_CacheNode_Class      */
+  /*                                                       */
+  FT_CALLBACK_DEF( FT_ULong )
+  ftc_glyph_image_node_size( FTC_GlyphImage  node )
+  {
+    FT_ULong  size  = 0;
+    FT_Glyph  glyph = node->ft_glyph;
+
+
+    switch ( glyph->format )
+    {
+    case ft_glyph_format_bitmap:
+      {
+        FT_BitmapGlyph  bitg;
+
+
+        bitg = (FT_BitmapGlyph)glyph;
+        size = bitg->bitmap.rows * labs( bitg->bitmap.pitch ) +
+               sizeof ( *bitg );
+      }
+      break;
+
+    case ft_glyph_format_outline:
+      {
+        FT_OutlineGlyph  outg;
+
+
+        outg = (FT_OutlineGlyph)glyph;
+        size = outg->outline.n_points *
+                 ( sizeof( FT_Vector ) + sizeof ( FT_Byte ) ) +
+               outg->outline.n_contours * sizeof ( FT_Short ) +
+               sizeof ( *outg );
+      }
+      break;
+
+    default:
+      ;
+    }
+
+    size += sizeof ( *node );
+    return size;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    GLYPH IMAGE SETS                           *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_image_set_init( FTC_ImageSet     iset,
+                      FTC_Image_Desc*  type )
+  {
+    iset->description = *type;
+    return 0;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_image_set_compare( FTC_ImageSet     iset,
+                         FTC_Image_Desc*  type )
+  {
+    return FT_BOOL( !memcmp( &iset->description, type, sizeof ( *type ) ) );
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_GlyphSet_Class  ftc_glyph_image_set_class =
+  {
+    sizeof( FTC_ImageSetRec ),
+
+    (FTC_GlyphSet_InitFunc)       ftc_image_set_init,
+    (FTC_GlyphSet_DoneFunc)       0,
+    (FTC_GlyphSet_CompareFunc)    ftc_image_set_compare,
+
+    (FTC_GlyphSet_NewNodeFunc)    ftc_glyph_image_node_new,
+    (FTC_GlyphSet_SizeNodeFunc)   ftc_glyph_image_node_size,
+    (FTC_GlyphSet_DestroyNodeFunc)ftc_glyph_image_node_destroy
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    GLYPH IMAGE CACHE                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_Glyph_Cache_Class  ftc_glyph_image_cache_class =
+  {
+    {
+      sizeof( FTC_Image_CacheRec ),
+      (FTC_Cache_InitFunc) FTC_Glyph_Cache_Init,
+      (FTC_Cache_DoneFunc) FTC_Glyph_Cache_Done
+    },
+    (FTC_GlyphSet_Class*) &ftc_glyph_image_set_class
+  };
+
+
+  /* documentation is in ftcimage.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Image_Cache_New( FTC_Manager       manager,
+                       FTC_Image_Cache  *acache )
+  {
+    return FTC_Manager_Register_Cache(
+             manager,
+             (FTC_Cache_Class*)&ftc_glyph_image_cache_class,
+             (FTC_Cache*)acache );
+  }
+
+
+  /* documentation is in ftcimage.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Image_Cache_Lookup( FTC_Image_Cache  cache,
+                          FTC_Image_Desc*  desc,
+                          FT_UInt          gindex,
+                          FT_Glyph        *aglyph )
+  {
+    FT_Error       error;
+    FTC_GlyphNode  node;
+
+
+    /* some argument checks are delayed to FTC_Glyph_Cache_Lookup */
+
+    if ( !aglyph )
+      return FTC_Err_Invalid_Argument;
+
+    error = FTC_Glyph_Cache_Lookup( (FTC_Glyph_Cache)cache,
+                                    desc, gindex, &node );
+
+    if ( !error )
+      *aglyph = ((FTC_GlyphImage)node)->ft_glyph;
+
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftcmanag.c b/libraries/freetype-2.0.5/ftcmanag.c
new file mode 100644 (file)
index 0000000..7076305
--- /dev/null
@@ -0,0 +1,516 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcmanag.c                                                             */
+/*                                                                         */
+/*    FreeType Cache Manager (body).                                       */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_MANAGER_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_LIST_H
+#include FT_SIZES_H
+
+#include "ftcerror.h"
+
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cache
+
+#define FTC_LRU_GET_MANAGER( lru )  (FTC_Manager)lru->user_data
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****               FACE & SIZE LRU CALLBACKS                       *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_manager_init_face( FT_Lru      lru,
+                         FT_LruNode  node )
+  {
+    FTC_Manager  manager = FTC_LRU_GET_MANAGER( lru );
+    FT_Error     error;
+    FT_Face      face;
+
+
+    error = manager->request_face( (FTC_FaceID)node->key,
+                                   manager->library,
+                                   manager->request_data,
+                                   (FT_Face*)&node->root.data );
+    if ( !error )
+    {
+      /* destroy initial size object; it will be re-created later */
+      face = (FT_Face)node->root.data;
+      if ( face->size )
+        FT_Done_Size( face->size );
+    }
+
+    return error;
+  }
+
+
+  /* helper function for ftc_manager_done_face() */
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_manager_size_selector( FT_Lru      lru,
+                             FT_LruNode  node,
+                             FT_Pointer  data )
+  {
+    FT_UNUSED( lru );
+
+    return FT_BOOL( ((FT_Size)node->root.data)->face == (FT_Face)data );
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  ftc_manager_done_face( FT_Lru      lru,
+                         FT_LruNode  node )
+  {
+    FTC_Manager  manager = FTC_LRU_GET_MANAGER( lru );
+    FT_Face      face    = (FT_Face)node->root.data;
+
+
+    /* we must begin by removing all sizes for the target face */
+    /* from the manager's list                                 */
+    FT_Lru_Remove_Selection( manager->sizes_lru,
+                             ftc_manager_size_selector,
+                             face );
+
+    /* all right, we can discard the face now */
+    FT_Done_Face( face );
+    node->root.data = 0;
+  }
+
+
+  typedef struct  FTC_FontRequest_
+  {
+    FT_Face    face;
+    FT_UShort  width;
+    FT_UShort  height;
+
+  } FTC_FontRequest;
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_manager_init_size( FT_Lru      lru,
+                         FT_LruNode  node )
+  {
+    FTC_FontRequest*  font_req = (FTC_FontRequest*)node->key;
+    FT_Size           size;
+    FT_Error          error;
+    FT_Face           face = font_req->face;
+
+    FT_UNUSED( lru );
+
+
+    node->root.data = 0;
+    error = FT_New_Size( face, &size );
+    if ( !error )
+    {
+      FT_Activate_Size( size );
+      error = FT_Set_Pixel_Sizes( face,
+                                  font_req->width,
+                                  font_req->height );
+      if ( error )
+        FT_Done_Size( size );
+      else
+        node->root.data = size;
+    }
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  ftc_manager_done_size( FT_Lru      lru,
+                         FT_LruNode  node )
+  {
+    FT_UNUSED( lru );
+
+    FT_Done_Size( (FT_Size)node->root.data );
+    node->root.data = 0;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_manager_flush_size( FT_Lru      lru,
+                          FT_LruNode  node,
+                          FT_LruKey   key )
+  {
+    FTC_FontRequest*  req  = (FTC_FontRequest*)key;
+    FT_Size           size = (FT_Size)node->root.data;
+    FT_Error          error;
+
+
+    if ( size->face == req->face )
+    {
+      FT_Activate_Size( size );
+      error = FT_Set_Pixel_Sizes( req->face, req->width, req->height );
+      if ( error )
+        FT_Done_Size( size );
+    }
+    else
+    {
+      FT_Done_Size( size );
+      node->key = key;
+      error = ftc_manager_init_size( lru, node );
+    }
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_manager_compare_size( FT_LruNode  node,
+                            FT_LruKey   key )
+  {
+    FTC_FontRequest*  req  = (FTC_FontRequest*)key;
+    FT_Size           size = (FT_Size)node->root.data;
+
+    FT_UNUSED( node );
+
+
+    return FT_BOOL( size->face           == req->face   &&
+                    size->metrics.x_ppem == req->width  &&
+                    size->metrics.y_ppem == req->height );
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Lru_Class  ftc_face_lru_class =
+  {
+    sizeof ( FT_LruRec ),
+    ftc_manager_init_face,
+    ftc_manager_done_face,
+    0,
+    0
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Lru_Class  ftc_size_lru_class =
+  {
+    sizeof ( FT_LruRec ),
+    ftc_manager_init_size,
+    ftc_manager_done_size,
+    ftc_manager_flush_size,
+    ftc_manager_compare_size
+  };
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Manager_New( FT_Library          library,
+                   FT_UInt             max_faces,
+                   FT_UInt             max_sizes,
+                   FT_ULong            max_bytes,
+                   FTC_Face_Requester  requester,
+                   FT_Pointer          req_data,
+                   FTC_Manager        *amanager )
+  {
+    FT_Error     error;
+    FT_Memory    memory;
+    FTC_Manager  manager = 0;
+
+
+    if ( !library )
+      return FTC_Err_Invalid_Library_Handle;
+
+    memory = library->memory;
+
+    if ( ALLOC( manager, sizeof ( *manager ) ) )
+      goto Exit;
+
+    if ( max_faces == 0 )
+      max_faces = FTC_MAX_FACES_DEFAULT;
+
+    if ( max_sizes == 0 )
+      max_sizes = FTC_MAX_SIZES_DEFAULT;
+
+    if ( max_bytes == 0 )
+      max_bytes = FTC_MAX_BYTES_DEFAULT;
+
+    error = FT_Lru_New( &ftc_face_lru_class,
+                        max_faces,
+                        manager,
+                        memory,
+                        1, /* pre_alloc = TRUE */
+                        (FT_Lru*)&manager->faces_lru );
+    if ( error )
+      goto Exit;
+
+    error = FT_Lru_New( &ftc_size_lru_class,
+                        max_sizes,
+                        manager,
+                        memory,
+                        1, /* pre_alloc = TRUE */
+                        (FT_Lru*)&manager->sizes_lru );
+    if ( error )
+      goto Exit;
+
+    manager->library      = library;
+    manager->max_bytes    = max_bytes;
+    manager->request_face = requester;
+    manager->request_data = req_data;
+
+    *amanager = manager;
+
+  Exit:
+    if ( error && manager )
+    {
+      FT_Lru_Done( manager->faces_lru );
+      FT_Lru_Done( manager->sizes_lru );
+      FREE( manager );
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( void )
+  FTC_Manager_Done( FTC_Manager  manager )
+  {
+    FT_Memory  memory;
+    FT_UInt    index;
+
+
+    if ( !manager || !manager->library )
+      return;
+
+    memory = manager->library->memory;
+
+    /* now discard all caches */
+    for (index = 0; index < FTC_MAX_CACHES; index++ )
+    {
+      FTC_Cache  cache = manager->caches[index];
+
+
+      if ( cache )
+      {
+        cache->clazz->done_cache( cache );
+        FREE( cache );
+        manager->caches[index] = 0;
+      }
+    }
+
+    /* discard faces and sizes */
+    FT_Lru_Done( manager->faces_lru );
+    manager->faces_lru = 0;
+
+    FT_Lru_Done( manager->sizes_lru );
+    manager->sizes_lru = 0;
+
+    FREE( manager );
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( void )
+  FTC_Manager_Reset( FTC_Manager  manager )
+  {
+    if (manager )
+    {
+      FT_Lru_Reset( manager->sizes_lru );
+      FT_Lru_Reset( manager->faces_lru );
+    }
+    /* XXX: FIXME: flush the caches? */
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Manager_Lookup_Face( FTC_Manager  manager,
+                           FTC_FaceID   face_id,
+                           FT_Face     *aface )
+  {
+    if ( !manager )
+      return FTC_Err_Invalid_Cache_Handle;
+
+    return  FT_Lru_Lookup( manager->faces_lru,
+                           (FT_LruKey)face_id,
+                           (FT_Pointer*)aface );
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Manager_Lookup_Size( FTC_Manager  manager,
+                           FTC_Font     font,
+                           FT_Face     *aface,
+                           FT_Size     *asize )
+  {
+    FTC_FontRequest  req;
+    FT_Error         error;
+
+
+    /* check for valid `manager' delayed to FTC_Manager_Lookup_Face() */
+
+    if ( aface )
+      *aface = 0;
+
+    if ( asize )
+      *asize = 0;
+
+    error = FTC_Manager_Lookup_Face( manager, font->face_id, aface );
+    if ( !error )
+    {
+      FT_Size  size;
+
+
+      req.face   = *aface;
+      req.width  = font->pix_width;
+      req.height = font->pix_height;
+
+      error = FT_Lru_Lookup( manager->sizes_lru,
+                             (FT_LruKey)&req,
+                             (FT_Pointer*)&size );
+      if ( !error )
+      {
+        /* select the size as the current one for this face */
+        (*aface)->size = size;
+
+        if ( asize )
+          *asize = size;
+      }
+    }
+
+    return error;
+  }
+
+
+  /* `Compress' the manager's data, i.e., get rid of old cache nodes */
+  /* that are not referenced anymore in order to limit the total     */
+  /* memory used by the cache.                                       */
+
+  /* documentation is in ftcmanag.h */
+
+  FT_EXPORT_DEF( void )
+  FTC_Manager_Compress( FTC_Manager  manager )
+  {
+    FT_ListNode  node;
+
+
+    node = manager->global_lru.tail;
+    while ( manager->num_bytes > manager->max_bytes && node )
+    {
+      FTC_CacheNode        cache_node = FTC_LIST_TO_CACHENODE( node );
+      FTC_CacheNode_Data*  data       = FTC_CACHENODE_TO_DATA_P( cache_node );
+      FTC_Cache            cache;
+      FT_ListNode          prev       = node->prev;
+
+
+      if ( data->ref_count <= 0 )
+      {
+        /* ok, we are going to remove this node */
+        FT_List_Remove( &manager->global_lru, node );
+
+        /* finalize cache node */
+        cache = manager->caches[data->cache_index];
+        if ( cache )
+        {
+          FTC_CacheNode_Class*  clazz = cache->node_clazz;
+
+
+          manager->num_bytes -= clazz->size_node( cache_node,
+                                                  cache->cache_data );
+
+          clazz->destroy_node( cache_node, cache->cache_data );
+        }
+        else
+        {
+          /* this should never happen! */
+          FT_ERROR(( "FTC_Manager_Compress: Cache Manager is corrupted!\n" ));
+        }
+
+        /* check, just in case of general corruption :-) */
+        if ( manager->num_nodes <= 0 )
+          FT_ERROR(( "FTC_Manager_Compress: Invalid cache node count!\n" ));
+        else
+          manager->num_nodes--;
+      }
+      node = prev;
+    }
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_Manager_Register_Cache( FTC_Manager       manager,
+                              FTC_Cache_Class*  clazz,
+                              FTC_Cache        *acache )
+  {
+    FT_Error  error = FTC_Err_Invalid_Argument;
+
+
+    if ( manager && clazz && acache )
+    {
+      FT_Memory  memory = manager->library->memory;
+      FTC_Cache  cache;
+      FT_UInt    index = 0;
+
+
+      /* by default, return 0 */
+      *acache = 0;
+
+      /* check for an empty cache slot in the manager's table */
+      for ( index = 0; index < FTC_MAX_CACHES; index++ )
+      {
+        if ( manager->caches[index] == 0 )
+          break;
+      }
+
+      /* return an error if there are too many registered caches */
+      if ( index >= FTC_MAX_CACHES )
+      {
+        error = FTC_Err_Too_Many_Caches;
+        FT_ERROR(( "FTC_Manager_Register_Cache:" ));
+        FT_ERROR(( " too many registered caches\n" ));
+        goto Exit;
+      }
+
+      if ( !ALLOC( cache, clazz->cache_byte_size ) )
+      {
+        cache->manager = manager;
+        cache->memory  = memory;
+        cache->clazz   = clazz;
+
+        /* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */
+        /* IF IT IS NOT SET CORRECTLY                         */
+        cache->cache_index = index;
+
+        if ( clazz->init_cache )
+          error = clazz->init_cache( cache );
+
+        if ( error )
+          FREE( cache );
+        else
+          manager->caches[index] = *acache = cache;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftcsbits.c b/libraries/freetype-2.0.5/ftcsbits.c
new file mode 100644 (file)
index 0000000..4b7d25d
--- /dev/null
@@ -0,0 +1,401 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcsbits.c                                                             */
+/*                                                                         */
+/*    FreeType sbits manager (body).                                       */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_SMALL_BITMAPS_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_ERRORS_H
+
+#include "ftcerror.h"
+
+#include <string.h>         /* memcmp() */
+
+
+#define FTC_SBITSET_ELEMENT_COUNT  16
+
+
+  typedef struct  FTC_SBitSetRec_
+  {
+    FTC_ChunkSetRec  root;
+    FTC_Image_Desc   desc;
+
+  } FTC_SBitSetRec, *FTC_SBitSet;
+
+
+  typedef struct  FTC_SBit_CacheRec_
+  {
+    FTC_Chunk_CacheRec  root;
+
+  } FTC_SBit_CacheRec;
+
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                     SBIT CACHE NODES                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_DEF( void )
+  ftc_sbit_chunk_node_destroy( FTC_ChunkNode  node )
+  {
+    FTC_ChunkSet  cset   = node->cset;
+    FT_Memory     memory = cset->memory;
+    FT_UInt       count  = node->num_elements;
+    FTC_SBit      sbit   = (FTC_SBit)node->elements;
+
+
+    for ( ; count > 0; sbit++, count-- )
+      FREE( sbit->buffer );
+
+    FREE( node->elements );
+    FREE( node );
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_bitmap_copy( FT_Memory   memory,
+                   FT_Bitmap*  source,
+                   FTC_SBit    target )
+  {
+    FT_Error  error;
+    FT_Int    pitch = source->pitch;
+    FT_ULong  size;
+
+
+    if ( pitch < 0 )
+      pitch = -pitch;
+
+    size = (FT_ULong)( pitch * source->rows );
+
+    if ( !ALLOC( target->buffer, size ) )
+      MEM_Copy( target->buffer, source->buffer, size );
+
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_sbit_chunk_node_new( FTC_ChunkSet    cset,
+                           FT_UInt         index,
+                           FTC_ChunkNode  *anode )
+  {
+    FT_Error       error;
+    FT_Memory      memory  = cset->memory;
+    FTC_SBitSet    sbitset = (FTC_SBitSet)cset;
+    FTC_ChunkNode  node    = 0;
+    FT_Face        face;
+    FT_Size        size;
+
+
+    /* allocate node */
+    if ( ALLOC( node, sizeof ( *node ) ) )
+      goto Exit;
+
+    /* initialize its inner fields */
+    error = FTC_ChunkNode_Init( node, cset, index, 1 );
+    if ( error )
+      goto Exit;
+
+    /* we will now load all glyph images for this chunk */
+    error = FTC_Manager_Lookup_Size( cset->manager,
+                                     &sbitset->desc.font,
+                                     &face, &size );
+    if ( !error )
+    {
+      FT_UInt   glyph_index = index * cset->element_count;
+      FT_UInt   load_flags  = FT_LOAD_DEFAULT;
+      FT_UInt   image_type  = sbitset->desc.image_type;
+      FT_UInt   count       = node->num_elements;
+      FTC_SBit  sbit        = (FTC_SBit)node->elements;
+
+
+      /* determine load flags, depending on the font description's */
+      /* image type                                                */
+
+      if ( FTC_IMAGE_FORMAT( image_type ) == ftc_image_format_bitmap )
+      {
+        if ( image_type & ftc_image_flag_monochrome )
+          load_flags |= FT_LOAD_MONOCHROME;
+
+        /* disable embedded bitmaps loading if necessary */
+        if ( image_type & ftc_image_flag_no_sbits )
+          load_flags |= FT_LOAD_NO_BITMAP;
+      }
+      else
+      {
+        FT_ERROR(( "FTC_SBit_Cache: cannot load scalable glyphs in an"
+                   " sbit cache, please check your arguments!\n" ));
+        error = FTC_Err_Invalid_Argument;
+        goto Exit;
+      }
+
+      /* always render glyphs to bitmaps */
+      load_flags |= FT_LOAD_RENDER;
+
+      if ( image_type & ftc_image_flag_unhinted )
+        load_flags |= FT_LOAD_NO_HINTING;
+
+      if ( image_type & ftc_image_flag_autohinted )
+        load_flags |= FT_LOAD_FORCE_AUTOHINT;
+
+      /* load a chunk of small bitmaps in a row */
+      for ( ; count > 0; count--, glyph_index++, sbit++ )
+      {
+        /* by default, indicates a `missing' glyph */
+        sbit->buffer = 0;
+
+        error = FT_Load_Glyph( face, glyph_index, load_flags );
+        if ( !error )
+        {
+          FT_Int        temp;
+          FT_GlyphSlot  slot   = face->glyph;
+          FT_Bitmap*    bitmap = &slot->bitmap;
+          FT_Int        xadvance, yadvance;
+
+
+          /* check that our values fit into 8-bit containers!       */
+          /* If this is not the case, our bitmap is too large       */
+          /* and we will leave it as `missing' with sbit.buffer = 0 */
+
+#define CHECK_CHAR( d )  ( temp = (FT_Char)d, temp == d )
+#define CHECK_BYTE( d )  ( temp = (FT_Byte)d, temp == d )
+
+          /* XXX: FIXME: add support for vertical layouts maybe */
+
+          /* horizontal advance in pixels */
+          xadvance = ( slot->metrics.horiAdvance + 32 ) >> 6;
+          yadvance = ( slot->metrics.vertAdvance + 32 ) >> 6;
+
+          if ( CHECK_BYTE( bitmap->rows  )     &&
+               CHECK_BYTE( bitmap->width )     &&
+               CHECK_CHAR( bitmap->pitch )     &&
+               CHECK_CHAR( slot->bitmap_left ) &&
+               CHECK_CHAR( slot->bitmap_top  ) &&
+               CHECK_CHAR( xadvance )          &&
+               CHECK_CHAR( yadvance )          )
+          {
+            sbit->width    = (FT_Byte)bitmap->width;
+            sbit->height   = (FT_Byte)bitmap->rows;
+            sbit->pitch    = (FT_Char)bitmap->pitch;
+            sbit->left     = (FT_Char)slot->bitmap_left;
+            sbit->top      = (FT_Char)slot->bitmap_top;
+            sbit->xadvance = (FT_Char)xadvance;
+            sbit->yadvance = (FT_Char)yadvance;
+            sbit->format   = (FT_Byte)bitmap->pixel_mode;
+
+            /* grab the bitmap when possible */
+            if ( slot->flags & ft_glyph_own_bitmap )
+            {
+              slot->flags &= ~ft_glyph_own_bitmap;
+              sbit->buffer = bitmap->buffer;
+            }
+            else
+            {
+              /* copy the bitmap into a new buffer -- ignore error */
+              ftc_bitmap_copy( memory, bitmap, sbit );
+            }
+          }
+        }
+      }
+
+      /* ignore the errors that might have occurred --        */
+      /* we recognize unloaded glyphs with `sbit.buffer == 0' */
+      error = 0;
+    }
+
+  Exit:
+    if ( error && node )
+    {
+      FREE( node->elements );
+      FREE( node );
+    }
+
+    *anode = node;
+
+    return error;
+  }
+
+
+  /* this function is important because it is both part of */
+  /* an FTC_ChunkSet_Class and an FTC_CacheNode_Class      */
+  /*                                                       */
+  FT_CALLBACK_DEF( FT_ULong )
+  ftc_sbit_chunk_node_size( FTC_ChunkNode  node )
+  {
+    FT_ULong      size;
+    FTC_ChunkSet  cset  = node->cset;
+    FT_UInt       count = node->num_elements;
+    FT_Int        pitch;
+    FTC_SBit      sbit  = (FTC_SBit)node->elements;
+
+
+    /* the node itself */
+    size  = sizeof ( *node );
+
+    /* the sbit records */
+    size += cset->element_count * sizeof ( FTC_SBitRec );
+
+    for ( ; count > 0; count--, sbit++ )
+    {
+      if ( sbit->buffer )
+      {
+        pitch = sbit->pitch;
+        if ( pitch < 0 )
+          pitch = -pitch;
+
+        /* add the size of a given glyph image */
+        size += pitch * sbit->height;
+      }
+    }
+
+    return size;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                     SBIT CHUNK SETS                           *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_sbit_chunk_set_sizes( FTC_ChunkSet     cset,
+                            FTC_Image_Desc*  desc )
+  {
+    FT_Error  error;
+    FT_Face   face;
+
+
+    cset->element_count = FTC_SBITSET_ELEMENT_COUNT;
+    cset->element_size  = sizeof ( FTC_SBitRec );
+
+    /* lookup the FT_Face to obtain the number of glyphs */
+    error = FTC_Manager_Lookup_Face( cset->manager,
+                                     desc->font.face_id, &face );
+    if ( !error )
+      cset->element_max = face->num_glyphs;
+
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_sbit_chunk_set_init( FTC_SBitSet      sset,
+                           FTC_Image_Desc*  type )
+  {
+    sset->desc = *type;
+
+    return 0;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_sbit_chunk_set_compare( FTC_SBitSet      sset,
+                              FTC_Image_Desc*  type )
+  {
+    return FT_BOOL( !memcmp( &sset->desc, type, sizeof ( *type ) ) );
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_ChunkSet_Class  ftc_sbit_chunk_set_class =
+  {
+    sizeof( FTC_SBitSetRec ),
+
+    (FTC_ChunkSet_InitFunc)       ftc_sbit_chunk_set_init,
+    (FTC_ChunkSet_DoneFunc)       0,
+    (FTC_ChunkSet_CompareFunc)    ftc_sbit_chunk_set_compare,
+    (FTC_ChunkSet_SizesFunc)      ftc_sbit_chunk_set_sizes,
+
+    (FTC_ChunkSet_NewNodeFunc)    ftc_sbit_chunk_node_new,
+    (FTC_ChunkSet_SizeNodeFunc)   ftc_sbit_chunk_node_size,
+    (FTC_ChunkSet_DestroyNodeFunc)ftc_sbit_chunk_node_destroy
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                     SBITS CACHE                               *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_Chunk_Cache_Class  ftc_sbit_cache_class =
+  {
+    {
+      sizeof( FTC_SBit_CacheRec ),
+      (FTC_Cache_InitFunc)FTC_Chunk_Cache_Init,
+      (FTC_Cache_DoneFunc)FTC_Chunk_Cache_Done
+    },
+    (FTC_ChunkSet_Class*)&ftc_sbit_chunk_set_class
+  };
+
+
+  /* documentation is in ftcsbits.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBit_Cache_New( FTC_Manager      manager,
+                      FTC_SBit_Cache  *acache )
+  {
+    return FTC_Manager_Register_Cache(
+             manager,
+             (FTC_Cache_Class*)&ftc_sbit_cache_class,
+             (FTC_Cache*)acache );
+  }
+
+
+  /* documentation is in ftcsbits.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBit_Cache_Lookup( FTC_SBit_Cache   cache,
+                         FTC_Image_Desc*  desc,
+                         FT_UInt          gindex,
+                         FTC_SBit        *ansbit )
+  {
+    FT_Error       error;
+    FTC_ChunkNode  node;
+    FT_UInt        cindex;
+
+
+    /* argument checks delayed to FTC_Chunk_Cache_Lookup */
+    if ( !ansbit )
+      return FTC_Err_Invalid_Argument;
+
+    *ansbit = 0;
+    error   = FTC_Chunk_Cache_Lookup( &cache->root, desc, gindex,
+                                      &node, &cindex );
+    if ( !error )
+      *ansbit = (FTC_SBit)node->elements + cindex;
+
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftdebug.c b/libraries/freetype-2.0.5/ftdebug.c
new file mode 100644 (file)
index 0000000..6a3fc49
--- /dev/null
@@ -0,0 +1,118 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftdebug.c                                                              */
+/*                                                                         */
+/*    Debugging and logging component (body).                              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This component contains various macros and functions used to ease the */
+  /* debugging of the FreeType engine.  Its main purpose is in assertion   */
+  /* checking, tracing, and error detection.                               */
+  /*                                                                       */
+  /* There are now three debugging modes:                                  */
+  /*                                                                       */
+  /* - trace mode                                                          */
+  /*                                                                       */
+  /*   Error and trace messages are sent to the log file (which can be the */
+  /*   standard error output).                                             */
+  /*                                                                       */
+  /* - error mode                                                          */
+  /*                                                                       */
+  /*   Only error messages are generated.                                  */
+  /*                                                                       */
+  /* - release mode:                                                       */
+  /*                                                                       */
+  /*   No error message is sent or generated.  The code is free from any   */
+  /*   debugging parts.                                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+  char  ft_trace_levels[trace_max];
+#endif
+
+
+#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE )
+
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+  FT_EXPORT_DEF( void )
+  FT_Message( const char*  fmt, ... )
+  {
+    va_list  ap;
+
+
+    va_start( ap, fmt );
+    vprintf( fmt, ap );
+    va_end( ap );
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Panic( const char*  fmt, ... )
+  {
+    va_list  ap;
+
+
+    va_start( ap, fmt );
+    vprintf( fmt, ap );
+    va_end( ap );
+
+    exit( EXIT_FAILURE );
+  }
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+  FT_EXPORT_DEF( void )
+  FT_SetTraceLevel( FT_Trace  component,
+                    char      level )
+  {
+    if ( component >= trace_max )
+      return;
+
+    /* if component is `trace_any', change _all_ levels at once */
+    if ( component == trace_any )
+    {
+      int  n;
+
+
+      for ( n = trace_any; n < trace_max; n++ )
+        ft_trace_levels[n] = level;
+    }
+    else        /* otherwise, only change individual component */
+      ft_trace_levels[component] = level;
+  }
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */
+
+
+  /* ANSI C doesn't allow empty files, so we insert a dummy symbol */
+  extern const int  ft_debug_dummy;
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftextend.c b/libraries/freetype-2.0.5/ftextend.c
new file mode 100644 (file)
index 0000000..cafb284
--- /dev/null
@@ -0,0 +1,302 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftextend.c                                                             */
+/*                                                                         */
+/*    FreeType extensions implementation (body).                           */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  This is an updated version of the extension component, now located   */
+  /*  in the main library's source directory.  It allows the dynamic       */
+  /*  registration/use of various face object extensions through a simple  */
+  /*  API.                                                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_EXTEND_H
+#include FT_INTERNAL_DEBUG_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_extend
+
+
+  typedef struct  FT_Extension_Registry_
+  {
+    FT_Int              num_extensions;
+    FT_Long             cur_offset;
+    FT_Extension_Class  classes[FT_MAX_EXTENSIONS];
+
+  } FT_Extension_Registry;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Init_Extensions                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes the extension component.                               */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    driver :: A handle to the driver object.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  FT_Init_Extensions( FT_Driver  driver )
+  {
+    FT_Error                error;
+    FT_Memory               memory;
+    FT_Extension_Registry*  registry;
+
+
+    memory = driver->root.library->memory;
+    if ( ALLOC( registry, sizeof ( *registry ) ) )
+      return error;
+
+    registry->num_extensions = 0;
+    registry->cur_offset     = 0;
+    driver->extensions       = registry;
+
+    FT_TRACE2(( "FT_Init_Extensions: success\n" ));
+
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Extensions                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes the extension component.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    driver :: A handle to the driver object.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  FT_Done_Extensions( FT_Driver  driver )
+  {
+    FT_Memory  memory = driver->root.memory;
+
+
+    FREE( driver->extensions );
+    return FT_Err_Ok;
+  }
+
+
+  /* documentation is in ftextend.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Register_Extension( FT_Driver            driver,
+                         FT_Extension_Class*  clazz )
+  {
+    FT_Extension_Registry*  registry;
+
+
+    if ( !driver )
+      return FT_Err_Invalid_Driver_Handle;
+
+    if ( !clazz )
+      return FT_Err_Invalid_Argument;
+
+    registry = (FT_Extension_Registry*)driver->extensions;
+    if ( registry )
+    {
+      FT_Int               n   = registry->num_extensions;
+      FT_Extension_Class*  cur = registry->classes + n;
+
+
+      if ( n >= FT_MAX_EXTENSIONS )
+        return FT_Err_Too_Many_Extensions;
+
+      *cur = *clazz;
+
+      cur->offset  = registry->cur_offset;
+
+      registry->num_extensions++;
+      registry->cur_offset +=
+        ( cur->size + FT_ALIGNMENT - 1 ) & -FT_ALIGNMENT;
+
+      FT_TRACE1(( "FT_Register_Extension: `%s' successfully registered\n",
+                  cur->id ));
+    }
+
+    return FT_Err_Ok;
+  }
+
+
+  /* documentation is in ftextend.h */
+
+  FT_EXPORT_DEF( void* )
+  FT_Get_Extension( FT_Face      face,
+                    const char*  extension_id,
+                    void**       extension_interface )
+  {
+    FT_Extension_Registry*  registry;
+
+
+    if ( !face || !extension_id || !extension_interface )
+      return 0;
+
+    registry = (FT_Extension_Registry*)face->driver->extensions;
+    if ( registry && face->extensions )
+    {
+      FT_Extension_Class*  cur   = registry->classes;
+      FT_Extension_Class*  limit = cur + registry->num_extensions;
+
+
+      for ( ; cur < limit; cur++ )
+        if ( strcmp( cur->id, extension_id ) == 0 )
+        {
+          *extension_interface = cur->interface;
+
+          FT_TRACE1(( "FT_Get_Extension: got `%s'\n", extension_id ));
+
+          return (void*)((char*)face->extensions + cur->offset);
+        }
+    }
+
+    /* could not find the extension id */
+
+    FT_ERROR(( "FT_Get_Extension: couldn't find `%s'\n", extension_id ));
+
+    *extension_interface = 0;
+
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Destroy_Extensions                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys all extensions within a face object.                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face :: A handle to the face object.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Called by the face object destructor.                              */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  FT_Destroy_Extensions( FT_Face  face )
+  {
+    FT_Extension_Registry*  registry;
+    FT_Memory               memory;
+
+
+    registry = (FT_Extension_Registry*)face->driver->extensions;
+    if ( registry && face->extensions )
+    {
+      FT_Extension_Class*  cur   = registry->classes;
+      FT_Extension_Class*  limit = cur + registry->num_extensions;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        char*  ext = (char*)face->extensions + cur->offset;
+
+        if ( cur->finalize )
+          cur->finalize( ext, face );
+      }
+
+      memory = face->driver->root.memory;
+      FREE( face->extensions );
+    }
+
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Create_Extensions                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates an extension object within a face object for all           */
+  /*    registered extensions.                                             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face :: A handle to the face object.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Called by the face object constructor.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  FT_Create_Extensions( FT_Face  face )
+  {
+    FT_Extension_Registry*  registry;
+    FT_Memory               memory;
+    FT_Error                error;
+
+
+    face->extensions = 0;
+
+    /* load extensions registry; exit successfully if none is there */
+
+    registry = (FT_Extension_Registry*)face->driver->extensions;
+    if ( !registry )
+      return FT_Err_Ok;
+
+    memory = face->driver->root.memory;
+    if ( ALLOC( face->extensions, registry->cur_offset ) )
+      return error;
+
+    {
+      FT_Extension_Class*  cur   = registry->classes;
+      FT_Extension_Class*  limit = cur + registry->num_extensions;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        char*  ext = (char*)face->extensions + cur->offset;
+
+        if ( cur->init )
+        {
+          error = cur->init( ext, face );
+          if ( error )
+            break;
+        }
+      }
+    }
+
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftglyph.c b/libraries/freetype-2.0.5/ftglyph.c
new file mode 100644 (file)
index 0000000..c3b37e5
--- /dev/null
@@ -0,0 +1,680 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftglyph.c                                                              */
+/*                                                                         */
+/*    FreeType convenience functions to handle glyphs (body).              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  This file contains the definition of several convenience functions   */
+  /*  that can be used by client applications to easily retrieve glyph     */
+  /*  bitmaps and outlines from a given face.                              */
+  /*                                                                       */
+  /*  These functions should be optional if you are writing a font server  */
+  /*  or text layout engine on top of FreeType.  However, they are pretty  */
+  /*  handy for many other simple uses of the library.                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_GLYPH_H
+#include FT_OUTLINE_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_glyph
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   Convenience functions                                         ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* documentation is in ftglyph.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Matrix_Multiply( FT_Matrix*  a,
+                      FT_Matrix*  b )
+  {
+    FT_Fixed  xx, xy, yx, yy;
+
+
+    if ( !a || !b )
+      return;
+
+    xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );
+    xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );
+    yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );
+    yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );
+
+    b->xx = xx;  b->xy = xy;
+    b->yx = yx;  b->yy = yy;
+  }
+
+
+  /* documentation is in ftglyph.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Matrix_Invert( FT_Matrix*  matrix )
+  {
+    FT_Pos  delta, xx, yy;
+
+
+    if ( !matrix )
+      return FT_Err_Invalid_Argument;
+
+    /* compute discriminant */
+    delta = FT_MulFix( matrix->xx, matrix->yy ) -
+            FT_MulFix( matrix->xy, matrix->yx );
+
+    if ( !delta )
+      return FT_Err_Invalid_Argument;  /* matrix can't be inverted */
+
+    matrix->xy = - FT_DivFix( matrix->xy, delta );
+    matrix->yx = - FT_DivFix( matrix->yx, delta );
+
+    xx = matrix->xx;
+    yy = matrix->yy;
+
+    matrix->xx = FT_DivFix( yy, delta );
+    matrix->yy = FT_DivFix( xx, delta );
+
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   FT_BitmapGlyph support                                        ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static FT_Error
+  ft_bitmap_copy( FT_Memory   memory,
+                  FT_Bitmap*  source,
+                  FT_Bitmap*  target )
+  {
+    FT_Error  error;
+    FT_Int    pitch = source->pitch;
+    FT_ULong  size;
+
+
+    *target = *source;
+
+    if ( pitch < 0 )
+      pitch = -pitch;
+
+    size = (FT_ULong)( pitch * source->rows );
+
+    if ( !ALLOC( target->buffer, size ) )
+      MEM_Copy( target->buffer, source->buffer, size );
+
+    return error;
+  }
+
+
+  static FT_Error
+  ft_bitmap_glyph_init( FT_BitmapGlyph  glyph,
+                        FT_GlyphSlot    slot )
+  {
+    FT_Error    error   = FT_Err_Ok;
+    FT_Library  library = FT_GLYPH(glyph)->library;
+    FT_Memory   memory  = library->memory;
+
+
+    if ( slot->format != ft_glyph_format_bitmap )
+    {
+      error = FT_Err_Invalid_Glyph_Format;
+      goto Exit;
+    }
+
+    /* grab the bitmap in the slot - do lazy copying whenever possible */
+    glyph->bitmap = slot->bitmap;
+    glyph->left   = slot->bitmap_left;
+    glyph->top    = slot->bitmap_top;
+
+    if ( slot->flags & ft_glyph_own_bitmap )
+      slot->flags &= ~ft_glyph_own_bitmap;
+    else
+    {
+      /* copy the bitmap into a new buffer */
+      error = ft_bitmap_copy( memory, &slot->bitmap, &glyph->bitmap );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_Error
+  ft_bitmap_glyph_copy( FT_BitmapGlyph  source,
+                        FT_BitmapGlyph  target )
+  {
+    FT_Memory  memory = source->root.library->memory;
+
+
+    target->left = source->left;
+    target->top  = source->top;
+
+    return ft_bitmap_copy( memory, &source->bitmap, &target->bitmap );
+  }
+
+
+  static void
+  ft_bitmap_glyph_done( FT_BitmapGlyph  glyph )
+  {
+    FT_Memory  memory = FT_GLYPH(glyph)->library->memory;
+
+
+    FREE( glyph->bitmap.buffer );
+  }
+
+
+  static void
+  ft_bitmap_glyph_bbox( FT_BitmapGlyph  glyph,
+                        FT_BBox*        cbox )
+  {
+    cbox->xMin = glyph->left << 6;
+    cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
+    cbox->yMax = glyph->top << 6;
+    cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );
+  }
+
+
+  const FT_Glyph_Class  ft_bitmap_glyph_class =
+  {
+    sizeof( FT_BitmapGlyphRec ),
+    ft_glyph_format_bitmap,
+
+    (FT_Glyph_Init_Func)     ft_bitmap_glyph_init,
+    (FT_Glyph_Done_Func)     ft_bitmap_glyph_done,
+    (FT_Glyph_Copy_Func)     ft_bitmap_glyph_copy,
+    (FT_Glyph_Transform_Func)0,
+    (FT_Glyph_BBox_Func)     ft_bitmap_glyph_bbox,
+    (FT_Glyph_Prepare_Func)  0
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   FT_OutlineGlyph support                                       ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static FT_Error
+  ft_outline_glyph_init( FT_OutlineGlyph  glyph,
+                         FT_GlyphSlot     slot )
+  {
+    FT_Error     error   = FT_Err_Ok;
+    FT_Library   library = FT_GLYPH(glyph)->library;
+    FT_Outline*  source  = &slot->outline;
+    FT_Outline*  target  = &glyph->outline;
+
+
+    /* check format in glyph slot */
+    if ( slot->format != ft_glyph_format_outline )
+    {
+      error = FT_Err_Invalid_Glyph_Format;
+      goto Exit;
+    }
+
+    /* allocate new outline */
+    error = FT_Outline_New( library, source->n_points, source->n_contours,
+                            &glyph->outline );
+    if ( error )
+      goto Exit;
+
+    /* copy it */
+    MEM_Copy( target->points, source->points,
+              source->n_points * sizeof ( FT_Vector ) );
+
+    MEM_Copy( target->tags, source->tags,
+              source->n_points * sizeof ( FT_Byte ) );
+
+    MEM_Copy( target->contours, source->contours,
+              source->n_contours * sizeof ( FT_Short ) );
+
+    /* copy all flags, except the `ft_outline_owner' one */
+    target->flags = source->flags | ft_outline_owner;
+
+  Exit:
+    return error;
+  }
+
+
+  static void
+  ft_outline_glyph_done( FT_OutlineGlyph  glyph )
+  {
+    FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
+  }
+
+
+  static FT_Error
+  ft_outline_glyph_copy( FT_OutlineGlyph  source,
+                         FT_OutlineGlyph  target )
+  {
+    FT_Error    error;
+    FT_Library  library = FT_GLYPH( source )->library;
+
+
+    error = FT_Outline_New( library, source->outline.n_points,
+                            source->outline.n_contours, &target->outline );
+    if ( !error )
+      FT_Outline_Copy( &source->outline, &target->outline );
+
+    return error;
+  }
+
+
+  static void
+  ft_outline_glyph_transform( FT_OutlineGlyph  glyph,
+                              FT_Matrix*       matrix,
+                              FT_Vector*       delta )
+  {
+    if ( matrix )
+      FT_Outline_Transform( &glyph->outline, matrix );
+
+    if ( delta )
+      FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
+  }
+
+
+  static void
+  ft_outline_glyph_bbox( FT_OutlineGlyph  glyph,
+                         FT_BBox*         bbox )
+  {
+    FT_Outline_Get_CBox( &glyph->outline, bbox );
+  }
+
+
+  static FT_Error
+  ft_outline_glyph_prepare( FT_OutlineGlyph  glyph,
+                            FT_GlyphSlot     slot )
+  {
+    slot->format         = ft_glyph_format_outline;
+    slot->outline        = glyph->outline;
+    slot->outline.flags &= ~ft_outline_owner;
+
+    return FT_Err_Ok;
+  }
+
+
+  const FT_Glyph_Class  ft_outline_glyph_class =
+  {
+    sizeof( FT_OutlineGlyphRec ),
+    ft_glyph_format_outline,
+
+    (FT_Glyph_Init_Func)     ft_outline_glyph_init,
+    (FT_Glyph_Done_Func)     ft_outline_glyph_done,
+    (FT_Glyph_Copy_Func)     ft_outline_glyph_copy,
+    (FT_Glyph_Transform_Func)ft_outline_glyph_transform,
+    (FT_Glyph_BBox_Func)     ft_outline_glyph_bbox,
+    (FT_Glyph_Prepare_Func)  ft_outline_glyph_prepare
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   FT_Glyph class and API                                        ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+   static FT_Error
+   ft_new_glyph( FT_Library             library,
+                 const FT_Glyph_Class*  clazz,
+                 FT_Glyph*              aglyph )
+   {
+     FT_Memory  memory = library->memory;
+     FT_Error   error;
+     FT_Glyph   glyph;
+
+
+     *aglyph = 0;
+
+     if ( !ALLOC( glyph, clazz->glyph_size ) )
+     {
+       glyph->library = library;
+       glyph->clazz   = clazz;
+       glyph->format  = clazz->glyph_format;
+
+       *aglyph = glyph;
+     }
+
+     return error;
+   }
+
+
+  /* documentation is in ftglyph.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Glyph_Copy( FT_Glyph   source,
+                 FT_Glyph  *target )
+  {
+    FT_Glyph               copy;
+    FT_Error               error;
+    const FT_Glyph_Class*  clazz;
+
+
+    /* check arguments */
+    if ( !target || !source || !source->clazz )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    *target = 0;
+
+    clazz = source->clazz;
+    error = ft_new_glyph( source->library, clazz, &copy );
+    if ( error )
+      goto Exit;
+
+    copy->advance = source->advance;
+    copy->format  = source->format;
+
+    if ( clazz->glyph_copy )
+      error = clazz->glyph_copy( source, copy );
+
+    if ( error )
+      FT_Done_Glyph( copy );
+    else
+      *target = copy;
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in ftglyph.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_Glyph( FT_GlyphSlot  slot,
+                FT_Glyph     *aglyph )
+  {
+    FT_Library  library = slot->library;
+    FT_Error    error;
+    FT_Glyph    glyph;
+
+    const FT_Glyph_Class*  clazz = 0;
+
+
+    if ( !slot )
+      return FT_Err_Invalid_Slot_Handle;
+
+    if ( !aglyph )
+      return FT_Err_Invalid_Argument;
+
+    /* if it is a bitmap, that's easy :-) */
+    if ( slot->format == ft_glyph_format_bitmap )
+      clazz = &ft_bitmap_glyph_class;
+
+    /* it it is an outline too */
+    else if ( slot->format == ft_glyph_format_outline )
+      clazz = &ft_outline_glyph_class;
+
+    else
+    {
+      /* try to find a renderer that supports the glyph image format */
+      FT_Renderer  render = FT_Lookup_Renderer( library, slot->format, 0 );
+
+
+      if ( render )
+        clazz = &render->glyph_class;
+    }
+
+    if ( !clazz )
+    {
+      error = FT_Err_Invalid_Glyph_Format;
+      goto Exit;
+    }
+
+    /* create FT_Glyph object */
+    error = ft_new_glyph( library, clazz, &glyph );
+    if ( error )
+      goto Exit;
+
+    /* copy advance while converting it to 16.16 format */
+    glyph->advance.x = slot->advance.x << 10;
+    glyph->advance.y = slot->advance.y << 10;
+
+    /* now import the image from the glyph slot */
+    error = clazz->glyph_init( glyph, slot );
+
+    /* if an error occurred, destroy the glyph */
+    if ( error )
+      FT_Done_Glyph( glyph );
+    else
+      *aglyph = glyph;
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in ftglyph.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Glyph_Transform( FT_Glyph    glyph,
+                      FT_Matrix*  matrix,
+                      FT_Vector*  delta )
+  {
+    const FT_Glyph_Class*  clazz;
+    FT_Error               error = FT_Err_Ok;
+
+
+    if ( !glyph || !glyph->clazz )
+      error = FT_Err_Invalid_Argument;
+    else
+    {
+      clazz = glyph->clazz;
+      if ( clazz->glyph_transform )
+      {
+        /* transform glyph image */
+        clazz->glyph_transform( glyph, matrix, delta );
+
+        /* transform advance vector */
+        if ( matrix )
+          FT_Vector_Transform( &glyph->advance, matrix );
+      }
+      else
+        error = FT_Err_Invalid_Glyph_Format;
+    }
+    return error;
+  }
+
+
+  /* documentation is in ftglyph.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Glyph_Get_CBox( FT_Glyph  glyph,
+                     FT_UInt   bbox_mode,
+                     FT_BBox  *acbox )
+  {
+    const FT_Glyph_Class*  clazz;
+
+
+    if ( !acbox )
+      return;
+
+    acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
+
+    if ( !glyph || !glyph->clazz )
+      return;
+    else
+    {
+      clazz = glyph->clazz;
+      if ( !clazz->glyph_bbox )
+        return;
+      else
+      {
+        /* retrieve bbox in 26.6 coordinates */
+        clazz->glyph_bbox( glyph, acbox );
+
+        /* perform grid fitting if needed */
+        if ( bbox_mode & ft_glyph_bbox_gridfit )
+        {
+          acbox->xMin &= -64;
+          acbox->yMin &= -64;
+          acbox->xMax  = ( acbox->xMax + 63 ) & -64;
+          acbox->yMax  = ( acbox->yMax + 63 ) & -64;
+        }
+
+        /* convert to integer pixels if needed */
+        if ( bbox_mode & ft_glyph_bbox_truncate )
+        {
+          acbox->xMin >>= 6;
+          acbox->yMin >>= 6;
+          acbox->xMax >>= 6;
+          acbox->yMax >>= 6;
+        }
+      }
+    }
+    return;
+  }
+
+
+  /* documentation is in ftglyph.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Glyph_To_Bitmap( FT_Glyph*   the_glyph,
+                      FT_ULong    render_mode,
+                      FT_Vector*  origin,
+                      FT_Bool     destroy )
+  {
+    FT_GlyphSlotRec  dummy;
+    FT_Error         error;
+    FT_Glyph         glyph;
+    FT_BitmapGlyph   bitmap;
+
+    const FT_Glyph_Class*  clazz;
+
+
+    /* check argument */
+    if ( !the_glyph )
+      goto Bad;
+
+    /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
+    /* then calling FT_Render_Glyph_Internal()                            */
+
+    glyph = *the_glyph;
+    if ( !glyph )
+      goto Bad;
+
+    clazz = glyph->clazz;
+    if ( !clazz || !clazz->glyph_prepare )
+      goto Bad;
+
+    MEM_Set( &dummy, 0, sizeof ( dummy ) );
+    dummy.library = glyph->library;
+    dummy.format  = clazz->glyph_format;
+
+    /* if `origin' is set, translate the glyph image */
+    if ( origin )
+      FT_Glyph_Transform( glyph, 0, origin );
+
+    /* create result bitmap glyph */
+    error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class,
+                          (FT_Glyph*)&bitmap );
+    if ( error )
+      goto Exit;
+
+    /* prepare dummy slot for rendering */
+    error = clazz->glyph_prepare( glyph, &dummy );
+    if ( !error )
+      error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
+
+    if ( error )
+    {
+      FT_Done_Glyph( FT_GLYPH( bitmap ) );
+      goto Exit;
+    }
+
+    if ( !destroy && origin )
+    {
+      FT_Vector  v;
+
+
+      v.x = -origin->x;
+      v.y = -origin->y;
+      FT_Glyph_Transform( glyph, 0, &v );
+    }
+
+    /* in case of success, copy the bitmap to the glyph bitmap */
+    if ( !error )
+    {
+      error = ft_bitmap_glyph_init( bitmap, &dummy );
+      if ( error )
+      {
+        /* this should never happen, but let's be safe */
+        FT_Done_Glyph( FT_GLYPH( bitmap ) );
+        goto Exit;
+      }
+
+      /* copy advance */
+      bitmap->root.advance = glyph->advance;
+
+      if ( destroy )
+        FT_Done_Glyph( glyph );
+
+      *the_glyph = FT_GLYPH( bitmap );
+    }
+
+  Exit:
+    return error;
+
+  Bad:
+    error = FT_Err_Invalid_Argument;
+    goto Exit;
+  }
+
+
+  /* documentation is in ftglyph.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Done_Glyph( FT_Glyph  glyph )
+  {
+    if ( glyph )
+    {
+      FT_Memory              memory = glyph->library->memory;
+      const FT_Glyph_Class*  clazz  = glyph->clazz;
+
+
+      if ( clazz->glyph_done )
+        clazz->glyph_done( glyph );
+
+      FREE( glyph );
+    }
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftgrays.c b/libraries/freetype-2.0.5/ftgrays.c
new file mode 100644 (file)
index 0000000..3b8fa70
--- /dev/null
@@ -0,0 +1,2043 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftgrays.c                                                              */
+/*                                                                         */
+/*    A new `perfect' anti-aliasing renderer (body).                       */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  This file can be compiled without the rest of the FreeType engine,   */
+  /*  by defining the _STANDALONE_ macro when compiling it.  You also need */
+  /*  to put the files `ftgrays.h' and `ftimage.h' into the current        */
+  /*  compilation directory.  Typically, you could do something like       */
+  /*                                                                       */
+  /*  - copy `src/base/ftgrays.c' to your current directory                */
+  /*                                                                       */
+  /*  - copy `include/freetype/ftimage.h' and                              */
+  /*    `include/freetype/ftgrays.h' to the same directory                 */
+  /*                                                                       */
+  /*  - compile `ftgrays' with the _STANDALONE_ macro defined, as in       */
+  /*                                                                       */
+  /*      cc -c -D_STANDALONE_ ftgrays.c                                   */
+  /*                                                                       */
+  /*  The renderer can be initialized with a call to                       */
+  /*  `ft_gray_raster.gray_raster_new'; an anti-aliased bitmap can be      */
+  /*  generated with a call to `ft_gray_raster.gray_raster_render'.        */
+  /*                                                                       */
+  /*  See the comments and documentation in the file `ftimage.h' for       */
+  /*  more details on how the raster works.                                */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  This is a new anti-aliasing scan-converter for FreeType 2.  The      */
+  /*  algorithm used here is _very_ different from the one in the standard */
+  /*  `ftraster' module.  Actually, `ftgrays' computes the _exact_         */
+  /*  coverage of the outline on each pixel cell.                          */
+  /*                                                                       */
+  /*  It is based on ideas that I initially found in Raph Levien's         */
+  /*  excellent LibArt graphics library (see http://www.levien.com/libart  */
+  /*  for more information, though the web pages do not tell anything      */
+  /*  about the renderer; you'll have to dive into the source code to      */
+  /*  understand how it works).                                            */
+  /*                                                                       */
+  /*  Note, however, that this is a _very_ different implementation        */
+  /*  compared to Raph's.  Coverage information is stored in a very        */
+  /*  different way, and I don't use sorted vector paths.  Also, it        */
+  /*  doesn't use floating point values.                                   */
+  /*                                                                       */
+  /*  This renderer has the following advantages:                          */
+  /*                                                                       */
+  /*  - It doesn't need an intermediate bitmap.  Instead, one can supply   */
+  /*    a callback function that will be called by the renderer to draw    */
+  /*    gray spans on any target surface.  You can thus do direct          */
+  /*    composition on any kind of bitmap, provided that you give the      */
+  /*    renderer the right callback.                                       */
+  /*                                                                       */
+  /*  - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on  */
+  /*    each pixel cell                                                    */
+  /*                                                                       */
+  /*  - It performs a single pass on the outline (the `standard' FT2       */
+  /*    renderer makes two passes).                                        */
+  /*                                                                       */
+  /*  - It can easily be modified to render to _any_ number of gray levels */
+  /*    cheaply.                                                           */
+  /*                                                                       */
+  /*  - For small (< 20) pixel sizes, it is faster than the standard       */
+  /*    renderer.                                                          */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <string.h>             /* for memcpy() */
+#include <setjmp.h>
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_aaraster
+
+
+#define ErrRaster_MemoryOverflow   -4
+
+#ifdef _STANDALONE_
+
+
+#define ErrRaster_Invalid_Mode     -2
+#define ErrRaster_Invalid_Outline  -1
+
+#include "ftimage.h"
+#include "ftgrays.h"
+
+  /* This macro is used to indicate that a function parameter is unused. */
+  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
+  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+  /* ANSI compilers (e.g. LCC).                                          */
+#define FT_UNUSED( x )  (x) = (x)
+
+  /* Disable the tracing mechanism for simplicity -- developers can      */
+  /* activate it easily by redefining these two macros.                  */
+#ifndef FT_ERROR
+#define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+
+#else /* _STANDALONE_ */
+
+
+#include <ft2build.h>
+#include "ftgrays.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_OUTLINE_H
+
+#include "ftsmerrs.h"
+
+#define ErrRaster_Invalid_Mode     Smooth_Err_Cannot_Render_Glyph
+#define ErrRaster_Invalid_Outline  Smooth_Err_Invalid_Outline
+
+
+#endif /* _STANDALONE_ */
+
+
+  /* define this to dump debugging information */
+#define xxxDEBUG_GRAYS
+
+  /* as usual, for the speed hungry :-) */
+
+#ifndef FT_STATIC_RASTER
+
+
+#define RAS_ARG   PRaster  raster
+#define RAS_ARG_  PRaster  raster,
+
+#define RAS_VAR   raster
+#define RAS_VAR_  raster,
+
+#define ras       (*raster)
+
+
+#else /* FT_STATIC_RASTER */
+
+
+#define RAS_ARG   /* empty */
+#define RAS_ARG_  /* empty */
+#define RAS_VAR   /* empty */
+#define RAS_VAR_  /* empty */
+
+  static TRaster  ras;
+
+
+#endif /* FT_STATIC_RASTER */
+
+
+  /* must be at least 6 bits! */
+#define PIXEL_BITS  8
+
+#define ONE_PIXEL       ( 1L << PIXEL_BITS )
+#define PIXEL_MASK      ( -1L << PIXEL_BITS )
+#define TRUNC( x )      ( (x) >> PIXEL_BITS )
+#define SUBPIXELS( x )  ( (x) << PIXEL_BITS )
+#define FLOOR( x )      ( (x) & -ONE_PIXEL )
+#define CEILING( x )    ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
+#define ROUND( x )      ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
+
+#if PIXEL_BITS >= 6
+#define UPSCALE( x )    ( (x) << ( PIXEL_BITS - 6 ) )
+#define DOWNSCALE( x )  ( (x) >> ( PIXEL_BITS - 6 ) )
+#else
+#define UPSCALE( x )    ( (x) >> ( 6 - PIXEL_BITS ) )
+#define DOWNSCALE( x )  ( (x) << ( 6 - PIXEL_BITS ) )
+#endif
+
+  /* Define this if you want to use a more compact storage scheme.  This   */
+  /* increases the number of cells available in the render pool but slows  */
+  /* down the rendering a bit.  It is useful if you have a really tiny     */
+  /* render pool.                                                          */
+#define xxxGRAYS_COMPACT
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*   TYPE DEFINITIONS                                                    */
+  /*                                                                       */
+  
+  /* don't change the following types to FT_Int or FT_Pos, since we might */
+  /* need to define them to "float" or "double" when experimenting with   */
+  /* new algorithms                                                       */
+
+  typedef int   TScan;   /* integer scanline/pixel coordinate */
+  typedef long  TPos;    /* sub-pixel coordinate              */
+
+  /* determine the type used to store cell areas.  This normally takes at */
+  /* least PIXEL_BYTES*2 + 1.  On 16-bit systems, we need to use `long'   */
+  /* instead of `int', otherwise bad things happen                        */
+#if PIXEL_BITS <= 7
+
+  typedef int   TArea;
+
+#else /* PIXEL_BITS >= 8 */
+
+  /* approximately determine the size of integers using an ANSI-C header */
+#include <limits.h>
+
+#if UINT_MAX == 0xFFFFU
+  typedef long  TArea;
+#else
+  typedef int  TArea;
+#endif
+
+#endif /* PIXEL_BITS >= 8 */
+
+
+  /* maximal number of gray spans in a call to the span callback */
+#define FT_MAX_GRAY_SPANS  32
+
+
+#ifdef GRAYS_COMPACT
+
+  typedef struct  TCell_
+  {
+    short  x     : 14;
+    short  y     : 14;
+    int    cover : PIXEL_BITS + 2;
+    int    area  : PIXEL_BITS * 2 + 2;
+
+  } TCell, *PCell;
+
+#else /* GRAYS_COMPACT */
+
+  typedef struct  TCell_
+  {
+    TScan  x;
+    TScan  y;
+    int    cover;
+    TArea  area;
+
+  } TCell, *PCell;
+
+#endif /* GRAYS_COMPACT */
+
+
+  typedef struct  TRaster_
+  {
+    PCell  cells;
+    int    max_cells;
+    int    num_cells;
+
+    TScan  min_ex, max_ex;
+    TScan  min_ey, max_ey;
+
+    TArea  area;
+    int    cover;
+    int    invalid;
+
+    TScan  ex, ey;
+    TScan  cx, cy;
+    TPos   x,  y;
+
+    TScan  last_ey;
+
+    FT_Vector   bez_stack[32 * 3 + 1];
+    int         lev_stack[32];
+
+    FT_Outline  outline;
+    FT_Bitmap   target;
+    FT_BBox     clip_box;
+
+    FT_Span     gray_spans[FT_MAX_GRAY_SPANS];
+    int         num_gray_spans;
+
+    FT_Raster_Span_Func  render_span;
+    void*                render_span_data;
+    int                  span_y;
+
+    int  band_size;
+    int  band_shoot;
+    int  conic_level;
+    int  cubic_level;
+
+    void*    memory;
+    jmp_buf  jump_buffer;
+
+  } TRaster, *PRaster;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Initialize the cells table.                                           */
+  /*                                                                       */
+  static void
+  gray_init_cells( RAS_ARG_ void*  buffer,
+                   long            byte_size )
+  {
+    ras.cells     = (PCell)buffer;
+    ras.max_cells = byte_size / sizeof ( TCell );
+    ras.num_cells = 0;
+    ras.area      = 0;
+    ras.cover     = 0;
+    ras.invalid   = 1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Compute the outline bounding box.                                     */
+  /*                                                                       */
+  static void
+  gray_compute_cbox( RAS_ARG )
+  {
+    FT_Outline*  outline = &ras.outline;
+    FT_Vector*   vec     = outline->points;
+    FT_Vector*   limit   = vec + outline->n_points;
+
+
+    if ( outline->n_points <= 0 )
+    {
+      ras.min_ex = ras.max_ex = 0;
+      ras.min_ey = ras.max_ey = 0;
+      return;
+    }
+
+    ras.min_ex = ras.max_ex = vec->x;
+    ras.min_ey = ras.max_ey = vec->y;
+
+    vec++;
+
+    for ( ; vec < limit; vec++ )
+    {
+      TPos  x = vec->x;
+      TPos  y = vec->y;
+
+
+      if ( x < ras.min_ex ) ras.min_ex = x;
+      if ( x > ras.max_ex ) ras.max_ex = x;
+      if ( y < ras.min_ey ) ras.min_ey = y;
+      if ( y > ras.max_ey ) ras.max_ey = y;
+    }
+
+    /* truncate the bounding box to integer pixels */
+    ras.min_ex = ras.min_ex >> 6;
+    ras.min_ey = ras.min_ey >> 6;
+    ras.max_ex = ( ras.max_ex + 63 ) >> 6;
+    ras.max_ey = ( ras.max_ey + 63 ) >> 6;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Record the current cell in the table.                                 */
+  /*                                                                       */
+  static void
+  gray_record_cell( RAS_ARG )
+  {
+    PCell  cell;
+
+
+    if ( !ras.invalid && ( ras.area | ras.cover ) )
+    {
+      if ( ras.num_cells >= ras.max_cells )
+        longjmp( ras.jump_buffer, 1 );
+
+      cell        = ras.cells + ras.num_cells++;
+      cell->x     = ras.ex - ras.min_ex;
+      cell->y     = ras.ey - ras.min_ey;
+      cell->area  = ras.area;
+      cell->cover = ras.cover;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Set the current cell to a new position.                               */
+  /*                                                                       */
+  static void
+  gray_set_cell( RAS_ARG_ TScan  ex,
+                          TScan  ey )
+  {
+    int  invalid, record, clean;
+
+
+    /* Move the cell pointer to a new position.  We set the `invalid'      */
+    /* flag to indicate that the cell isn't part of those we're interested */
+    /* in during the render phase.  This means that:                       */
+    /*                                                                     */
+    /* . the new vertical position must be within min_ey..max_ey-1.        */
+    /* . the new horizontal position must be strictly less than max_ex     */
+    /*                                                                     */
+    /* Note that if a cell is to the left of the clipping region, it is    */
+    /* actually set to the (min_ex-1) horizontal position.                 */
+
+    record  = 0;
+    clean   = 1;
+
+    invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex );
+    if ( !invalid )
+    {
+      /* All cells that are on the left of the clipping region go to the */
+      /* min_ex - 1 horizontal position.                                 */
+      if ( ex < ras.min_ex )
+        ex = ras.min_ex - 1;
+
+      /* if our position is new, then record the previous cell */
+      if ( ex != ras.ex || ey != ras.ey )
+        record = 1;
+      else
+        clean = ras.invalid;  /* do not clean if we didn't move from */
+                              /* a valid cell                        */
+    }
+
+    /* record the previous cell if needed (i.e., if we changed the cell */
+    /* position, of changed the `invalid' flag)                         */
+    if ( ras.invalid != invalid || record )
+      gray_record_cell( RAS_VAR );
+
+    if ( clean )
+    {
+      ras.area  = 0;
+      ras.cover = 0;
+    }
+
+    ras.invalid = invalid;
+    ras.ex      = ex;
+    ras.ey      = ey;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Start a new contour at a given cell.                                  */
+  /*                                                                       */
+  static void
+  gray_start_cell( RAS_ARG_  TScan  ex,
+                             TScan  ey )
+  {
+    if ( ex < ras.min_ex )
+      ex = ras.min_ex - 1;
+
+    ras.area    = 0;
+    ras.cover   = 0;
+    ras.ex      = ex;
+    ras.ey      = ey;
+    ras.last_ey = SUBPIXELS( ey );
+    ras.invalid = 0;
+
+    gray_set_cell( RAS_VAR_ ex, ey );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Render a scanline as one or more cells.                               */
+  /*                                                                       */
+  static void
+  gray_render_scanline( RAS_ARG_  TScan  ey,
+                                  TPos   x1,
+                                  TScan  y1,
+                                  TPos   x2,
+                                  TScan  y2 )
+  {
+    TScan  ex1, ex2, fx1, fx2, delta;
+    long   p, first, dx;
+    int    incr, lift, mod, rem;
+
+
+    dx = x2 - x1;
+
+    ex1 = TRUNC( x1 ); /* if (ex1 >= ras.max_ex) ex1 = ras.max_ex-1; */
+    ex2 = TRUNC( x2 ); /* if (ex2 >= ras.max_ex) ex2 = ras.max_ex-1; */
+    fx1 = x1 - SUBPIXELS( ex1 );
+    fx2 = x2 - SUBPIXELS( ex2 );
+
+    /* trivial case.  Happens often */
+    if ( y1 == y2 )
+    {
+      gray_set_cell( RAS_VAR_ ex2, ey );
+      return;
+    }
+
+    /* everything is located in a single cell.  That is easy! */
+    /*                                                        */
+    if ( ex1 == ex2 )
+    {
+      delta      = y2 - y1;
+      ras.area  += (TArea)( fx1 + fx2 ) * delta;
+      ras.cover += delta;
+      return;
+    }
+
+    /* ok, we'll have to render a run of adjacent cells on the same */
+    /* scanline...                                                  */
+    /*                                                              */
+    p     = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
+    first = ONE_PIXEL;
+    incr  = 1;
+
+    if ( dx < 0 )
+    {
+      p     = fx1 * ( y2 - y1 );
+      first = 0;
+      incr  = -1;
+      dx    = -dx;
+    }
+
+    delta = p / dx;
+    mod   = p % dx;
+    if ( mod < 0 )
+    {
+      delta--;
+      mod += dx;
+    }
+
+    ras.area  += (TArea)( fx1 + first ) * delta;
+    ras.cover += delta;
+
+    ex1 += incr;
+    gray_set_cell( RAS_VAR_ ex1, ey );
+    y1  += delta;
+
+    if ( ex1 != ex2 )
+    {
+      p     = ONE_PIXEL * ( y2 - y1 );
+      lift  = p / dx;
+      rem   = p % dx;
+      if ( rem < 0 )
+      {
+        lift--;
+        rem += dx;
+      }
+
+      mod -= dx;
+
+      while ( ex1 != ex2 )
+      {
+        delta = lift;
+        mod  += rem;
+        if ( mod >= 0 )
+        {
+          mod -= dx;
+          delta++;
+        }
+
+        ras.area  += (TArea)ONE_PIXEL * delta;
+        ras.cover += delta;
+        y1        += delta;
+        ex1       += incr;
+        gray_set_cell( RAS_VAR_ ex1, ey );
+      }
+    }
+
+    delta      = y2 - y1;
+    ras.area  += (TArea)( fx2 + ONE_PIXEL - first ) * delta;
+    ras.cover += delta;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Render a given line as a series of scanlines.                         */
+  /*                                                                       */
+  static void
+  gray_render_line( RAS_ARG_ TPos  to_x,
+                             TPos  to_y )
+  {
+    TScan  ey1, ey2, fy1, fy2;
+    TPos   dx, dy, x, x2;
+    int    p, rem, mod, lift, delta, first, incr;
+
+
+    ey1 = TRUNC( ras.last_ey );
+    ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
+    fy1 = ras.y - ras.last_ey;
+    fy2 = to_y - SUBPIXELS( ey2 );
+
+    dx = to_x - ras.x;
+    dy = to_y - ras.y;
+
+    /* XXX: we should do something about the trivial case where dx == 0, */
+    /*      as it happens very often!                                    */
+
+    /* perform vertical clipping */
+    {
+      TScan  min, max;
+
+
+      min = ey1;
+      max = ey2;
+      if ( ey1 > ey2 )
+      {
+        min = ey2;
+        max = ey1;
+      }
+      if ( min >= ras.max_ey || max < ras.min_ey )
+        goto End;
+    }
+
+    /* everything is on a single scanline */
+    if ( ey1 == ey2 )
+    {
+      gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );
+      goto End;
+    }
+
+    /* ok, we have to render several scanlines */
+    p     = ( ONE_PIXEL - fy1 ) * dx;
+    first = ONE_PIXEL;
+    incr  = 1;
+
+    if ( dy < 0 )
+    {
+      p     = fy1 * dx;
+      first = 0;
+      incr  = -1;
+      dy    = -dy;
+    }
+
+    delta = p / dy;
+    mod   = p % dy;
+    if ( mod < 0 )
+    {
+      delta--;
+      mod += dy;
+    }
+
+    x = ras.x + delta;
+    gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first );
+
+    ey1 += incr;
+    gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
+
+    if ( ey1 != ey2 )
+    {
+      p     = ONE_PIXEL * dx;
+      lift  = p / dy;
+      rem   = p % dy;
+      if ( rem < 0 )
+      {
+        lift--;
+        rem += dy;
+      }
+      mod -= dy;
+
+      while ( ey1 != ey2 )
+      {
+        delta = lift;
+        mod  += rem;
+        if ( mod >= 0 )
+        {
+          mod -= dy;
+          delta++;
+        }
+
+        x2 = x + delta;
+        gray_render_scanline( RAS_VAR_ ey1, x, ONE_PIXEL - first, x2, first );
+        x = x2;
+
+        ey1 += incr;
+        gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
+      }
+    }
+
+    gray_render_scanline( RAS_VAR_ ey1, x, ONE_PIXEL - first, to_x, fy2 );
+
+  End:
+    ras.x       = to_x;
+    ras.y       = to_y;
+    ras.last_ey = SUBPIXELS( ey2 );
+  }
+
+
+  static void
+  gray_split_conic( FT_Vector*  base )
+  {
+    TPos  a, b;
+
+
+    base[4].x = base[2].x;
+    b = base[1].x;
+    a = base[3].x = ( base[2].x + b ) / 2;
+    b = base[1].x = ( base[0].x + b ) / 2;
+    base[2].x = ( a + b ) / 2;
+
+    base[4].y = base[2].y;
+    b = base[1].y;
+    a = base[3].y = ( base[2].y + b ) / 2;
+    b = base[1].y = ( base[0].y + b ) / 2;
+    base[2].y = ( a + b ) / 2;
+  }
+
+
+  static void
+  gray_render_conic( RAS_ARG_ FT_Vector*  control,
+                              FT_Vector*  to )
+  {
+    TPos        dx, dy;
+    int         top, level;
+    int*        levels;
+    FT_Vector*  arc;
+
+
+    dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
+    if ( dx < 0 )
+      dx = -dx;
+    dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
+    if ( dy < 0 )
+      dy = -dy;
+    if ( dx < dy )
+      dx = dy;
+
+    level = 1;
+    dx = dx / ras.conic_level;
+    while ( dx > 0 )
+    {
+      dx >>= 2;
+      level++;
+    }
+
+    /* a shortcut to speed things up */
+    if ( level <= 1 )
+    {
+      /* we compute the mid-point directly in order to avoid */
+      /* calling gray_split_conic()                          */
+      TPos   to_x, to_y, mid_x, mid_y;
+
+
+      to_x  = UPSCALE( to->x );
+      to_y  = UPSCALE( to->y );
+      mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
+      mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
+
+      gray_render_line( RAS_VAR_ mid_x, mid_y );
+      gray_render_line( RAS_VAR_ to_x, to_y );
+      return;
+    }
+
+    arc       = ras.bez_stack;
+    levels    = ras.lev_stack;
+    top       = 0;
+    levels[0] = level;
+
+    arc[0].x = UPSCALE( to->x );
+    arc[0].y = UPSCALE( to->y );
+    arc[1].x = UPSCALE( control->x );
+    arc[1].y = UPSCALE( control->y );
+    arc[2].x = ras.x;
+    arc[2].y = ras.y;
+
+    while ( top >= 0 )
+    {
+      level = levels[top];
+      if ( level > 1 )
+      {
+        /* check that the arc crosses the current band */
+        TPos  min, max, y;
+
+
+        min = max = arc[0].y;
+
+        y = arc[1].y;
+        if ( y < min ) min = y;
+        if ( y > max ) max = y;
+
+        y = arc[2].y;
+        if ( y < min ) min = y;
+        if ( y > max ) max = y;
+
+        if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
+          goto Draw;
+
+        gray_split_conic( arc );
+        arc += 2;
+        top++;
+        levels[top] = levels[top - 1] = level - 1;
+        continue;
+      }
+
+    Draw:
+      {
+        TPos  to_x, to_y, mid_x, mid_y;
+
+
+        to_x  = arc[0].x;
+        to_y  = arc[0].y;
+        mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
+        mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
+
+        gray_render_line( RAS_VAR_ mid_x, mid_y );
+        gray_render_line( RAS_VAR_ to_x, to_y );
+
+        top--;
+        arc -= 2;
+      }
+    }
+    return;
+  }
+
+
+  static void
+  gray_split_cubic( FT_Vector*  base )
+  {
+    TPos  a, b, c, d;
+
+
+    base[6].x = base[3].x;
+    c = base[1].x;
+    d = base[2].x;
+    base[1].x = a = ( base[0].x + c ) / 2;
+    base[5].x = b = ( base[3].x + d ) / 2;
+    c = ( c + d ) / 2;
+    base[2].x = a = ( a + c ) / 2;
+    base[4].x = b = ( b + c ) / 2;
+    base[3].x = ( a + b ) / 2;
+
+    base[6].y = base[3].y;
+    c = base[1].y;
+    d = base[2].y;
+    base[1].y = a = ( base[0].y + c ) / 2;
+    base[5].y = b = ( base[3].y + d ) / 2;
+    c = ( c + d ) / 2;
+    base[2].y = a = ( a + c ) / 2;
+    base[4].y = b = ( b + c ) / 2;
+    base[3].y = ( a + b ) / 2;
+  }
+
+
+  static void
+  gray_render_cubic( RAS_ARG_ FT_Vector*  control1,
+                              FT_Vector*  control2,
+                              FT_Vector*  to )
+  {
+    TPos        dx, dy, da, db;
+    int         top, level;
+    int*        levels;
+    FT_Vector*  arc;
+
+
+    dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
+    if ( dx < 0 )
+      dx = -dx;
+    dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
+    if ( dy < 0 )
+      dy = -dy;
+    if ( dx < dy )
+      dx = dy;
+    da = dx;
+
+    dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
+    if ( dx < 0 )
+      dx = -dx;
+    dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y );
+    if ( dy < 0 )
+      dy = -dy;
+    if ( dx < dy )
+      dx = dy;
+    db = dx;
+
+    level = 1;
+    da    = da / ras.cubic_level;
+    db    = db / ras.conic_level;
+    while ( da > 0 || db > 0 )
+    {
+      da >>= 2;
+      db >>= 3;
+      level++;
+    }
+
+    if ( level <= 1 )
+    {
+      TPos   to_x, to_y, mid_x, mid_y;
+
+
+      to_x  = UPSCALE( to->x );
+      to_y  = UPSCALE( to->y );
+      mid_x = ( ras.x + to_x +
+                3 * UPSCALE( control1->x + control2->x ) ) / 8;
+      mid_y = ( ras.y + to_y +
+                3 * UPSCALE( control1->y + control2->y ) ) / 8;
+
+      gray_render_line( RAS_VAR_ mid_x, mid_y );
+      gray_render_line( RAS_VAR_ to_x, to_y );
+      return;
+    }
+
+    arc      = ras.bez_stack;
+    arc[0].x = UPSCALE( to->x );
+    arc[0].y = UPSCALE( to->y );
+    arc[1].x = UPSCALE( control2->x );
+    arc[1].y = UPSCALE( control2->y );
+    arc[2].x = UPSCALE( control1->x );
+    arc[2].y = UPSCALE( control1->y );
+    arc[3].x = ras.x;
+    arc[3].y = ras.y;
+
+    levels    = ras.lev_stack;
+    top       = 0;
+    levels[0] = level;
+
+    while ( top >= 0 )
+    {
+      level = levels[top];
+      if ( level > 1 )
+      {
+        /* check that the arc crosses the current band */
+        TPos  min, max, y;
+
+
+        min = max = arc[0].y;
+        y = arc[1].y;
+        if ( y < min ) min = y;
+        if ( y > max ) max = y;
+        y = arc[2].y;
+        if ( y < min ) min = y;
+        if ( y > max ) max = y;
+        y = arc[3].y;
+        if ( y < min ) min = y;
+        if ( y > max ) max = y;
+        if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
+          goto Draw;
+        gray_split_cubic( arc );
+        arc += 3;
+        top ++;
+        levels[top] = levels[top - 1] = level - 1;
+        continue;
+      }
+
+    Draw:
+      {
+        TPos  to_x, to_y, mid_x, mid_y;
+
+
+        to_x  = arc[0].x;
+        to_y  = arc[0].y;
+        mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
+        mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
+
+        gray_render_line( RAS_VAR_ mid_x, mid_y );
+        gray_render_line( RAS_VAR_ to_x, to_y );
+        top --;
+        arc -= 3;
+      }
+    }
+    return;
+  }
+
+
+  /* a macro comparing two cell pointers.  Returns true if a <= b. */
+#if 1
+
+#define PACK( a )          ( ( (long)(a)->y << 16 ) + (a)->x )
+#define LESS_THAN( a, b )  ( PACK( a ) < PACK( b ) )
+
+#else /* 1 */
+
+#define LESS_THAN( a, b )  ( (a)->y < (b)->y || \
+                             ( (a)->y == (b)->y && (a)->x < (b)->x ) )
+
+#endif /* 1 */
+
+#define SWAP_CELLS( a, b, temp )  do             \
+                                  {              \
+                                    temp = *(a); \
+                                    *(a) = *(b); \
+                                    *(b) = temp; \
+                                  } while ( 0 )
+#define DEBUG_SORT
+#define QUICK_SORT
+
+#ifdef SHELL_SORT
+
+  /* a simple shell sort algorithm that works directly on our */
+  /* cells table                                              */
+  static void
+  gray_shell_sort ( PCell  cells,
+                    int    count )
+  {
+    PCell  i, j, limit = cells + count;
+    TCell  temp;
+    int    gap;
+
+
+    /* compute initial gap */
+    for ( gap = 0; ++gap < count; gap *= 3 )
+      ;
+
+    while ( gap /= 3 )
+    {
+      for ( i = cells + gap; i < limit; i++ )
+      {
+        for ( j = i - gap; ; j -= gap )
+        {
+          PCell  k = j + gap;
+
+
+          if ( LESS_THAN( j, k ) )
+            break;
+
+          SWAP_CELLS( j, k, temp );
+
+          if ( j < cells + gap )
+            break;
+        }
+      }
+    }
+  }
+
+#endif /* SHELL_SORT */
+
+
+#ifdef QUICK_SORT
+
+  /* This is a non-recursive quicksort that directly process our cells     */
+  /* array.  It should be faster than calling the stdlib qsort(), and we   */
+  /* can even tailor our insertion threshold...                            */
+
+#define QSORT_THRESHOLD  9  /* below this size, a sub-array will be sorted */
+                            /* through a normal insertion sort             */
+
+  static void
+  gray_quick_sort( PCell  cells,
+                   int    count )
+  {
+    PCell   stack[40];  /* should be enough ;-) */
+    PCell*  top;        /* top of stack */
+    PCell   base, limit;
+    TCell   temp;
+
+
+    limit = cells + count;
+    base  = cells;
+    top   = stack;
+
+    for (;;)
+    {
+      int    len = (int)( limit - base );
+      PCell  i, j, pivot;
+
+
+      if ( len > QSORT_THRESHOLD )
+      {
+        /* we use base + len/2 as the pivot */
+        pivot = base + len / 2;
+        SWAP_CELLS( base, pivot, temp );
+
+        i = base + 1;
+        j = limit - 1;
+
+        /* now ensure that *i <= *base <= *j */
+        if ( LESS_THAN( j, i ) )
+          SWAP_CELLS( i, j, temp );
+
+        if ( LESS_THAN( base, i ) )
+          SWAP_CELLS( base, i, temp );
+
+        if ( LESS_THAN( j, base ) )
+          SWAP_CELLS( base, j, temp );
+
+        for (;;)
+        {
+          do i++; while ( LESS_THAN( i, base ) );
+          do j--; while ( LESS_THAN( base, j ) );
+
+          if ( i > j )
+            break;
+
+          SWAP_CELLS( i, j, temp );
+        }
+
+        SWAP_CELLS( base, j, temp );
+
+        /* now, push the largest sub-array */
+        if ( j - base > limit - i )
+        {
+          top[0] = base;
+          top[1] = j;
+          base   = i;
+        }
+        else
+        {
+          top[0] = i;
+          top[1] = limit;
+          limit  = j;
+        }
+        top += 2;
+      }
+      else
+      {
+        /* the sub-array is small, perform insertion sort */
+        j = base;
+        i = j + 1;
+
+        for ( ; i < limit; j = i, i++ )
+        {
+          for ( ; LESS_THAN( j + 1, j ); j-- )
+          {
+            SWAP_CELLS( j + 1, j, temp );
+            if ( j == base )
+              break;
+          }
+        }
+        if ( top > stack )
+        {
+          top  -= 2;
+          base  = top[0];
+          limit = top[1];
+        }
+        else
+          break;
+      }
+    }
+  }
+
+#endif /* QUICK_SORT */
+
+
+#ifdef DEBUG_GRAYS
+#ifdef DEBUG_SORT
+
+  static int
+  gray_check_sort( PCell  cells,
+                   int    count )
+  {
+    PCell  p, q;
+
+
+    for ( p = cells + count - 2; p >= cells; p-- )
+    {
+      q = p + 1;
+      if ( !LESS_THAN( p, q ) )
+        return 0;
+    }
+    return 1;
+  }
+
+#endif /* DEBUG_SORT */
+#endif /* DEBUG_GRAYS */
+
+
+  static int
+  gray_move_to( FT_Vector*  to,
+                FT_Raster   raster )
+  {
+    TPos  x, y;
+
+
+    /* record current cell, if any */
+    gray_record_cell( (PRaster)raster );
+
+    /* start to a new position */
+    x = UPSCALE( to->x );
+    y = UPSCALE( to->y );
+    
+    gray_start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) );
+      
+    ((PRaster)raster)->x = x;
+    ((PRaster)raster)->y = y;
+    return 0;
+  }
+
+
+  static int
+  gray_line_to( FT_Vector*  to,
+                FT_Raster   raster )
+  {
+    gray_render_line( (PRaster)raster,
+                      UPSCALE( to->x ), UPSCALE( to->y ) );
+    return 0;
+  }
+
+
+  static int
+  gray_conic_to( FT_Vector*  control,
+                 FT_Vector*  to,
+                 FT_Raster   raster )
+  {
+    gray_render_conic( (PRaster)raster, control, to );
+    return 0;
+  }
+
+
+  static int
+  gray_cubic_to( FT_Vector*  control1,
+                 FT_Vector*  control2,
+                 FT_Vector*  to,
+                 FT_Raster   raster )
+  {
+    gray_render_cubic( (PRaster)raster, control1, control2, to );
+    return 0;
+  }
+
+
+  static void
+  gray_render_span( int       y,
+                    int       count,
+                    FT_Span*  spans,
+                    PRaster   raster )
+  {
+    unsigned char*  p;
+    FT_Bitmap*      map = &raster->target;
+
+
+    /* first of all, compute the scanline offset */
+    p = (unsigned char*)map->buffer - y * map->pitch;
+    if ( map->pitch >= 0 )
+      p += ( map->rows - 1 ) * map->pitch;
+
+    for ( ; count > 0; count--, spans++ )
+    {
+      if ( spans->coverage )
+#if 1
+        memset( p + spans->x, (unsigned char)spans->coverage, spans->len );
+#else /* 1 */
+      {
+        q     = p + spans->x;
+        limit = q + spans->len;
+        for ( ; q < limit; q++ )
+          q[0] = (unsigned char)spans->coverage;
+      }
+#endif /* 1 */
+    }
+  }
+
+
+#ifdef DEBUG_GRAYS
+
+#include <stdio.h>
+
+  static void
+  gray_dump_cells( RAS_ARG )
+  {
+    PCell  cell, limit;
+    int    y = -1;
+
+
+    cell  = ras.cells;
+    limit = cell + ras.num_cells;
+
+    for ( ; cell < limit; cell++ )
+    {
+      if ( cell->y != y )
+      {
+        fprintf( stderr, "\n%2d: ", cell->y );
+        y = cell->y;
+      }
+      fprintf( stderr, "[%d %d %d]",
+               cell->x, cell->area, cell->cover );
+    }
+    fprintf(stderr, "\n" );
+  }
+
+#endif /* DEBUG_GRAYS */
+
+
+  static void
+  gray_hline( RAS_ARG_ TScan  x,
+                       TScan  y,
+                       TPos   area,
+                       int    acount )
+  {
+    FT_Span*   span;
+    int        count;
+    int        coverage;
+
+
+    /* compute the coverage line's coverage, depending on the    */
+    /* outline fill rule                                         */
+    /*                                                           */
+    /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
+    /*                                                           */
+    coverage = area >> ( PIXEL_BITS * 2 + 1 - 8);  /* use range 0..256 */
+
+    if ( ras.outline.flags & ft_outline_even_odd_fill )
+    {
+      if ( coverage < 0 )
+        coverage = -coverage;
+
+      while ( coverage >= 512 )
+        coverage -= 512;
+
+      if ( coverage > 256 )
+        coverage = 512 - coverage;
+      else if ( coverage == 256 )
+        coverage = 255;
+    }
+    else
+    {
+      /* normal non-zero winding rule */
+      if ( coverage < 0 )
+        coverage = -coverage;
+
+      if ( coverage >= 256 )
+        coverage = 255;
+    }
+
+    y += ras.min_ey;
+    x += ras.min_ex;
+
+    if ( coverage )
+    {
+      /* see if we can add this span to the current list */
+      count = ras.num_gray_spans;
+      span  = ras.gray_spans + count - 1;
+      if ( count > 0                          &&
+           ras.span_y == y                    &&
+           (int)span->x + span->len == (int)x &&
+           span->coverage == coverage )
+      {
+        span->len = (unsigned short)( span->len + acount );
+        return;
+      }
+
+      if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
+      {
+        if ( ras.render_span && count > 0 )
+          ras.render_span( ras.span_y, count, ras.gray_spans,
+                           ras.render_span_data );
+        /* ras.render_span( span->y, ras.gray_spans, count ); */
+
+#ifdef DEBUG_GRAYS
+
+        if ( ras.span_y >= 0 )
+        {
+          int  n;
+
+
+          fprintf( stderr, "y=%3d ", ras.span_y );
+          span = ras.gray_spans;
+          for ( n = 0; n < count; n++, span++ )
+            fprintf( stderr, "[%d..%d]:%02x ",
+                     span->x, span->x + span->len - 1, span->coverage );
+          fprintf( stderr, "\n" );
+        }
+
+#endif /* DEBUG_GRAYS */
+
+        ras.num_gray_spans = 0;
+        ras.span_y         = y;
+
+        count = 0;
+        span  = ras.gray_spans;
+      }
+      else
+        span++;
+
+      /* add a gray span to the current list */
+      span->x        = (short)x;
+      span->len      = (unsigned short)acount;
+      span->coverage = (unsigned char)coverage;
+      ras.num_gray_spans++;
+    }
+  }
+
+
+  static void
+  gray_sweep( RAS_ARG_ FT_Bitmap*  target )
+  {
+    TScan  x, y, cover;
+    TArea  area;
+    PCell  start, cur, limit;
+
+    FT_UNUSED( target );
+
+    if ( ras.num_cells == 0 )
+      return;
+      
+    cur   = ras.cells;
+    limit = cur + ras.num_cells;
+
+    cover              = 0;
+    ras.span_y         = -1;
+    ras.num_gray_spans = 0;
+
+    for (;;)
+    {
+      start  = cur;
+      y      = start->y;
+      x      = start->x;
+
+      area   = start->area;
+      cover += start->cover;
+
+      /* accumulate all start cells */
+      for (;;)
+      {
+        ++cur;
+        if ( cur >= limit || cur->y != start->y || cur->x != start->x )
+          break;
+
+        area  += cur->area;
+        cover += cur->cover;
+      }
+
+      /* if the start cell has a non-null area, we must draw an */
+      /* individual gray pixel there                            */
+      if ( area && x >= 0 )
+      {
+        gray_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ) - area, 1 );
+        x++;
+      }
+
+      if ( x < 0 )
+        x = 0;
+
+      if ( cur < limit && start->y == cur->y )
+      {
+        /* draw a gray span between the start cell and the current one */
+        if ( cur->x > x )
+          gray_hline( RAS_VAR_ x, y,
+                       cover * ( ONE_PIXEL * 2 ), cur->x - x );
+      }
+      else
+      {
+        /* draw a gray span until the end of the clipping region */
+        if ( cover && x < ras.max_ex - ras.min_ex )
+          gray_hline( RAS_VAR_ x, y,
+                       cover * ( ONE_PIXEL * 2 ),
+                       ras.max_ex - x - ras.min_ex );
+        cover = 0;
+      }
+
+      if ( cur >= limit )
+        break;
+    }
+
+    if ( ras.render_span && ras.num_gray_spans > 0 )
+      ras.render_span( ras.span_y, ras.num_gray_spans,
+                       ras.gray_spans, ras.render_span_data );
+
+#ifdef DEBUG_GRAYS
+
+    {
+      int       n;
+      FT_Span*  span;
+
+
+      fprintf( stderr, "y=%3d ", ras.span_y );
+      span = ras.gray_spans;
+      for ( n = 0; n < ras.num_gray_spans; n++, span++ )
+        fprintf( stderr, "[%d..%d]:%02x ",
+                 span->x, span->x + span->len - 1, span->coverage );
+      fprintf( stderr, "\n" );
+    }
+
+#endif /* DEBUG_GRAYS */
+
+  }
+
+
+#ifdef _STANDALONE_
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  The following function should only compile in stand_alone mode,      */
+  /*  i.e., when building this component without the rest of FreeType.     */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Decompose                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Walks over an outline's structure to decompose it into individual  */
+  /*    segments and Bezier arcs.  This function is also able to emit      */
+  /*    `move to' and `close to' operations to indicate the start and end  */
+  /*    of new contours in the outline.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline   :: A pointer to the source target.                       */
+  /*                                                                       */
+  /*    interface :: A table of `emitters', i.e,. function pointers called */
+  /*                 during decomposition to indicate path operations.     */
+  /*                                                                       */
+  /*    user      :: A typeless pointer which is passed to each emitter    */
+  /*                 during the decomposition.  It can be used to store    */
+  /*                 the state during the decomposition.                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means sucess.                                       */
+  /*                                                                       */
+  static
+  int  FT_Outline_Decompose( FT_Outline*              outline,
+                             const FT_Outline_Funcs*  interface,
+                             void*                    user )
+  {
+#undef SCALED
+#if 0
+#define SCALED( x )  ( ( (x) << shift ) - delta )
+#else
+#define SCALED( x )  (x)
+#endif
+
+    FT_Vector   v_last;
+    FT_Vector   v_control;
+    FT_Vector   v_start;
+
+    FT_Vector*  point;
+    FT_Vector*  limit;
+    char*       tags;
+
+    int     n;         /* index of contour in outline     */
+    int     first;     /* index of first point in contour */
+    int     error;
+    char    tag;       /* current point's state           */
+
+#if 0
+    int     shift = interface->shift;
+    FT_Pos  delta = interface->delta;
+#endif
+
+
+    first = 0;
+
+    for ( n = 0; n < outline->n_contours; n++ )
+    {
+      int  last;  /* index of last point in contour */
+
+
+      last  = outline->contours[n];
+      limit = outline->points + last;
+
+      v_start = outline->points[first];
+      v_last  = outline->points[last];
+
+      v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
+      v_last.x  = SCALED( v_last.x );  v_last.y  = SCALED( v_last.y );
+
+      v_control = v_start;
+
+      point = outline->points + first;
+      tags  = outline->tags  + first;
+      tag   = FT_CURVE_TAG( tags[0] );
+
+      /* A contour cannot start with a cubic control point! */
+      if ( tag == FT_Curve_Tag_Cubic )
+        goto Invalid_Outline;
+
+      /* check first point to determine origin */
+      if ( tag == FT_Curve_Tag_Conic )
+      {
+        /* first point is conic control.  Yes, this happens. */
+        if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
+        {
+          /* start at last point if it is on the curve */
+          v_start = v_last;
+          limit--;
+        }
+        else
+        {
+          /* if both first and last points are conic,         */
+          /* start at their middle and record its position    */
+          /* for closure                                      */
+          v_start.x = ( v_start.x + v_last.x ) / 2;
+          v_start.y = ( v_start.y + v_last.y ) / 2;
+
+          v_last = v_start;
+        }
+        point--;
+        tags--;
+      }
+
+      error = interface->move_to( &v_start, user );
+      if ( error )
+        goto Exit;
+
+      while ( point < limit )
+      {
+        point++;
+        tags++;
+
+        tag = FT_CURVE_TAG( tags[0] );
+        switch ( tag )
+        {
+        case FT_Curve_Tag_On:  /* emit a single line_to */
+          {
+            FT_Vector  vec;
+
+
+            vec.x = SCALED( point->x );
+            vec.y = SCALED( point->y );
+
+            error = interface->line_to( &vec, user );
+            if ( error )
+              goto Exit;
+            continue;
+          }
+
+        case FT_Curve_Tag_Conic:  /* consume conic arcs */
+          {
+            v_control.x = SCALED( point->x );
+            v_control.y = SCALED( point->y );
+
+          Do_Conic:
+            if ( point < limit )
+            {
+              FT_Vector  vec;
+              FT_Vector  v_middle;
+
+
+              point++;
+              tags++;
+              tag = FT_CURVE_TAG( tags[0] );
+
+              vec.x = SCALED( point->x );
+              vec.y = SCALED( point->y );
+
+              if ( tag == FT_Curve_Tag_On )
+              {
+                error = interface->conic_to( &v_control, &vec, user );
+                if ( error )
+                  goto Exit;
+                continue;
+              }
+
+              if ( tag != FT_Curve_Tag_Conic )
+                goto Invalid_Outline;
+
+              v_middle.x = ( v_control.x + vec.x ) / 2;
+              v_middle.y = ( v_control.y + vec.y ) / 2;
+
+              error = interface->conic_to( &v_control, &v_middle, user );
+              if ( error )
+                goto Exit;
+
+              v_control = vec;
+              goto Do_Conic;
+            }
+
+            error = interface->conic_to( &v_control, &v_start, user );
+            goto Close;
+          }
+
+        default:  /* FT_Curve_Tag_Cubic */
+          {
+            FT_Vector  vec1, vec2;
+
+
+            if ( point + 1 > limit                             ||
+                 FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+              goto Invalid_Outline;
+
+            point += 2;
+            tags  += 2;
+
+            vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
+            vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
+
+            if ( point <= limit )
+            {
+              FT_Vector  vec;
+
+
+              vec.x = SCALED( point->x );
+              vec.y = SCALED( point->y );
+
+              error = interface->cubic_to( &vec1, &vec2, &vec, user );
+              if ( error )
+                goto Exit;
+              continue;
+            }
+
+            error = interface->cubic_to( &vec1, &vec2, &v_start, user );
+            goto Close;
+          }
+        }
+      }
+
+      /* close the contour with a line segment */
+      error = interface->line_to( &v_start, user );
+
+   Close:
+      if ( error )
+        goto Exit;
+
+      first = last + 1;
+    }
+
+    return 0;
+
+  Exit:
+    return error;
+
+  Invalid_Outline:
+    return ErrRaster_Invalid_Outline;
+  }
+
+#endif /* _STANDALONE_ */
+
+
+  typedef struct  TBand_
+  {
+    FT_Pos  min, max;
+
+  } TBand;
+
+
+  static int
+  gray_convert_glyph_inner( RAS_ARG )
+  {
+    static
+    const FT_Outline_Funcs  interface =
+    {
+      (FT_Outline_MoveTo_Func) gray_move_to,
+      (FT_Outline_LineTo_Func) gray_line_to,
+      (FT_Outline_ConicTo_Func)gray_conic_to,
+      (FT_Outline_CubicTo_Func)gray_cubic_to,
+      0,
+      0
+    };
+
+    volatile int  error = 0;
+    
+    if ( setjmp( ras.jump_buffer ) == 0 )
+    {
+      error = FT_Outline_Decompose( &ras.outline, &interface, &ras );
+      gray_record_cell( RAS_VAR );
+    }
+    else
+    {
+      error = ErrRaster_MemoryOverflow;
+    }
+
+    return error;
+  }
+
+
+  static int
+  gray_convert_glyph( RAS_ARG )
+  {
+    TBand     bands[40], *band;
+    int       n, num_bands;
+    TPos      min, max, max_y;
+    FT_BBox*  clip;
+
+
+    /* Set up state in the raster object */
+    gray_compute_cbox( RAS_VAR );
+
+    /* clip to target bitmap, exit if nothing to do */
+    clip = &ras.clip_box;
+    
+    if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax ||
+         ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax )
+      return 0;
+
+    if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin;
+    if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin;
+
+    if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax;
+    if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax;
+
+    /* simple heuristic used to speed-up the bezier decomposition -- see */
+    /* the code in gray_render_conic() and gray_render_cubic() for more  */
+    /* details                                                           */
+    ras.conic_level = 32;
+    ras.cubic_level = 16;
+
+    {
+      int level = 0;
+
+
+      if ( ras.max_ex > 24 || ras.max_ey > 24 )
+        level++;
+      if ( ras.max_ex > 120 || ras.max_ey > 120 )
+        level++;
+
+      ras.conic_level <<= level;
+      ras.cubic_level <<= level;
+    }
+
+    /* setup vertical bands */
+    num_bands = ( ras.max_ey - ras.min_ey ) / ras.band_size;
+    if ( num_bands == 0 )  num_bands = 1;
+    if ( num_bands >= 39 ) num_bands = 39;
+
+    ras.band_shoot = 0;
+
+    min   = ras.min_ey;
+    max_y = ras.max_ey;
+
+    for ( n = 0; n < num_bands; n++, min = max )
+    {
+      max = min + ras.band_size;
+      if ( n == num_bands - 1 || max > max_y )
+        max = max_y;
+
+      bands[0].min = min;
+      bands[0].max = max;
+      band         = bands;
+
+      while ( band >= bands )
+      {
+        FT_Pos  bottom, top, middle;
+        int     error;
+
+
+        ras.num_cells = 0;
+        ras.invalid   = 1;
+        ras.min_ey    = band->min;
+        ras.max_ey    = band->max;
+
+#if 1
+        error = gray_convert_glyph_inner( RAS_VAR );
+#else       
+        error = FT_Outline_Decompose( outline, &interface, &ras ) ||
+                gray_record_cell( RAS_VAR );
+#endif
+
+        if ( !error )
+        {
+#ifdef SHELL_SORT
+          gray_shell_sort( ras.cells, ras.num_cells );
+#else
+          gray_quick_sort( ras.cells, ras.num_cells );
+#endif
+
+#ifdef DEBUG_GRAYS
+          gray_check_sort( ras.cells, ras.num_cells );
+          gray_dump_cells( RAS_VAR );
+#endif
+
+          gray_sweep( RAS_VAR_  &ras.target );
+          band--;
+          continue;
+        }
+        else if ( error != ErrRaster_MemoryOverflow )
+          return 1;
+
+        /* render pool overflow, we will reduce the render band by half */
+        bottom = band->min;
+        top    = band->max;
+        middle = bottom + ( ( top - bottom ) >> 1 );
+
+        /* waoow! This is too complex for a single scanline, something */
+        /* must be really rotten here!                                 */
+        if ( middle == bottom )
+        {
+#ifdef DEBUG_GRAYS
+          fprintf( stderr, "Rotten glyph!\n" );
+#endif
+          return 1;
+        }
+
+        if ( bottom-top >= ras.band_size )
+          ras.band_shoot++;
+
+        band[1].min = bottom;
+        band[1].max = middle;
+        band[0].min = middle;
+        band[0].max = top;
+        band++;
+      }
+    }
+
+    if ( ras.band_shoot > 8 && ras.band_size > 16 )
+      ras.band_size = ras.band_size / 2;
+
+    return 0;
+  }
+
+
+  extern int
+  gray_raster_render( PRaster            raster,
+                      FT_Raster_Params*  params )
+  {
+    FT_Outline*  outline = (FT_Outline*)params->source;
+    FT_Bitmap*   target_map = params->target;
+
+
+    if ( !raster || !raster->cells || !raster->max_cells )
+      return -1;
+
+    /* return immediately if the outline is empty */
+    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+      return 0;
+
+    if ( !outline || !outline->contours || !outline->points )
+      return ErrRaster_Invalid_Outline;
+
+    if ( outline->n_points !=
+           outline->contours[outline->n_contours - 1] + 1 )
+      return ErrRaster_Invalid_Outline;
+
+    /* if direct mode is not set, we must have a target bitmap */
+    if ( ( params->flags & ft_raster_flag_direct ) == 0 &&
+         ( !target_map || !target_map->buffer )         )
+      return -1;
+
+    /* this version does not support monochrome rendering */
+    if ( !( params->flags & ft_raster_flag_aa ) )
+      return ErrRaster_Invalid_Mode;
+
+    /* compute clipping box */
+    if ( ( params->flags & ft_raster_flag_direct ) == 0 )
+    {
+      /* compute clip box from target pixmap */
+      ras.clip_box.xMin = 0;
+      ras.clip_box.yMin = 0;
+      ras.clip_box.xMax = target_map->width;
+      ras.clip_box.yMax = target_map->rows;
+    }
+    else if ( params->flags & ft_raster_flag_clip )
+    {
+      ras.clip_box = params->clip_box;
+    }
+    else
+    {
+      ras.clip_box.xMin = -32768L;
+      ras.clip_box.yMin = -32768L;
+      ras.clip_box.xMax =  32767L;
+      ras.clip_box.yMax =  32767L;
+    }
+
+    ras.outline   = *outline;
+    ras.num_cells = 0;
+    ras.invalid   = 1;
+
+    if ( target_map )
+      ras.target = *target_map;
+
+    ras.render_span      = (FT_Raster_Span_Func)gray_render_span;
+    ras.render_span_data = &ras;
+
+    if ( params->flags & ft_raster_flag_direct )
+    {
+      ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
+      ras.render_span_data = params->user;
+    }
+
+    return gray_convert_glyph( (PRaster)raster );
+  }
+
+
+  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+  /****                         a static object.                  *****/
+
+#ifdef _STANDALONE_
+
+  static int
+  gray_raster_new( void*       memory,
+                   FT_Raster*  araster )
+  {
+    static TRaster  the_raster;
+
+    FT_UNUSED( memory );
+
+
+    *araster = (FT_Raster)&the_raster;
+    memset( &the_raster, 0, sizeof ( the_raster ) );
+
+    return 0;
+  }
+
+
+  static void
+  gray_raster_done( FT_Raster  raster )
+  {
+    /* nothing */
+    FT_UNUSED( raster );
+  }
+
+#else /* _STANDALONE_ */
+
+  static int
+  gray_raster_new( FT_Memory   memory,
+                   FT_Raster*  araster )
+  {
+    FT_Error  error;
+    PRaster   raster;
+
+
+    *araster = 0;
+    if ( !ALLOC( raster, sizeof ( TRaster ) ) )
+    {
+      raster->memory = memory;
+      *araster = (FT_Raster)raster;
+    }
+
+    return error;
+  }
+
+
+  static void
+  gray_raster_done( FT_Raster  raster )
+  {
+    FT_Memory  memory = (FT_Memory)((PRaster)raster)->memory;
+
+
+    FREE( raster );
+  }
+
+#endif /* _STANDALONE_ */
+
+
+  static void
+  gray_raster_reset( FT_Raster    raster,
+                     const char*  pool_base,
+                     long         pool_size )
+  {
+    PRaster  rast = (PRaster)raster;
+
+
+    if ( raster && pool_base && pool_size >= 4096 )
+      gray_init_cells( rast, (char*)pool_base, pool_size );
+
+    rast->band_size  = ( pool_size / sizeof ( TCell ) ) / 8;
+  }
+
+
+  const FT_Raster_Funcs  ft_grays_raster =
+  {
+    ft_glyph_format_outline,
+
+    (FT_Raster_New_Func)      gray_raster_new,
+    (FT_Raster_Reset_Func)    gray_raster_reset,
+    (FT_Raster_Set_Mode_Func) 0,
+    (FT_Raster_Render_Func)   gray_raster_render,
+    (FT_Raster_Done_Func)     gray_raster_done
+  };
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftinit.c b/libraries/freetype-2.0.5/ftinit.c
new file mode 100644 (file)
index 0000000..e2f809d
--- /dev/null
@@ -0,0 +1,155 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftinit.c                                                               */
+/*                                                                         */
+/*    FreeType initialization layer (body).                                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  The purpose of this file is to implement the following two           */
+  /*  functions:                                                           */
+  /*                                                                       */
+  /*  FT_Add_Default_Modules():                                            */
+  /*     This function is used to add the set of default modules to a      */
+  /*     fresh new library object.  The set is taken from the header file  */
+  /*     `freetype/config/ftmodule.h'.  See the document `FreeType 2.0     */
+  /*     Build System' for more information.                               */
+  /*                                                                       */
+  /*  FT_Init_FreeType():                                                  */
+  /*     This function creates a system object for the current platform,   */
+  /*     builds a library out of it, then calls FT_Default_Drivers().      */
+  /*                                                                       */
+  /*  Note that even if FT_Init_FreeType() uses the implementation of the  */
+  /*  system object defined at build time, client applications are still   */
+  /*  able to provide their own `ftsystem.c'.                              */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_MODULE_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_init
+
+#undef  FT_USE_MODULE
+#ifdef __cplusplus
+#define FT_USE_MODULE( x )  extern "C" const FT_Module_Class*  x;
+#else
+#define FT_USE_MODULE( x )  extern const FT_Module_Class*  x;
+#endif
+
+
+#include FT_CONFIG_MODULES_H
+
+
+#undef  FT_USE_MODULE
+#define FT_USE_MODULE( x )  (const FT_Module_Class*)&x,
+
+  static
+  const FT_Module_Class*  const ft_default_modules[] =
+  {
+#include FT_CONFIG_MODULES_H
+    0
+  };
+
+
+  /* documentation is in ftmodule.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Add_Default_Modules( FT_Library  library )
+  {
+    FT_Error                       error;
+    const FT_Module_Class* const*  cur;
+
+
+    /* test for valid `library' delayed to FT_Add_Module() */
+
+    cur = ft_default_modules;
+    while ( *cur )
+    {
+      error = FT_Add_Module( library, *cur );
+      /* notify errors, but don't stop */
+      if ( error )
+      {
+        FT_ERROR(( "FT_Add_Default_Module: Cannot install `%s', error = %x\n",
+                   (*cur)->module_name, error ));
+      }
+      cur++;
+    }
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Init_FreeType( FT_Library  *alibrary )
+  {
+    FT_Error   error;
+    FT_Memory  memory;
+
+
+    /* First of all, allocate a new system object -- this function is part */
+    /* of the system-specific component, i.e. `ftsystem.c'.                */
+
+    memory = FT_New_Memory();
+    if ( !memory )
+    {
+      FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" ));
+      return FT_Err_Unimplemented_Feature;
+    }
+
+    /* build a library out of it, then fill it with the set of */
+    /* default drivers.                                        */
+
+    error = FT_New_Library( memory, alibrary );
+    if ( !error )
+      FT_Add_Default_Modules( *alibrary );
+
+    return error;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Done_FreeType( FT_Library  library )
+  {
+    if ( library )
+    {
+      FT_Memory  memory = library->memory;
+
+
+      /* Discard the library object */
+      FT_Done_Library( library );
+
+      /* discard memory manager */
+      FT_Done_Memory( memory );
+    }
+
+    return FT_Err_Ok;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftlist.c b/libraries/freetype-2.0.5/ftlist.c
new file mode 100644 (file)
index 0000000..b516918
--- /dev/null
@@ -0,0 +1,217 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftlist.c                                                               */
+/*                                                                         */
+/*    Generic list support for FreeType (body).                            */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  This file implements functions relative to list processing.  Its     */
+  /*  data structures are defined in `freetype/internal/ftlist.h'.         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_LIST_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_list
+
+
+  /* documentation is in ftlist.h */
+
+  FT_EXPORT_DEF( FT_ListNode )
+  FT_List_Find( FT_List  list,
+                void*    data )
+  {
+    FT_ListNode  cur;
+
+
+    cur = list->head;
+    while ( cur )
+    {
+      if ( cur->data == data )
+        return cur;
+
+      cur = cur->next;
+    }
+
+    return (FT_ListNode)0;
+  }
+
+
+  /* documentation is in ftlist.h */
+
+  FT_EXPORT_DEF( void )
+  FT_List_Add( FT_List      list,
+               FT_ListNode  node )
+  {
+    FT_ListNode  before = list->tail;
+
+
+    node->next = 0;
+    node->prev = before;
+
+    if ( before )
+      before->next = node;
+    else
+      list->head = node;
+
+    list->tail = node;
+  }
+
+
+  /* documentation is in ftlist.h */
+
+  FT_EXPORT_DEF( void )
+  FT_List_Insert( FT_List      list,
+                  FT_ListNode  node )
+  {
+    FT_ListNode  after = list->head;
+
+
+    node->next = after;
+    node->prev = 0;
+
+    if ( !after )
+      list->tail = node;
+    else
+      after->prev = node;
+
+    list->head = node;
+  }
+
+
+  /* documentation is in ftlist.h */
+
+  FT_EXPORT_DEF( void )
+  FT_List_Remove( FT_List      list,
+                  FT_ListNode  node )
+  {
+    FT_ListNode  before, after;
+
+
+    before = node->prev;
+    after  = node->next;
+
+    if ( before )
+      before->next = after;
+    else
+      list->head = after;
+
+    if ( after )
+      after->prev = before;
+    else
+      list->tail = before;
+  }
+
+
+  /* documentation is in ftlist.h */
+
+  FT_EXPORT_DEF( void )
+  FT_List_Up( FT_List      list,
+              FT_ListNode  node )
+  {
+    FT_ListNode  before, after;
+
+
+    before = node->prev;
+    after  = node->next;
+
+    /* check whether we are already on top of the list */
+    if ( !before )
+      return;
+
+    before->next = after;
+
+    if ( after )
+      after->prev = before;
+    else
+      list->tail = before;
+
+    node->prev       = 0;
+    node->next       = list->head;
+    list->head->prev = node;
+    list->head       = node;
+  }
+
+
+  /* documentation is in ftlist.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_List_Iterate( FT_List            list,
+                   FT_List_Iterator   iterator,
+                   void*              user )
+  {
+    FT_ListNode  cur   = list->head;
+    FT_Error     error = FT_Err_Ok;
+
+
+    while ( cur )
+    {
+      FT_ListNode  next = cur->next;
+
+
+      error = iterator( cur, user );
+      if ( error )
+        break;
+
+      cur = next;
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in ftlist.h */
+
+  FT_EXPORT_DEF( void )
+  FT_List_Finalize( FT_List             list,
+                    FT_List_Destructor  destroy,
+                    FT_Memory           memory,
+                    void*               user )
+  {
+    FT_ListNode  cur;
+
+
+    cur = list->head;
+    while ( cur )
+    {
+      FT_ListNode  next = cur->next;
+      void*        data = cur->data;
+
+
+      if ( destroy )
+        destroy( memory, data, user );
+
+      FREE( cur );
+      cur = next;
+    }
+
+    list->head = 0;
+    list->tail = 0;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftlru.c b/libraries/freetype-2.0.5/ftlru.c
new file mode 100644 (file)
index 0000000..2838847
--- /dev/null
@@ -0,0 +1,352 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftlru.c                                                                */
+/*                                                                         */
+/*    Simple LRU list-cache (body).                                        */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_INTERNAL_LRU_H
+#include FT_LIST_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "ftcerror.h"
+
+
+  static void
+  lru_build_free_list( FT_LruNode  nodes,
+                       FT_UInt     count,
+                       FT_List     free_list )
+  {
+    FT_LruNode  node  = nodes;
+    FT_LruNode  limit = node + count;
+
+
+    free_list->head = free_list->tail = 0;
+    for ( ; node < limit; node++ )
+      FT_List_Add( free_list, (FT_ListNode)node );
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Lru_New( const FT_Lru_Class*  clazz,
+              FT_UInt              max_elements,
+              FT_Pointer           user_data,
+              FT_Memory            memory,
+              FT_Bool              pre_alloc,
+              FT_Lru              *anlru )
+  {
+    FT_Error  error;
+    FT_Lru    lru;
+
+
+    if ( !anlru )
+      return FTC_Err_Invalid_Argument;
+
+    *anlru = 0;
+    if ( !ALLOC( lru, sizeof ( *lru ) ) )
+    {
+      if ( pre_alloc )
+      {
+        /* allocate static array of lru list nodes */
+        if ( ALLOC_ARRAY( lru->nodes, max_elements, FT_LruNodeRec ) )
+        {
+          FREE( lru );
+          goto Exit;
+        }
+
+        /* build the `free_nodes' list from the array */
+        lru_build_free_list( lru->nodes, max_elements, &lru->free_nodes );
+      }
+
+      /* initialize common fields */
+      lru->clazz        = (FT_Lru_Class*)clazz;
+      lru->max_elements = max_elements;
+      lru->memory       = memory;
+      lru->user_data    = user_data;
+
+      *anlru = lru;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Lru_Reset( FT_Lru  lru )
+  {
+    FT_ListNode    node;
+    FT_Lru_Class*  clazz;
+    FT_Memory      memory;
+
+
+    if ( !lru )
+      return;
+
+    node   = lru->elements.head;
+    clazz  = lru->clazz;
+    memory = lru->memory;
+
+    while ( node )
+    {
+      FT_ListNode  next = node->next;
+
+
+      clazz->done_element( lru, (FT_LruNode)node );
+      if ( !lru->nodes )
+        FREE( node );
+
+      node = next;
+    }
+
+    /* rebuild free list if necessary */
+    if ( lru->nodes )
+      lru_build_free_list( lru->nodes, lru->max_elements, &lru->free_nodes );
+
+    lru->elements.head = lru->elements.tail = 0;
+    lru->num_elements  = 0;
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Lru_Done( FT_Lru  lru )
+  {
+    FT_Memory  memory;
+
+
+    if ( !lru )
+      return;
+
+    memory = lru->memory;
+
+    FT_Lru_Reset( lru );
+
+    FREE( lru->nodes );
+    FREE( lru );
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Lru_Lookup_Node( FT_Lru       lru,
+                      FT_LruKey    key,
+                      FT_LruNode  *anode )
+  {
+    FT_Error       error = 0;
+    FT_ListNode    node;
+    FT_Lru_Class*  clazz;
+    FT_LruNode     found = 0;
+    FT_Memory      memory;
+
+
+    if ( !lru || !key || !anode )
+      return FTC_Err_Invalid_Argument;
+
+    node   = lru->elements.head;
+    clazz  = lru->clazz;
+    memory = lru->memory;
+
+    if ( clazz->compare_element )
+    {
+      for ( ; node; node = node->next )
+        if ( clazz->compare_element( (FT_LruNode)node, key ) )
+        {
+          found = (FT_LruNode)node;
+          break;
+        }
+    }
+    else
+    {
+      for ( ; node; node = node->next )
+        if ( ((FT_LruNode)node)->key == key )
+        {
+          found = (FT_LruNode)node;
+          break;
+        }
+    }
+
+    if ( found )
+    {
+      /* move element to top of list */
+      FT_List_Up( &lru->elements, node );
+    }
+    else
+    {
+      /* we haven't found the relevant element.  We will now try */
+      /* to create a new one.                                    */
+      if ( lru->num_elements >= lru->max_elements )
+      {
+        /* this lru list is full; we will now flush */
+        /* the oldest node                          */
+        FT_LruNode  lru_node;
+
+
+        node     = lru->elements.tail;
+        lru_node = (FT_LruNode)node;
+        found    = lru_node;
+
+        if ( clazz->flush_element )
+          error = clazz->flush_element( lru, lru_node, key );
+        else
+        {
+          clazz->done_element( lru, lru_node );
+          lru_node->key = key;
+          node->data    = 0;
+          error = clazz->init_element( lru, lru_node );
+        }
+
+        if ( !error )
+        {
+          /* now, move element to top of list */
+          FT_List_Up( &lru->elements, node );
+        }
+        else
+        {
+          /* in case of error, the node must be discarded */
+          FT_List_Remove( &lru->elements, node );
+          lru->num_elements--;
+
+          if ( lru->nodes )
+            FT_List_Insert( &lru->free_nodes, node );
+          else
+            FREE( lru_node );
+
+          found = 0;
+        }
+      }
+      else
+      {
+        FT_LruNode  lru_node;
+
+
+        /* create a new lru list node, then the element for it */
+        if ( lru->nodes )
+        {
+          node          = lru->free_nodes.head;
+          lru_node      = (FT_LruNode)node;
+          lru_node->key = key;
+
+          error = clazz->init_element( lru, lru_node );
+          if ( error )
+            goto Exit;
+
+          FT_List_Remove( &lru->free_nodes, node );
+        }
+        else
+        {
+          if ( ALLOC( lru_node, sizeof ( *lru_node ) ) )
+            goto Exit;
+
+          lru_node->key = key;
+          error = clazz->init_element( lru, lru_node );
+          if ( error )
+          {
+            FREE( lru_node );
+            goto Exit;
+          }
+        }
+
+        found = lru_node;
+        node  = (FT_ListNode)lru_node;
+        FT_List_Insert( &lru->elements, node );
+        lru->num_elements++;
+      }
+    }
+
+  Exit:
+    *anode = found;
+    return error;
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Lru_Lookup( FT_Lru       lru,
+                 FT_LruKey    key,
+                 FT_Pointer  *anobject )
+  {
+    FT_Error    error;
+    FT_LruNode  node;
+
+
+    /* check for valid `lru' and `key' delayed to FT_Lru_Lookup_Node() */
+
+    if ( !anobject )
+      return FTC_Err_Invalid_Argument;
+
+    *anobject = 0;
+    error = FT_Lru_Lookup_Node( lru, key, &node );
+    if ( !error )
+      *anobject = node->root.data;
+
+    return error;
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Lru_Remove_Node( FT_Lru      lru,
+                      FT_LruNode  node )
+  {
+    if ( !lru || !node )
+      return;
+
+    if ( lru->num_elements > 0 )
+    {
+      FT_List_Remove( &lru->elements, (FT_ListNode)node );
+      lru->clazz->done_element( lru, node );
+
+      if ( lru->nodes )
+        FT_List_Insert( &lru->free_nodes, (FT_ListNode)node );
+      else
+      {
+        FT_Memory  memory = lru->memory;
+
+
+        FREE( node );
+      }
+
+      lru->num_elements--;
+    }
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Lru_Remove_Selection( FT_Lru           lru,
+                           FT_Lru_Selector  selector,
+                           FT_Pointer       data )
+  {
+    if ( !lru || !selector )
+      return;
+
+    if ( lru->num_elements > 0 )
+    {
+      FT_ListNode  node = lru->elements.head;
+      FT_ListNode  next;
+
+
+      while ( node )
+      {
+        next = node->next;
+        if ( selector( lru, (FT_LruNode)node, data ) )
+        {
+          /* remove this element from the list, and destroy it */
+          FT_Lru_Remove_Node( lru, (FT_LruNode)node );
+        }
+        node = next;
+      }
+    }
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftmac.c b/libraries/freetype-2.0.5/ftmac.c
new file mode 100644 (file)
index 0000000..005ae4f
--- /dev/null
@@ -0,0 +1,711 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmac.c                                                                */
+/*                                                                         */
+/*    Mac FOND support.  Written by just@letterror.com.                    */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.     */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*
+    Notes
+
+    Mac suitcase files can (and often do!) contain multiple fonts. To
+    support this I use the face_index argument of FT_(Open|New)_Face()
+    functions, and pretend the suitcase file is a collection.
+    Warning: although the FOND driver sets face->num_faces field to the
+    number of available fonts, but the Type 1 driver sets it to 1 anyway.
+    So this field is currently not reliable, and I don't see a clean way
+    to  resolve that. The face_index argument translates to
+      Get1IndResource( 'FOND', face_index + 1 );
+    so clients should figure out the resource index of the FOND.
+    (I'll try to provide some example code for this at some point.)
+
+
+    The Mac FOND support works roughly like this:
+
+    - Check whether the offered stream points to a Mac suitcase file.
+      This is done by checking the file type: it has to be 'FFIL' or 'tfil'.
+      The stream that gets passed to our init_face() routine is a stdio
+      stream, which isn't usable for us, since the FOND resources live
+      in the resource fork. So we just grab the stream->pathname field.
+
+    - Read the FOND resource into memory, then check whether there is
+      a TrueType font and/or (!) a Type 1 font available.
+
+    - If there is a Type 1 font available (as a separate 'LWFN' file),
+      read its data into memory, massage it slightly so it becomes
+      PFB data, wrap it into a memory stream, load the Type 1 driver
+      and delegate the rest of the work to it by calling FT_Open_Face().
+      (XXX TODO: after this has been done, the kerning data from the FOND
+      resource should be appended to the face: on the Mac there are usually
+      no AFM files available. However, this is tricky since we need to map
+      Mac char codes to ps glyph names to glyph ID's...)
+
+    - If there is a TrueType font (an 'sfnt' resource), read it into
+      memory, wrap it into a memory stream, load the TrueType driver
+      and delegate the rest of the work to it, by calling FT_Open_Face().
+  */
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_STREAM_H
+#include "truetype/ttobjs.h"
+#include "type1/t1objs.h"
+
+#include <Resources.h>
+#include <Fonts.h>
+#include <Errors.h>
+
+#include <ctype.h>  /* for isupper() and isalnum() */
+
+#include FT_MAC_H
+
+
+
+  /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
+     TrueType in case *both* are available (this is not common,
+     but it *is* possible). */
+#ifndef PREFER_LWFN
+#define PREFER_LWFN 1
+#endif
+
+
+
+  /* Quick'n'dirty Pascal string to C string converter.
+     Warning: this call is not thread safe! Use with caution. */
+  static char*
+  p2c_str( unsigned char*  pstr )
+  {
+    static char  cstr[256];
+
+
+    strncpy( cstr, (char*)pstr + 1, pstr[0] );
+    cstr[pstr[0]] = '\0';
+    return cstr;
+  }
+
+
+  /* Given a pathname, fill in a file spec. */
+  static int
+  file_spec_from_path( const char*  pathname,
+                       FSSpec*      spec )
+  {
+    Str255    p_path;
+    FT_ULong  path_len;
+
+
+    /* convert path to a pascal string */
+    path_len = strlen( pathname );
+    if ( path_len > 255 )
+      return -1;
+    p_path[0] = (unsigned char)path_len;
+    strncpy( (char*)p_path + 1, pathname, path_len );
+
+    if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr )
+      return -1;
+    else
+      return 0;
+  }
+
+
+  /* Return the file type of the file specified by spec. */
+  static OSType
+  get_file_type( FSSpec*  spec )
+  {
+    FInfo  finfo;
+
+
+    if ( FSpGetFInfo( spec, &finfo ) != noErr )
+      return 0;  /* file might not exist */
+
+    return finfo.fdType;
+  }
+
+
+  /* Given a PostScript font name, create the Macintosh LWFN file name. */
+  static void
+  create_lwfn_name( char*   ps_name,
+                    Str255  lwfn_file_name )
+  {
+    int       max = 5, count = 0;
+    FT_Byte*  p = lwfn_file_name;
+    FT_Byte*  q = (FT_Byte*)ps_name;
+
+
+    lwfn_file_name[0] = 0;
+
+    while ( *q )
+    {
+      if ( isupper( *q ) )
+      {
+        if ( count )
+          max = 3;
+        count = 0;
+      }
+      if ( count < max && ( isalnum( *q ) || *q == '_' ) )
+      {
+        *++p = *q;
+        lwfn_file_name[0]++;
+        count++;
+      }
+      q++;
+    }
+  }
+
+
+  /* Given a file reference, answer its location as a vRefNum
+     and a dirID. */
+  static FT_Error
+  get_file_location( short           ref_num,
+                     short*          v_ref_num,
+                     long*           dir_id,
+                     unsigned char*  file_name )
+  {
+    FCBPBRec  pb;
+    OSErr     error;
+
+    pb.ioNamePtr = file_name;
+    pb.ioVRefNum = 0;
+    pb.ioRefNum  = ref_num;
+    pb.ioFCBIndx = 0;
+
+
+    error = PBGetFCBInfoSync( &pb );
+    if ( error == noErr )
+    {
+      *v_ref_num = pb.ioFCBVRefNum;
+      *dir_id    = pb.ioFCBParID;
+    }
+    return error;
+  }
+
+
+  /* Make a file spec for an LWFN file from a FOND resource and
+     a file name. */
+  static FT_Error
+  make_lwfn_spec( Handle          fond,
+                  unsigned char*  file_name,
+                  FSSpec*         spec )
+  {
+    FT_Error  error;
+    short     ref_num, v_ref_num;
+    long      dir_id;
+    Str255    fond_file_name;
+
+
+    ref_num = HomeResFile( fond );
+
+    error = ResError();
+    if ( !error )
+      error = get_file_location( ref_num, &v_ref_num,
+                                 &dir_id, fond_file_name );
+    if ( !error )
+      error = FSMakeFSSpec( v_ref_num, dir_id, file_name, spec );
+
+    return error;
+  }
+
+
+  /* Look inside the FOND data, answer whether there should be an SFNT
+     resource, and answer the name of a possible LWFN Type 1 file. */
+  static void
+  parse_fond( char*   fond_data,
+              short*  have_sfnt,
+              short*  sfnt_id,
+              Str255  lwfn_file_name )
+  {
+    AsscEntry*  assoc;
+    FamRec*     fond;
+
+
+    *sfnt_id          = 0;
+    *have_sfnt        = 0;
+    lwfn_file_name[0] = 0;
+
+    fond = (FamRec*)fond_data;
+    assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
+
+    if ( assoc->fontSize == 0 )
+    {
+      *have_sfnt = 1;
+      *sfnt_id = assoc->fontID;
+    }
+
+    if ( fond->ffStylOff )
+    {
+      unsigned char*  p = (unsigned char*)fond_data;
+      StyleTable*     style;
+      unsigned short  string_count;
+      unsigned char*  name_table = 0;
+      char            ps_name[256];
+      unsigned char*  names[64];
+      int             i;
+
+
+      p += fond->ffStylOff;
+      style = (StyleTable*)p;
+      p += sizeof ( StyleTable );
+      string_count = *(unsigned short*)(p);
+      p += sizeof ( short );
+
+      for ( i = 0 ; i < string_count && i < 64; i++ )
+      {
+        names[i] = p;
+        p += names[i][0];
+        p++;
+      }
+      strcpy( ps_name, p2c_str( names[0] ) );  /* Family name */
+
+      if ( style->indexes[0] > 1 )
+      {
+        unsigned char*  suffixes = names[style->indexes[0] - 1];
+
+
+        for ( i=1; i<=suffixes[0]; i++ )
+          strcat( ps_name, p2c_str( names[suffixes[i] - 1 ] ) );
+      }
+      create_lwfn_name( ps_name, lwfn_file_name );
+    }
+  }
+
+
+  /* Read Type 1 data from the POST resources inside the LWFN file,
+     return a PFB buffer. This is somewhat convoluted because the FT2
+     PFB parser wants the ASCII header as one chunk, and the LWFN
+     chunks are often not organized that way, so we'll glue chunks
+     of the same type together. */
+  static FT_Error
+  read_lwfn( FT_Memory  memory,
+             FSSpec*    lwfn_spec,
+             FT_Byte**  pfb_data,
+             FT_ULong*  size )
+  {
+    FT_Error       error = FT_Err_Ok;
+    short          res_ref, res_id;
+    unsigned char  *buffer, *p, *size_p;
+    FT_ULong       total_size = 0;
+    FT_ULong       post_size, pfb_chunk_size;
+    Handle         post_data;
+    char           code, last_code;
+
+
+    res_ref = FSpOpenResFile( lwfn_spec, fsRdPerm );
+    if ( ResError() )
+      return FT_Err_Out_Of_Memory;
+    UseResFile( res_ref );
+
+    /* First pass: load all POST resources, and determine the size of
+       the output buffer. */
+    res_id = 501;
+    last_code = -1;
+
+    for (;;)
+    {
+      post_data = Get1Resource( 'POST', res_id++ );
+      if ( post_data == NULL )
+        break;  /* we're done */
+
+      code = (*post_data)[0];
+
+      if ( code != last_code )
+      {
+        if ( code == 5 )
+          total_size += 2; /* just the end code */
+        else
+          total_size += 6; /* code + 4 bytes chunk length */
+      }
+
+      total_size += GetHandleSize( post_data ) - 2;
+      last_code = code;
+    }
+
+    if ( ALLOC( buffer, (FT_Long)total_size ) )
+      goto Error;
+
+    /* Second pass: append all POST data to the buffer, add PFB fields.
+       Glue all consecutive chunks of the same type together. */
+    p = buffer;
+    res_id = 501;
+    last_code = -1;
+    pfb_chunk_size = 0;
+
+    for (;;)
+    {
+      post_data = Get1Resource( 'POST', res_id++ );
+      if ( post_data == NULL )
+        break;  /* we're done */
+
+      post_size = (FT_ULong)GetHandleSize( post_data ) - 2;
+      code = (*post_data)[0];
+
+      if ( code != last_code )
+      {
+
+        if ( last_code != -1 )
+        {
+          /* we're done adding a chunk, fill in the size field */
+          *size_p++ = (FT_Byte)(   pfb_chunk_size         & 0xFF );
+          *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8  ) & 0xFF );
+          *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF );
+          *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF );
+          pfb_chunk_size = 0;
+        }
+
+        *p++ = 0x80;
+        if ( code == 5 )
+          *p++ = 0x03;  /* the end */
+        else if ( code == 2 )
+          *p++ = 0x02;  /* binary segment */
+        else
+          *p++ = 0x01;  /* ASCII segment */
+
+        if ( code != 5 )
+        {
+          size_p = p;   /* save for later */
+          p += 4;       /* make space for size field */
+        }
+      }
+
+      memcpy( p, *post_data + 2, post_size );
+      pfb_chunk_size += post_size;
+      p += post_size;
+      last_code = code;
+    }
+
+    *pfb_data = buffer;
+    *size = total_size;
+
+  Error:
+    CloseResFile( res_ref );
+    return error;
+  }
+
+
+  /* Finalizer for a memory stream; gets called by FT_Done_Face().
+     It frees the memory it uses. */
+  static void
+  memory_stream_close( FT_Stream  stream )
+  {
+    FT_Memory  memory = stream->memory;
+
+
+    FREE( stream->base );
+
+    stream->size  = 0;
+    stream->base  = 0;
+    stream->close = 0;
+  }
+
+
+  /* Create a new memory stream from a buffer and a size. */
+  static FT_Error
+  new_memory_stream( FT_Library       library,
+                     FT_Byte*         base,
+                     FT_ULong         size,
+                     FT_Stream_Close  close,
+                     FT_Stream*       astream )
+  {
+      FT_Error   error;
+      FT_Memory  memory;
+      FT_Stream  stream;
+
+
+      if ( !library )
+        return FT_Err_Invalid_Library_Handle;
+
+      if ( !base )
+        return FT_Err_Invalid_Argument;
+
+      *astream = 0;
+      memory = library->memory;
+      if ( ALLOC( stream, sizeof ( *stream ) ) )
+        goto Exit;
+
+      FT_New_Memory_Stream( library,
+                            base,
+                            size,
+                            stream );
+
+      stream->close = close;
+
+      *astream = stream;
+
+    Exit:
+      return error;
+  }
+
+
+  /* Create a new FT_Face given a buffer and a driver name. */
+  static FT_Error
+  open_face_from_buffer( FT_Library  library,
+                         FT_Byte*    base,
+                         FT_ULong    size,
+                         FT_Long     face_index,
+                         char*       driver_name,
+                         FT_Face*    aface )
+  {
+    FT_Open_Args  args;
+    FT_Error      error;
+    FT_Stream     stream;
+    FT_Memory     memory = library->memory;
+
+
+    error = new_memory_stream( library,
+                               base,
+                               size,
+                               memory_stream_close,
+                               &stream );
+    if ( error )
+    {
+      FREE( base );
+      return error;
+    }
+
+    args.flags = ft_open_stream;
+    args.stream = stream;
+    if ( driver_name )
+    {
+      args.flags = args.flags | ft_open_driver;
+      args.driver = FT_Get_Module( library, driver_name );
+    }
+
+    error = FT_Open_Face( library, &args, face_index, aface );
+    if ( error == FT_Err_Ok )
+      (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
+    else
+    {
+      FT_Done_Stream( stream );
+      FREE( stream );
+    }
+    return error;
+  }
+
+
+  /* Create a new FT_Face from a file spec to an LWFN file. */
+  static FT_Error
+  FT_New_Face_From_LWFN( FT_Library  library,
+                         FSSpec*     spec,
+                         FT_Long     face_index,
+                         FT_Face*    aface )
+  {
+    FT_Byte*   pfb_data;
+    FT_ULong   pfb_size;
+    FT_Error   error;
+    FT_Memory  memory = library->memory;
+
+
+    error = read_lwfn( library->memory, spec, &pfb_data, &pfb_size );
+    if ( error )
+      return error;
+
+#if 0
+    {
+      FILE*  f;
+      char*  path;
+
+
+      path = p2c_str( spec->name );
+      strcat( path, ".PFB" );
+      f = fopen( path, "wb" );
+      if ( f )
+      {
+        fwrite( pfb_data, 1, pfb_size, f );
+        fclose( f );
+      }
+    }
+#endif
+
+    return open_face_from_buffer( library,
+                                  pfb_data,
+                                  pfb_size,
+                                  face_index,
+                                  "type1",
+                                  aface );
+  }
+
+
+  /* Create a new FT_Face from an SFNT resource, specified by res ID. */
+  static FT_Error
+  FT_New_Face_From_SFNT( FT_Library  library,
+                         short       sfnt_id,
+                         FT_Long     face_index,
+                         FT_Face*    aface )
+  {
+    Handle     sfnt = NULL;
+    FT_Byte*   sfnt_data;
+    size_t     sfnt_size;
+    FT_Stream  stream = NULL;
+    FT_Error   error = 0;
+    FT_Memory  memory = library->memory;
+
+
+    sfnt = GetResource( 'sfnt', sfnt_id );
+    if ( ResError() )
+      return FT_Err_Invalid_Handle;
+
+    sfnt_size = (FT_ULong)GetHandleSize( sfnt );
+    if ( ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
+    {
+      ReleaseResource( sfnt );
+      return error;
+    }
+
+    HLock( sfnt );
+    memcpy( sfnt_data, *sfnt, sfnt_size );
+    HUnlock( sfnt );
+    ReleaseResource( sfnt );
+
+    return open_face_from_buffer( library,
+                                  sfnt_data,
+                                  sfnt_size,
+                                  face_index,
+                                  "truetype",
+                                  aface );
+  }
+
+
+  /* Create a new FT_Face from a file spec to a suitcase file. */
+  static FT_Error
+  FT_New_Face_From_Suitcase( FT_Library  library,
+                             FSSpec*     spec,
+                             FT_Long     face_index,
+                             FT_Face*    aface )
+  {
+    FT_Error  error = FT_Err_Ok;
+    short     res_ref, res_index;
+    Handle    fond;
+
+
+    res_ref = FSpOpenResFile( spec, fsRdPerm );
+    if ( ResError() )
+      return FT_Err_Cannot_Open_Resource;
+    UseResFile( res_ref );
+
+    /* face_index may be -1, in which case we
+       just need to do a sanity check */
+    if ( face_index < 0 )
+      res_index = 1;
+    else
+    {
+      res_index = (short)( face_index + 1 );
+      face_index = 0;
+    }
+    fond = Get1IndResource( 'FOND', res_index );
+    if ( ResError() )
+    {
+      error = FT_Err_Cannot_Open_Resource;
+      goto Error;
+    }
+
+    error = FT_New_Face_From_FOND( library, fond, face_index, aface );
+
+  Error:
+    CloseResFile( res_ref );
+    return error;
+  }
+
+
+  /* documentation in ftmac.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_New_Face_From_FOND( FT_Library  library,
+                         Handle      fond,
+                         FT_Long     face_index,
+                         FT_Face    *aface )
+  {
+    short     sfnt_id, have_sfnt, have_lwfn = 0;
+    Str255    lwfn_file_name;
+    short     fond_id;
+    OSType    fond_type;
+    Str255    fond_name;
+    FSSpec    lwfn_spec;
+    FT_Error  error = FT_Err_Unknown_File_Format;
+
+
+    GetResInfo(fond, &fond_id, &fond_type, fond_name);
+    if ( ResError() != noErr || fond_type != 'FOND' )
+      return FT_Err_Invalid_File_Format;
+
+    HLock( fond );
+    parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name );
+    HUnlock( fond );
+
+    if ( lwfn_file_name[0] )
+    {
+      if ( make_lwfn_spec( fond, lwfn_file_name, &lwfn_spec ) == FT_Err_Ok )
+        have_lwfn = 1;  /* yeah, we got one! */
+      else
+        have_lwfn = 0;  /* no LWFN file found */
+    }
+
+    if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) )
+      return FT_New_Face_From_LWFN( library,
+                                    &lwfn_spec,
+                                    face_index,
+                                    aface );
+    else if ( have_sfnt )
+      return FT_New_Face_From_SFNT( library,
+                                    sfnt_id,
+                                    face_index,
+                                    aface );
+
+    return FT_Err_Unknown_File_Format;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Face                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This is the Mac-specific implementation of FT_New_Face.  In        */
+  /*    addition to the standard FT_New_Face() functionality, it also      */
+  /*    accepts pathnames to Mac suitcase files.  For further              */
+  /*    documentation see the original FT_New_Face() in freetype.h.        */
+  /*                                                                       */
+  FT_EXPORT_DEF( FT_Error )
+  FT_New_Face( FT_Library   library,
+               const char*  pathname,
+               FT_Long      face_index,
+               FT_Face     *aface )
+  {
+    FT_Open_Args  args;
+    FSSpec        spec;
+    OSType        file_type;
+
+
+    /* test for valid `library' and `aface' delayed to FT_Open_Face() */
+    if ( !pathname )
+      return FT_Err_Invalid_Argument;
+
+    if ( file_spec_from_path( pathname, &spec ) )
+      return FT_Err_Invalid_Argument;
+
+    file_type = get_file_type( &spec );
+    if ( file_type == 'FFIL' || file_type == 'tfil' )
+      return FT_New_Face_From_Suitcase( library, &spec, face_index, aface );
+    else if ( file_type == 'LWFN' )
+      return FT_New_Face_From_LWFN( library, &spec, face_index, aface );
+    else
+    {
+      args.flags    = ft_open_pathname;
+      args.pathname = (char*)pathname;
+
+      return FT_Open_Face( library, &args, face_index, aface );
+    }
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftmm.c b/libraries/freetype-2.0.5/ftmm.c
new file mode 100644 (file)
index 0000000..229a043
--- /dev/null
@@ -0,0 +1,126 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmm.c                                                                 */
+/*                                                                         */
+/*    Multiple Master font support (body).                                 */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_MULTIPLE_MASTERS_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_mm
+
+
+  /* documentation is in ftmm.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_Multi_Master( FT_Face           face,
+                       FT_Multi_Master  *amaster )
+  {
+    FT_Error  error;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    error = FT_Err_Invalid_Argument;
+
+    if ( FT_HAS_MULTIPLE_MASTERS( face ) )
+    {
+      FT_Driver       driver = face->driver;
+      FT_Get_MM_Func  func;
+
+
+      func = (FT_Get_MM_Func)driver->root.clazz->get_interface(
+                               FT_MODULE( driver ), "get_mm" );
+      if ( func )
+        error = func( face, amaster );
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in ftmm.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Set_MM_Design_Coordinates( FT_Face   face,
+                                FT_UInt   num_coords,
+                                FT_Long*  coords )
+  {
+    FT_Error  error;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    error = FT_Err_Invalid_Argument;
+
+    if ( FT_HAS_MULTIPLE_MASTERS( face ) )
+    {
+      FT_Driver              driver = face->driver;
+      FT_Set_MM_Design_Func  func;
+
+
+      func = (FT_Set_MM_Design_Func)driver->root.clazz->get_interface(
+                                      FT_MODULE( driver ), "set_mm_design" );
+      if ( func )
+        error = func( face, num_coords, coords );
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in ftmm.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Set_MM_Blend_Coordinates( FT_Face    face,
+                               FT_UInt    num_coords,
+                               FT_Fixed*  coords )
+  {
+    FT_Error  error;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    error = FT_Err_Invalid_Argument;
+
+    if ( FT_HAS_MULTIPLE_MASTERS( face ) )
+    {
+      FT_Driver             driver = face->driver;
+      FT_Set_MM_Blend_Func  func;
+
+
+      func = (FT_Set_MM_Blend_Func)driver->root.clazz->get_interface(
+                                     FT_MODULE( driver ), "set_mm_blend" );
+      if ( func )
+        error = func( face, num_coords, coords );
+    }
+
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftnames.c b/libraries/freetype-2.0.5/ftnames.c
new file mode 100644 (file)
index 0000000..d38d2d5
--- /dev/null
@@ -0,0 +1,77 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftnames.c                                                              */
+/*                                                                         */
+/*    Simple interface to access SFNT name tables (which are used          */
+/*    to hold font names, copyright info, notices, etc.) (body).           */
+/*                                                                         */
+/*    This is _not_ used to retrieve glyph names!                          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_SFNT_NAMES_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+#ifdef TT_CONFIG_OPTION_SFNT_NAMES
+
+
+  /* documentation is in ftnames.h */
+
+  FT_EXPORT_DEF( FT_UInt )
+  FT_Get_Sfnt_Name_Count( FT_Face  face )
+  {
+    return (face && FT_IS_SFNT( face )) ? ((TT_Face)face)->num_names : 0;
+  }
+
+
+  /* documentation is in ftnames.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_Sfnt_Name( FT_Face       face,
+                    FT_UInt       index,
+                    FT_SfntName  *aname )
+  {
+    FT_Error  error = FT_Err_Invalid_Argument;
+
+
+    if ( aname && face && FT_IS_SFNT( face ) )
+    {
+      TT_Face  ttface = (TT_Face)face;
+
+
+      if ( index < (FT_UInt)ttface->num_names )
+      {
+        TT_NameRec*  name = ttface->name_table.names + index;
+
+
+        aname->platform_id = name->platformID;
+        aname->encoding_id = name->encodingID;
+        aname->language_id = name->languageID;
+        aname->name_id     = name->nameID;
+        aname->string      = (FT_Byte*)name->string;
+        aname->string_len  = name->stringLength;
+
+        error = FT_Err_Ok;
+      }
+    }
+
+    return error;
+  }
+
+
+#endif /* TT_CONFIG_OPTION_SFNT_NAMES */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftobjs.c b/libraries/freetype-2.0.5/ftobjs.c
new file mode 100644 (file)
index 0000000..b4ec9b6
--- /dev/null
@@ -0,0 +1,2660 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftobjs.c                                                               */
+/*                                                                         */
+/*    The FreeType private base classes (body).                            */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_LIST_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TABLES_H
+
+#include <string.h>     /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                           M E M O R Y                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_memory
+
+
+  /* documentation is in ftmemory.h */
+
+  FT_BASE_DEF( FT_Error )
+  FT_Alloc( FT_Memory  memory,
+            FT_Long    size,
+            void*     *P )
+  {
+    FT_Assert( P != 0 );
+
+    if ( size > 0 )
+    {
+      *P = memory->alloc( memory, size );
+      if ( !*P )
+      {
+        FT_ERROR(( "FT_Alloc:" ));
+        FT_ERROR(( " Out of memory? (%ld requested)\n",
+                   size ));
+
+        return FT_Err_Out_Of_Memory;
+      }
+      MEM_Set( *P, 0, size );
+    }
+    else
+      *P = NULL;
+
+    FT_TRACE7(( "FT_Alloc:" ));
+    FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
+                size, *P, P ));
+
+    return FT_Err_Ok;
+  }
+
+
+  /* documentation is in ftmemory.h */
+
+  FT_BASE_DEF( FT_Error )
+  FT_Realloc( FT_Memory  memory,
+              FT_Long    current,
+              FT_Long    size,
+              void**     P )
+  {
+    void*  Q;
+
+
+    FT_Assert( P != 0 );
+
+    /* if the original pointer is NULL, call FT_Alloc() */
+    if ( !*P )
+      return FT_Alloc( memory, size, P );
+
+    /* if the new block if zero-sized, clear the current one */
+    if ( size <= 0 )
+    {
+      FT_Free( memory, P );
+      return FT_Err_Ok;
+    }
+
+    Q = memory->realloc( memory, current, size, *P );
+    if ( !Q )
+      goto Fail;
+
+    *P = Q;
+    return FT_Err_Ok;
+
+  Fail:
+    FT_ERROR(( "FT_Realloc:" ));
+    FT_ERROR(( " Failed (current %ld, requested %ld)\n",
+               current, size ));
+    return FT_Err_Out_Of_Memory;
+  }
+
+
+  /* documentation is in ftmemory.h */
+
+  FT_BASE_DEF( void )
+  FT_Free( FT_Memory  memory,
+           void**     P )
+  {
+    FT_TRACE7(( "FT_Free:" ));
+    FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n",
+                P, P ? *P : (void*)0 ));
+
+    if ( P && *P )
+    {
+      memory->free( memory, *P );
+      *P = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                           S T R E A M                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_new_input_stream                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new input stream object from an FT_Open_Args structure.  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The function expects a valid `astream' parameter.                  */
+  /*                                                                       */
+  static FT_Error
+  ft_new_input_stream( FT_Library     library,
+                       FT_Open_Args*  args,
+                       FT_Stream*     astream )
+  {
+    FT_Error   error;
+    FT_Memory  memory;
+    FT_Stream  stream;
+
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    if ( !args )
+      return FT_Err_Invalid_Argument;
+
+    *astream = 0;
+    memory   = library->memory;
+    if ( ALLOC( stream, sizeof ( *stream ) ) )
+      goto Exit;
+
+    stream->memory = memory;
+
+    /* now, look at the stream flags */
+    if ( args->flags & ft_open_memory )
+    {
+      error = 0;
+      FT_New_Memory_Stream( library,
+                            (FT_Byte*)args->memory_base,
+                            args->memory_size,
+                            stream );
+    }
+    else if ( args->flags & ft_open_pathname )
+    {
+      error = FT_New_Stream( args->pathname, stream );
+      stream->pathname.pointer = args->pathname;
+    }
+    else if ( ( args->flags & ft_open_stream ) && args->stream )
+    {
+      /* in this case, we do not need to allocate a new stream object */
+      /* since the caller is responsible for closing it himself       */
+      FREE( stream );
+      stream = args->stream;
+    }
+    else
+      error = FT_Err_Invalid_Argument;
+
+    if ( error )
+      FREE( stream );
+
+    *astream = stream;
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Done_Stream( FT_Stream  stream )
+  {
+    if ( stream && stream->close )
+    {
+      stream->close( stream );
+      stream->close = 0;
+    }
+  }
+
+
+  static void
+  ft_done_stream( FT_Stream*  astream,
+                  FT_Int      external )
+  {
+    FT_Stream  stream = *astream;
+
+
+    if ( stream->close )
+      stream->close( stream );
+
+    if ( !external )
+    {
+      FT_Memory  memory = stream->memory;
+
+
+      FREE( stream );
+    }
+    *astream = 0;
+  }
+
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_objs
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                     G L Y P H   L O A D E R                     ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The glyph loader is a simple object which is used to load a set of    */
+  /* glyphs easily.  It is critical for the correct loading of composites. */
+  /*                                                                       */
+  /* Ideally, one can see it as a stack of abstract `glyph' objects.       */
+  /*                                                                       */
+  /*   loader.base     Is really the bottom of the stack.  It describes a  */
+  /*                   single glyph image made of the juxtaposition of     */
+  /*                   several glyphs (those `in the stack').              */
+  /*                                                                       */
+  /*   loader.current  Describes the top of the stack, on which a new      */
+  /*                   glyph can be loaded.                                */
+  /*                                                                       */
+  /*   Rewind          Clears the stack.                                   */
+  /*   Prepare         Set up `loader.current' for addition of a new glyph */
+  /*                   image.                                              */
+  /*   Add             Add the `current' glyph image to the `base' one,    */
+  /*                   and prepare for another one.                        */
+  /*                                                                       */
+  /* The glyph loader is now a base object.  Each driver used to           */
+  /* re-implement it in one way or the other, which wasted code and        */
+  /* energy.                                                               */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* create a new glyph loader */
+  FT_BASE_DEF( FT_Error )
+  FT_GlyphLoader_New( FT_Memory         memory,
+                      FT_GlyphLoader*  *aloader )
+  {
+    FT_GlyphLoader*  loader;
+    FT_Error         error;
+
+
+    if ( !ALLOC( loader, sizeof ( *loader ) ) )
+    {
+      loader->memory = memory;
+      *aloader       = loader;
+    }
+    return error;
+  }
+
+
+  /* rewind the glyph loader - reset counters to 0 */
+  FT_BASE_DEF( void )
+  FT_GlyphLoader_Rewind( FT_GlyphLoader*  loader )
+  {
+    FT_GlyphLoad*  base    = &loader->base;
+    FT_GlyphLoad*  current = &loader->current;
+
+
+    base->outline.n_points   = 0;
+    base->outline.n_contours = 0;
+    base->num_subglyphs      = 0;
+
+    *current = *base;
+  }
+
+
+  /* reset the glyph loader, frees all allocated tables */
+  /* and starts from zero                               */
+  FT_BASE_DEF( void )
+  FT_GlyphLoader_Reset( FT_GlyphLoader*  loader )
+  {
+    FT_Memory memory = loader->memory;
+
+
+    FREE( loader->base.outline.points );
+    FREE( loader->base.outline.tags );
+    FREE( loader->base.outline.contours );
+    FREE( loader->base.extra_points );
+    FREE( loader->base.subglyphs );
+
+    loader->max_points    = 0;
+    loader->max_contours  = 0;
+    loader->max_subglyphs = 0;
+
+    FT_GlyphLoader_Rewind( loader );
+  }
+
+
+  /* delete a glyph loader */
+  FT_BASE_DEF( void )
+  FT_GlyphLoader_Done( FT_GlyphLoader*  loader )
+  {
+    if ( loader )
+    {
+      FT_Memory memory = loader->memory;
+
+
+      FT_GlyphLoader_Reset( loader );
+      FREE( loader );
+    }
+  }
+
+
+  /* re-adjust the `current' outline fields */
+  static void
+  FT_GlyphLoader_Adjust_Points( FT_GlyphLoader*  loader )
+  {
+    FT_Outline*  base    = &loader->base.outline;
+    FT_Outline*  current = &loader->current.outline;
+
+
+    current->points   = base->points   + base->n_points;
+    current->tags     = base->tags     + base->n_points;
+    current->contours = base->contours + base->n_contours;
+
+    /* handle extra points table - if any */
+    if ( loader->use_extra )
+      loader->current.extra_points =
+        loader->base.extra_points + base->n_points;
+  }
+
+
+  FT_BASE_DEF( FT_Error )
+  FT_GlyphLoader_Create_Extra( FT_GlyphLoader*  loader )
+  {
+    FT_Error   error;
+    FT_Memory  memory = loader->memory;
+
+
+    if ( !ALLOC_ARRAY( loader->base.extra_points,
+                       loader->max_points, FT_Vector ) )
+    {
+      loader->use_extra = 1;
+      FT_GlyphLoader_Adjust_Points( loader );
+    }
+    return error;
+  }
+
+
+  /* re-adjust the `current' subglyphs field */
+  static void
+  FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader*  loader )
+  {
+    FT_GlyphLoad* base    = &loader->base;
+    FT_GlyphLoad* current = &loader->current;
+
+
+    current->subglyphs = base->subglyphs + base->num_subglyphs;
+  }
+
+
+  /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
+  /* function reallocates its outline tables if necessary.  Note that it   */
+  /* DOESN'T change the number of points within the loader!                */
+  /*                                                                       */
+  FT_BASE_DEF( FT_Error )
+  FT_GlyphLoader_Check_Points( FT_GlyphLoader*  loader,
+                               FT_UInt          n_points,
+                               FT_UInt          n_contours )
+  {
+    FT_Memory    memory  = loader->memory;
+    FT_Error     error   = FT_Err_Ok;
+    FT_Outline*  base    = &loader->base.outline;
+    FT_Outline*  current = &loader->current.outline;
+    FT_Bool      adjust  = 1;
+
+    FT_UInt      new_max, old_max;
+
+
+    /* check points & tags */
+    new_max = base->n_points + current->n_points + n_points;
+    old_max = loader->max_points;
+
+    if ( new_max > old_max )
+    {
+      new_max = ( new_max + 7 ) & -8;
+
+      if ( REALLOC_ARRAY( base->points, old_max, new_max, FT_Vector ) ||
+           REALLOC_ARRAY( base->tags,   old_max, new_max, FT_Byte   ) )
+       goto Exit;
+
+      if ( loader->use_extra &&
+           REALLOC_ARRAY( loader->base.extra_points, old_max,
+                          new_max, FT_Vector ) )
+       goto Exit;
+
+      adjust = 1;
+      loader->max_points = new_max;
+    }
+
+    /* check contours */
+    old_max = loader->max_contours;
+    new_max = base->n_contours + current->n_contours +
+              n_contours;
+    if ( new_max > old_max )
+    {
+      new_max = ( new_max + 3 ) & -4;
+      if ( REALLOC_ARRAY( base->contours, old_max, new_max, FT_Short ) )
+        goto Exit;
+
+      adjust = 1;
+      loader->max_contours = new_max;
+    }
+
+    if ( adjust )
+      FT_GlyphLoader_Adjust_Points( loader );
+
+  Exit:
+    return error;
+  }
+
+
+  /* Ensure that we can add `n_subglyphs' to our glyph. this function */
+  /* reallocates its subglyphs table if necessary.  Note that it DOES */
+  /* NOT change the number of subglyphs within the loader!            */
+  /*                                                                  */
+  FT_BASE_DEF( FT_Error )
+  FT_GlyphLoader_Check_Subglyphs( FT_GlyphLoader*  loader,
+                                  FT_UInt          n_subs )
+  {
+    FT_Memory  memory = loader->memory;
+    FT_Error   error  = FT_Err_Ok;
+    FT_UInt    new_max, old_max;
+
+    FT_GlyphLoad*  base    = &loader->base;
+    FT_GlyphLoad*  current = &loader->current;
+
+
+    new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
+    old_max = loader->max_subglyphs;
+    if ( new_max > old_max )
+    {
+      new_max = ( new_max + 1 ) & -2;
+      if ( REALLOC_ARRAY( base->subglyphs, old_max, new_max, FT_SubGlyph ) )
+        goto Exit;
+
+      loader->max_subglyphs = new_max;
+
+      FT_GlyphLoader_Adjust_Subglyphs( loader );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* prepare loader for the addition of a new glyph on top of the base one */
+  FT_BASE_DEF( void )
+  FT_GlyphLoader_Prepare( FT_GlyphLoader*  loader )
+  {
+    FT_GlyphLoad*  current = &loader->current;
+
+
+    current->outline.n_points   = 0;
+    current->outline.n_contours = 0;
+    current->num_subglyphs      = 0;
+
+    FT_GlyphLoader_Adjust_Points   ( loader );
+    FT_GlyphLoader_Adjust_Subglyphs( loader );
+  }
+
+
+  /* add current glyph to the base image - and prepare for another */
+  FT_BASE_DEF( void )
+  FT_GlyphLoader_Add( FT_GlyphLoader*  loader )
+  {
+    FT_GlyphLoad*  base    = &loader->base;
+    FT_GlyphLoad*  current = &loader->current;
+
+    FT_UInt        n_curr_contours = current->outline.n_contours;
+    FT_UInt        n_base_points   = base->outline.n_points;
+    FT_UInt        n;
+
+
+    base->outline.n_points =
+      (short)( base->outline.n_points + current->outline.n_points );
+    base->outline.n_contours =
+      (short)( base->outline.n_contours + current->outline.n_contours );
+
+    base->num_subglyphs += current->num_subglyphs;
+
+    /* adjust contours count in newest outline */
+    for ( n = 0; n < n_curr_contours; n++ )
+      current->outline.contours[n] =
+        (short)( current->outline.contours[n] + n_base_points );
+
+    /* prepare for another new glyph image */
+    FT_GlyphLoader_Prepare( loader );
+  }
+
+
+  FT_BASE_DEF( FT_Error )
+  FT_GlyphLoader_Copy_Points( FT_GlyphLoader*  target,
+                              FT_GlyphLoader*  source )
+  {
+    FT_Error  error;
+    FT_UInt   num_points   = source->base.outline.n_points;
+    FT_UInt   num_contours = source->base.outline.n_contours;
+
+
+    error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
+    if ( !error )
+    {
+      FT_Outline*  out = &target->base.outline;
+      FT_Outline*  in  = &source->base.outline;
+
+
+      MEM_Copy( out->points, in->points,
+                num_points * sizeof ( FT_Vector ) );
+      MEM_Copy( out->tags, in->tags,
+                num_points * sizeof ( char ) );
+      MEM_Copy( out->contours, in->contours,
+                num_contours * sizeof ( short ) );
+
+      /* do we need to copy the extra points? */
+      if ( target->use_extra && source->use_extra )
+        MEM_Copy( target->base.extra_points, source->base.extra_points,
+                  num_points * sizeof ( FT_Vector ) );
+
+      out->n_points   = (short)num_points;
+      out->n_contours = (short)num_contours;
+
+      FT_GlyphLoader_Adjust_Points( target );
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static FT_Error
+  ft_glyphslot_init( FT_GlyphSlot  slot )
+  {
+    FT_Driver         driver = slot->face->driver;
+    FT_Driver_Class*  clazz  = driver->clazz;
+    FT_Memory         memory = driver->root.memory;
+    FT_Error          error  = FT_Err_Ok;
+    FT_Slot_Internal  internal;
+
+
+    slot->library = driver->root.library;
+
+    if ( ALLOC( internal, sizeof ( *internal ) ) )
+      goto Exit;
+
+    slot->internal = internal;
+
+    if ( FT_DRIVER_USES_OUTLINES( driver ) )
+      error = FT_GlyphLoader_New( memory, &internal->loader );
+
+    if ( !error && clazz->init_slot )
+      error = clazz->init_slot( slot );
+
+  Exit:
+    return error;
+  }
+
+
+  static void
+  ft_glyphslot_clear( FT_GlyphSlot  slot )
+  {
+    /* free bitmap if needed */
+    if ( slot->flags & ft_glyph_own_bitmap )
+    {
+      FT_Memory  memory = FT_FACE_MEMORY( slot->face );
+
+
+      FREE( slot->bitmap.buffer );
+      slot->flags &= ~ft_glyph_own_bitmap;
+    }
+
+    /* clear all public fields in the glyph slot */
+    MEM_Set( &slot->metrics, 0, sizeof ( slot->metrics ) );
+    MEM_Set( &slot->outline, 0, sizeof ( slot->outline ) );
+    MEM_Set( &slot->bitmap,  0, sizeof ( slot->bitmap )  );
+
+    slot->bitmap_left   = 0;
+    slot->bitmap_top    = 0;
+    slot->num_subglyphs = 0;
+    slot->subglyphs     = 0;
+    slot->control_data  = 0;
+    slot->control_len   = 0;
+    slot->other         = 0;
+    slot->format        = ft_glyph_format_none;
+
+    slot->linearHoriAdvance = 0;
+    slot->linearVertAdvance = 0;
+  }
+
+
+  static void
+  ft_glyphslot_done( FT_GlyphSlot  slot )
+  {
+    FT_Driver         driver = slot->face->driver;
+    FT_Driver_Class*  clazz  = driver->clazz;
+    FT_Memory         memory = driver->root.memory;
+
+
+    if ( clazz->done_slot )
+      clazz->done_slot( slot );
+
+    /* free bitmap buffer if needed */
+    if ( slot->flags & ft_glyph_own_bitmap )
+      FREE( slot->bitmap.buffer );
+
+    /* free glyph loader */
+    if ( FT_DRIVER_USES_OUTLINES( driver ) )
+    {
+      FT_GlyphLoader_Done( slot->internal->loader );
+      slot->internal->loader = 0;
+    }
+
+    FREE( slot->internal );
+  }
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_BASE_DEF( FT_Error )
+  FT_New_GlyphSlot( FT_Face        face,
+                    FT_GlyphSlot  *aslot )
+  {
+    FT_Error          error;
+    FT_Driver         driver;
+    FT_Driver_Class*  clazz;
+    FT_Memory         memory;
+    FT_GlyphSlot      slot;
+
+
+    if ( !face || !aslot || !face->driver )
+      return FT_Err_Invalid_Argument;
+
+    *aslot = 0;
+
+    driver = face->driver;
+    clazz  = driver->clazz;
+    memory = driver->root.memory;
+
+    FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
+    if ( !ALLOC( slot, clazz->slot_object_size ) )
+    {
+      slot->face = face;
+
+      error = ft_glyphslot_init( slot );
+      if ( error )
+      {
+        ft_glyphslot_done( slot );
+        FREE( slot );
+        goto Exit;
+      }
+
+      *aslot = slot;
+    }
+
+  Exit:
+    FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
+    return error;
+  }
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_BASE_DEF( void )
+  FT_Done_GlyphSlot( FT_GlyphSlot  slot )
+  {
+    if ( slot )
+    {
+      FT_Driver         driver = slot->face->driver;
+      FT_Memory         memory = driver->root.memory;
+      FT_GlyphSlot*     parent;
+      FT_GlyphSlot      cur;
+
+
+      /* Remove slot from its parent face's list */
+      parent = &slot->face->glyph;
+      cur    = *parent;
+
+      while ( cur )
+      {
+        if ( cur == slot )
+        {
+          *parent = cur->next;
+          ft_glyphslot_done( slot );
+          FREE( slot );
+          break;
+        }
+        cur = cur->next;
+      }
+    }
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Set_Transform( FT_Face     face,
+                    FT_Matrix*  matrix,
+                    FT_Vector*  delta )
+  {
+    FT_Face_Internal  internal;
+
+
+    if ( !face )
+      return;
+
+    internal = face->internal;
+
+    internal->transform_flags = 0;
+
+    if ( !matrix )
+    {
+      internal->transform_matrix.xx = 0x10000L;
+      internal->transform_matrix.xy = 0;
+      internal->transform_matrix.yx = 0;
+      internal->transform_matrix.yy = 0x10000L;
+      matrix = &internal->transform_matrix;
+    }
+    else
+      internal->transform_matrix = *matrix;
+
+    /* set transform_flags bit flag 0 if `matrix' isn't the identity */
+    if ( ( matrix->xy | matrix->yx ) ||
+         matrix->xx != 0x10000L      ||
+         matrix->yy != 0x10000L      )
+      internal->transform_flags |= 1;
+
+    if ( !delta )
+    {
+      internal->transform_delta.x = 0;
+      internal->transform_delta.y = 0;
+      delta = &internal->transform_delta;
+    }
+    else
+      internal->transform_delta = *delta;
+
+    /* set transform_flags bit flag 1 if `delta' isn't the null vector */
+    if ( delta->x | delta->y )
+      internal->transform_flags |= 2;
+  }
+
+
+  static FT_Renderer
+  ft_lookup_glyph_renderer( FT_GlyphSlot  slot );
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Load_Glyph( FT_Face  face,
+                 FT_UInt  glyph_index,
+                 FT_Int   load_flags )
+  {
+    FT_Error      error;
+    FT_Driver     driver;
+    FT_GlyphSlot  slot;
+    FT_Library    library;
+    FT_Bool       autohint;
+    FT_Module     hinter;
+
+
+    if ( !face || !face->size || !face->glyph )
+      return FT_Err_Invalid_Face_Handle;
+
+    if ( glyph_index >= (FT_UInt)face->num_glyphs )
+      return FT_Err_Invalid_Argument;
+
+    slot = face->glyph;
+    ft_glyphslot_clear( slot );
+
+    driver = face->driver;
+
+    /* when the flag NO_RECURSE is set, we disable hinting and scaling */
+    if ( load_flags & FT_LOAD_NO_RECURSE )
+    {
+      /* disable scaling, hinting, and transformation */
+      load_flags |= FT_LOAD_NO_SCALE         |
+                    FT_LOAD_NO_HINTING       |
+                    FT_LOAD_IGNORE_TRANSFORM;
+
+      /* disable bitmap rendering */
+      load_flags &= ~FT_LOAD_RENDER;
+    }
+
+    /* do we need to load the glyph through the auto-hinter? */
+    library  = driver->root.library;
+    hinter   = library->auto_hinter;
+    autohint =
+      FT_BOOL( hinter                                                      &&
+               !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) &&
+               FT_DRIVER_IS_SCALABLE( driver )                             &&
+               FT_DRIVER_USES_OUTLINES( driver )                           );
+    if ( autohint )
+    {
+      if ( FT_DRIVER_HAS_HINTER( driver ) &&
+           !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
+        autohint = 0;
+    }
+
+    if ( autohint )
+    {
+      FT_AutoHinter_Interface*  hinting;
+
+
+      hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface;
+
+      error   = hinting->load_glyph( (FT_AutoHinter)hinter,
+                                     slot, face->size,
+                                     glyph_index, load_flags );
+    }
+    else
+      error = driver->clazz->load_glyph( slot,
+                                         face->size,
+                                         glyph_index,
+                                         load_flags );
+    if ( error )
+      goto Exit;
+
+    /* compute the advance */
+    if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+    {
+      slot->advance.x = 0;
+      slot->advance.y = slot->metrics.vertAdvance;
+    }
+    else
+    {
+      slot->advance.x = slot->metrics.horiAdvance;
+      slot->advance.y = 0;
+    }
+
+    /* compute the linear advance in 16.16 pixels */
+    if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 )
+    {
+      FT_UInt           EM      = face->units_per_EM;
+      FT_Size_Metrics*  metrics = &face->size->metrics;
+
+      slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
+                                           (FT_Long)metrics->x_ppem << 16, EM );
+
+      slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
+                                           (FT_Long)metrics->y_ppem << 16, EM );
+    }
+
+    if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
+    {
+      FT_Face_Internal  internal = face->internal;
+
+
+      /* now, transform the glyph image if needed */
+      if ( internal->transform_flags )
+      {
+        /* get renderer */
+        FT_Renderer  renderer = ft_lookup_glyph_renderer( slot );
+
+
+        if ( renderer )
+          error = renderer->clazz->transform_glyph(
+                                     renderer, slot,
+                                     &internal->transform_matrix,
+                                     &internal->transform_delta );
+        /* transform advance */
+        FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
+      }
+    }
+
+    /* do we need to render the image now? */
+    if ( !error                                    &&
+         slot->format != ft_glyph_format_bitmap    &&
+         slot->format != ft_glyph_format_composite &&
+         load_flags & FT_LOAD_RENDER )
+    {
+      error = FT_Render_Glyph( slot,
+                               ( load_flags & FT_LOAD_MONOCHROME )
+                                  ? ft_render_mode_mono
+                                  : ft_render_mode_normal );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Load_Char( FT_Face   face,
+                FT_ULong  char_code,
+                FT_Int    load_flags )
+  {
+    FT_UInt  glyph_index;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    glyph_index = (FT_UInt)char_code;
+    if ( face->charmap )
+      glyph_index = FT_Get_Char_Index( face, char_code );
+
+    return FT_Load_Glyph( face, glyph_index, load_flags );
+  }
+
+
+  /* destructor for sizes list */
+  static void
+  destroy_size( FT_Memory  memory,
+                FT_Size    size,
+                FT_Driver  driver )
+  {
+    /* finalize client-specific data */
+    if ( size->generic.finalizer )
+      size->generic.finalizer( size );
+
+    /* finalize format-specific stuff */
+    if ( driver->clazz->done_size )
+      driver->clazz->done_size( size );
+
+    FREE( size->internal );
+    FREE( size );
+  }
+
+
+  /* destructor for faces list */
+  static void
+  destroy_face( FT_Memory  memory,
+                FT_Face    face,
+                FT_Driver  driver )
+  {
+    FT_Driver_Class*  clazz = driver->clazz;
+
+
+    /* discard auto-hinting data */
+    if ( face->autohint.finalizer )
+      face->autohint.finalizer( face->autohint.data );
+
+    /* Discard glyph slots for this face                            */
+    /* Beware!  FT_Done_GlyphSlot() changes the field `face->glyph' */
+    while ( face->glyph )
+      FT_Done_GlyphSlot( face->glyph );
+
+    /* Discard all sizes for this face */
+    FT_List_Finalize( &face->sizes_list,
+                     (FT_List_Destructor)destroy_size,
+                     memory,
+                     driver );
+    face->size = 0;
+
+    /* Now discard client data */
+    if ( face->generic.finalizer )
+      face->generic.finalizer( face );
+
+    /* finalize format-specific stuff */
+    if ( clazz->done_face )
+      clazz->done_face( face );
+
+    /* close the stream for this face if needed */
+    ft_done_stream(
+      &face->stream,
+      ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
+
+    /* get rid of it */
+    if ( face->internal )
+    {
+      FREE( face->internal->postscript_name );
+      FREE( face->internal );
+    }
+    FREE( face );
+  }
+
+
+  static void
+  Destroy_Driver( FT_Driver  driver )
+  {
+    FT_List_Finalize( &driver->faces_list,
+                      (FT_List_Destructor)destroy_face,
+                      driver->root.memory,
+                      driver );
+
+    /* check whether we need to drop the driver's glyph loader */
+    if ( FT_DRIVER_USES_OUTLINES( driver ) )
+      FT_GlyphLoader_Done( driver->glyph_loader );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    open_face                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function does some work for FT_Open_Face().                   */
+  /*                                                                       */
+  static FT_Error
+  open_face( FT_Driver      driver,
+             FT_Stream      stream,
+             FT_Long        face_index,
+             FT_Int         num_params,
+             FT_Parameter*  params,
+             FT_Face*       aface )
+  {
+    FT_Memory         memory;
+    FT_Driver_Class*  clazz;
+    FT_Face           face = 0;
+    FT_Error          error;
+    FT_Face_Internal  internal;
+
+
+    clazz  = driver->clazz;
+    memory = driver->root.memory;
+
+    /* allocate the face object and perform basic initialization */
+    if ( ALLOC( face, clazz->face_object_size ) )
+      goto Fail;
+
+    if ( ALLOC( internal, sizeof ( *internal ) ) )
+      goto Fail;
+
+    face->internal = internal;
+
+    face->driver   = driver;
+    face->memory   = memory;
+    face->stream   = stream;
+
+    error = clazz->init_face( stream,
+                              face,
+                              face_index,
+                              num_params,
+                              params );
+    if ( error )
+      goto Fail;
+
+    *aface = face;
+
+  Fail:
+    if ( error )
+    {
+      clazz->done_face( face );
+      FREE( face->internal );
+      FREE( face );
+      *aface = 0;
+    }
+
+    return error;
+  }
+
+
+  /* there's a Mac-specific extended implementation of FT_New_Face() */
+  /* in src/mac/ftmac.c                                              */
+
+#ifndef macintosh
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_New_Face( FT_Library   library,
+               const char*  pathname,
+               FT_Long      face_index,
+               FT_Face     *aface )
+  {
+    FT_Open_Args  args;
+
+
+    /* test for valid `library' and `aface' delayed to FT_Open_Face() */
+    if ( !pathname )
+      return FT_Err_Invalid_Argument;
+
+    args.flags    = ft_open_pathname;
+    args.pathname = (char*)pathname;
+
+    return FT_Open_Face( library, &args, face_index, aface );
+  }
+
+#endif  /* !macintosh */
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_New_Memory_Face( FT_Library      library,
+                      const FT_Byte*  file_base,
+                      FT_Long         file_size,
+                      FT_Long         face_index,
+                      FT_Face        *aface )
+  {
+    FT_Open_Args  args;
+
+
+    /* test for valid `library' and `face' delayed to FT_Open_Face() */
+    if ( !file_base )
+      return FT_Err_Invalid_Argument;
+
+    args.flags       = ft_open_memory;
+    args.memory_base = file_base;
+    args.memory_size = file_size;
+
+    return FT_Open_Face( library, &args, face_index, aface );
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Open_Face( FT_Library     library,
+                FT_Open_Args*  args,
+                FT_Long        face_index,
+                FT_Face       *aface )
+  {
+    FT_Error     error;
+    FT_Driver    driver;
+    FT_Memory    memory;
+    FT_Stream    stream;
+    FT_Face      face = 0;
+    FT_ListNode  node = 0;
+    FT_Bool      external_stream;
+
+
+    /* test for valid `library' delayed to */
+    /* ft_new_input_stream()               */
+
+    if ( !aface || !args )
+      return FT_Err_Invalid_Argument;
+
+    *aface = 0;
+
+    external_stream = FT_BOOL( ( args->flags & ft_open_stream ) &&
+                               args->stream                     );
+
+    /* create input stream */
+    error = ft_new_input_stream( library, args, &stream );
+    if ( error )
+      goto Exit;
+
+    memory = library->memory;
+
+    /* If the font driver is specified in the `args' structure, use */
+    /* it.  Otherwise, we scan the list of registered drivers.      */
+    if ( ( args->flags & ft_open_driver ) && args->driver )
+    {
+      driver = FT_DRIVER( args->driver );
+
+      /* not all modules are drivers, so check... */
+      if ( FT_MODULE_IS_DRIVER( driver ) )
+      {
+        FT_Int         num_params = 0;
+        FT_Parameter*  params     = 0;
+
+
+        if ( args->flags & ft_open_params )
+        {
+          num_params = args->num_params;
+          params     = args->params;
+        }
+
+        error = open_face( driver, stream, face_index,
+                           num_params, params, &face );
+        if ( !error )
+          goto Success;
+      }
+      else
+        error = FT_Err_Invalid_Handle;
+
+      ft_done_stream( &stream, external_stream );
+      goto Fail;
+    }
+    else
+    {
+      /* check each font driver for an appropriate format */
+      FT_Module*  cur   = library->modules;
+      FT_Module*  limit = cur + library->num_modules;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        /* not all modules are font drivers, so check... */
+        if ( FT_MODULE_IS_DRIVER( cur[0] ) )
+        {
+          FT_Int         num_params = 0;
+          FT_Parameter*  params     = 0;
+
+
+          driver = FT_DRIVER( cur[0] );
+
+          if ( args->flags & ft_open_params )
+          {
+            num_params = args->num_params;
+            params     = args->params;
+          }
+
+          error = open_face( driver, stream, face_index,
+                             num_params, params, &face );
+          if ( !error )
+            goto Success;
+
+          if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
+            goto Fail2;
+        }
+      }
+
+      /* no driver is able to handle this format */
+      error = FT_Err_Unknown_File_Format;
+
+  Fail2:
+      ft_done_stream( &stream, external_stream );
+      goto Fail;
+    }
+
+  Success:
+    FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
+
+    /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
+    if ( external_stream )
+      face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
+
+    /* add the face object to its driver's list */
+    if ( ALLOC( node, sizeof ( *node ) ) )
+      goto Fail;
+
+    node->data = face;
+    /* don't assume driver is the same as face->driver, so use */
+    /* face->driver instead.                                   */
+    FT_List_Add( &face->driver->faces_list, node );
+
+    /* now allocate a glyph slot object for the face */
+    {
+      FT_GlyphSlot  slot;
+
+
+      FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
+
+      error = FT_New_GlyphSlot( face, &slot );
+      if ( error )
+        goto Fail;
+
+      face->glyph = slot;
+    }
+
+    /* finally, allocate a size object for the face */
+    {
+      FT_Size  size;
+
+
+      FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
+
+      error = FT_New_Size( face, &size );
+      if ( error )
+        goto Fail;
+
+      face->size = size;
+    }
+
+    /* initialize internal face data */
+    {
+      FT_Face_Internal  internal = face->internal;
+
+
+      internal->transform_matrix.xx = 0x10000L;
+      internal->transform_matrix.xy = 0;
+      internal->transform_matrix.yx = 0;
+      internal->transform_matrix.yy = 0x10000L;
+
+      internal->transform_delta.x = 0;
+      internal->transform_delta.y = 0;
+    }
+
+    *aface = face;
+    goto Exit;
+
+  Fail:
+    FT_Done_Face( face );
+
+  Exit:
+    FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
+
+    return error;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Attach_File( FT_Face      face,
+                  const char*  filepathname )
+  {
+    FT_Open_Args  open;
+
+
+    /* test for valid `face' delayed to FT_Attach_Stream() */
+
+    if ( !filepathname )
+      return FT_Err_Invalid_Argument;
+
+    open.flags    = ft_open_pathname;
+    open.pathname = (char*)filepathname;
+
+    return FT_Attach_Stream( face, &open );
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Attach_Stream( FT_Face        face,
+                    FT_Open_Args*  parameters )
+  {
+    FT_Stream  stream;
+    FT_Error   error;
+    FT_Driver  driver;
+
+    FT_Driver_Class*  clazz;
+
+
+    /* test for valid `parameters' delayed to ft_new_input_stream() */
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    driver = face->driver;
+    if ( !driver )
+      return FT_Err_Invalid_Driver_Handle;
+
+    error = ft_new_input_stream( driver->root.library, parameters, &stream );
+    if ( error )
+      goto Exit;
+
+    /* we implement FT_Attach_Stream in each driver through the */
+    /* `attach_file' interface                                  */
+
+    error = FT_Err_Unimplemented_Feature;
+    clazz = driver->clazz;
+    if ( clazz->attach_file )
+      error = clazz->attach_file( face, stream );
+
+    /* close the attached stream */
+    ft_done_stream( &stream,
+                    (FT_Bool)( parameters->stream &&
+                               ( parameters->flags & ft_open_stream ) ) );
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Done_Face( FT_Face  face )
+  {
+    FT_Error     error;
+    FT_Driver    driver;
+    FT_Memory    memory;
+    FT_ListNode  node;
+
+
+    error = FT_Err_Invalid_Face_Handle;
+    if ( face && face->driver )
+    {
+      driver = face->driver;
+      memory = driver->root.memory;
+
+      /* find face in driver's list */
+      node = FT_List_Find( &driver->faces_list, face );
+      if ( node )
+      {
+        /* remove face object from the driver's list */
+        FT_List_Remove( &driver->faces_list, node );
+        FREE( node );
+
+        /* now destroy the object proper */
+        destroy_face( memory, face, driver );
+        error = FT_Err_Ok;
+      }
+    }
+    return error;
+  }
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_New_Size( FT_Face   face,
+               FT_Size  *asize )
+  {
+    FT_Error          error;
+    FT_Memory         memory;
+    FT_Driver         driver;
+    FT_Driver_Class*  clazz;
+
+    FT_Size           size = 0;
+    FT_ListNode       node = 0;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    if ( !asize )
+      return FT_Err_Invalid_Size_Handle;
+
+    if ( !face->driver )
+      return FT_Err_Invalid_Driver_Handle;
+
+    *asize = 0;
+
+    driver = face->driver;
+    clazz  = driver->clazz;
+    memory = face->memory;
+
+    /* Allocate new size object and perform basic initialisation */
+    if ( ALLOC( size, clazz->size_object_size ) ||
+         ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
+      goto Exit;
+
+    size->face = face;
+
+    /* for now, do not use any internal fields in size objects */
+    size->internal = 0;
+
+    if ( clazz->init_size )
+      error = clazz->init_size( size );
+
+    /* in case of success, add to the face's list */
+    if ( !error )
+    {
+      *asize     = size;
+      node->data = size;
+      FT_List_Add( &face->sizes_list, node );
+    }
+
+  Exit:
+    if ( error )
+    {
+      FREE( node );
+      FREE( size );
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Done_Size( FT_Size  size )
+  {
+    FT_Error     error;
+    FT_Driver    driver;
+    FT_Memory    memory;
+    FT_Face      face;
+    FT_ListNode  node;
+
+
+    if ( !size )
+      return FT_Err_Invalid_Size_Handle;
+
+    face = size->face;
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    driver = face->driver;
+    if ( !driver )
+      return FT_Err_Invalid_Driver_Handle;
+
+    memory = driver->root.memory;
+
+    error = FT_Err_Ok;
+    node  = FT_List_Find( &face->sizes_list, size );
+    if ( node )
+    {
+      FT_List_Remove( &face->sizes_list, node );
+      FREE( node );
+
+      if ( face->size == size )
+      {
+        face->size = 0;
+        if ( face->sizes_list.head )
+          face->size = (FT_Size)(face->sizes_list.head->data);
+      }
+
+      destroy_size( memory, size, driver );
+    }
+    else
+      error = FT_Err_Invalid_Size_Handle;
+
+    return error;
+  }
+
+
+  static void
+  ft_recompute_scaled_metrics( FT_Face           face,
+                               FT_Size_Metrics*  metrics )
+  {
+    /* Compute root ascender, descender, test height, and max_advance */
+
+    metrics->ascender    = ( FT_MulFix( face->ascender,
+                                        metrics->y_scale ) + 32 ) & -64;
+
+    metrics->descender   = ( FT_MulFix( face->descender,
+                                        metrics->y_scale ) + 32 ) & -64;
+
+    metrics->height      = ( FT_MulFix( face->height,
+                                        metrics->y_scale ) + 32 ) & -64;
+
+    metrics->max_advance = ( FT_MulFix( face->max_advance_width,
+                                        metrics->x_scale ) + 32 ) & -64;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Set_Char_Size( FT_Face     face,
+                    FT_F26Dot6  char_width,
+                    FT_F26Dot6  char_height,
+                    FT_UInt     horz_resolution,
+                    FT_UInt     vert_resolution )
+  {
+    FT_Error          error = FT_Err_Ok;
+    FT_Driver         driver;
+    FT_Driver_Class*  clazz;
+    FT_Size_Metrics*  metrics;
+    FT_Long           dim_x, dim_y;
+
+
+    if ( !face || !face->size || !face->driver )
+      return FT_Err_Invalid_Face_Handle;
+
+    driver  = face->driver;
+    metrics = &face->size->metrics;
+
+    if ( !char_width )
+      char_width = char_height;
+
+    else if ( !char_height )
+      char_height = char_width;
+
+    if ( !horz_resolution )
+      horz_resolution = 72;
+
+    if ( !vert_resolution )
+      vert_resolution = 72;
+
+    driver = face->driver;
+    clazz  = driver->clazz;
+
+    /* default processing -- this can be overridden by the driver */
+    if ( char_width  < 1 * 64 )
+      char_width  = 1 * 64;
+    if ( char_height < 1 * 64 )
+      char_height = 1 * 64;
+
+    /* Compute pixel sizes in 26.6 units */
+    dim_x = ( ( ( char_width  * horz_resolution ) / 72 ) + 32 ) & -64;
+    dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;
+
+    metrics->x_ppem  = (FT_UShort)( dim_x >> 6 );
+    metrics->y_ppem  = (FT_UShort)( dim_y >> 6 );
+
+    metrics->x_scale = 0x10000L;
+    metrics->y_scale = 0x10000L;
+
+    if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+    {
+      metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
+      metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
+
+      ft_recompute_scaled_metrics( face, metrics );
+    }
+
+    if ( clazz->set_char_sizes )
+      error = clazz->set_char_sizes( face->size,
+                                     char_width,
+                                     char_height,
+                                     horz_resolution,
+                                     vert_resolution );
+    return error;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Set_Pixel_Sizes( FT_Face  face,
+                      FT_UInt  pixel_width,
+                      FT_UInt  pixel_height )
+  {
+    FT_Error          error = FT_Err_Ok;
+    FT_Driver         driver;
+    FT_Driver_Class*  clazz;
+    FT_Size_Metrics*  metrics = &face->size->metrics;
+
+
+    if ( !face || !face->size || !face->driver )
+      return FT_Err_Invalid_Face_Handle;
+
+    driver = face->driver;
+    clazz  = driver->clazz;
+
+    /* default processing -- this can be overridden by the driver */
+    if ( pixel_width == 0 )
+      pixel_width = pixel_height;
+
+    else if ( pixel_height == 0 )
+      pixel_height = pixel_width;
+
+    if ( pixel_width  < 1 )
+      pixel_width  = 1;
+    if ( pixel_height < 1 )
+      pixel_height = 1;
+
+    metrics->x_ppem = (FT_UShort)pixel_width;
+    metrics->y_ppem = (FT_UShort)pixel_height;
+
+    if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+    {
+      metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
+                                    face->units_per_EM );
+
+      metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
+                                    face->units_per_EM );
+
+      ft_recompute_scaled_metrics( face, metrics );
+    }
+
+    if ( clazz->set_pixel_sizes )
+      error = clazz->set_pixel_sizes( face->size,
+                                      pixel_width,
+                                      pixel_height );
+    return error;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_Kerning( FT_Face     face,
+                  FT_UInt     left_glyph,
+                  FT_UInt     right_glyph,
+                  FT_UInt     kern_mode,
+                  FT_Vector  *akerning )
+  {
+    FT_Error   error = FT_Err_Ok;
+    FT_Driver  driver;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    if ( !akerning )
+      return FT_Err_Invalid_Argument;
+
+    driver = face->driver;
+
+    akerning->x = 0;
+    akerning->y = 0;
+
+    if ( driver->clazz->get_kerning )
+    {
+      error = driver->clazz->get_kerning( face,
+                                          left_glyph,
+                                          right_glyph,
+                                          akerning );
+      if ( !error )
+      {
+        if ( kern_mode != ft_kerning_unscaled )
+        {
+          akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
+          akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
+
+          if ( kern_mode != ft_kerning_unfitted )
+          {
+            akerning->x = ( akerning->x + 32 ) & -64;
+            akerning->y = ( akerning->y + 32 ) & -64;
+          }
+        }
+      }
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Select_Charmap( FT_Face      face,
+                     FT_Encoding  encoding )
+  {
+    FT_CharMap*  cur;
+    FT_CharMap*  limit;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    cur = face->charmaps;
+    if ( !cur )
+      return FT_Err_Invalid_CharMap_Handle;
+
+    limit = cur + face->num_charmaps;
+
+    for ( ; cur < limit; cur++ )
+    {
+      if ( cur[0]->encoding == encoding )
+      {
+        face->charmap = cur[0];
+        return 0;
+      }
+    }
+
+    return FT_Err_Invalid_Argument;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Set_Charmap( FT_Face     face,
+                  FT_CharMap  charmap )
+  {
+    FT_CharMap*  cur;
+    FT_CharMap*  limit;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    cur = face->charmaps;
+    if ( !cur )
+      return FT_Err_Invalid_CharMap_Handle;
+
+    limit = cur + face->num_charmaps;
+
+    for ( ; cur < limit; cur++ )
+    {
+      if ( cur[0] == charmap )
+      {
+        face->charmap = cur[0];
+        return 0;
+      }
+    }
+    return FT_Err_Invalid_Argument;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_UInt )
+  FT_Get_Char_Index( FT_Face   face,
+                     FT_ULong  charcode )
+  {
+    FT_UInt    result;
+    FT_Driver  driver;
+
+
+    result = 0;
+    if ( face && face->charmap )
+    {
+      driver = face->driver;
+      result = driver->clazz->get_char_index( face->charmap, charcode );
+    }
+    return result;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_UInt )
+  FT_Get_Name_Index( FT_Face     face,
+                     FT_String*  glyph_name )
+  {
+    FT_UInt  result = 0;
+
+
+    if ( face && FT_HAS_GLYPH_NAMES( face ) )
+    {
+      /* now, lookup for glyph name */
+      FT_Driver         driver = face->driver;
+      FT_Module_Class*  clazz  = FT_MODULE_CLASS( driver );
+
+
+      if ( clazz->get_interface )
+      {
+        FT_Name_Index_Requester  requester;
+
+
+        requester = (FT_Name_Index_Requester)clazz->get_interface(
+                      FT_MODULE( driver ), "name_index" );
+        if ( requester )
+          result = requester( face, glyph_name );
+      }
+    }
+
+    return result;
+  }
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Get_Glyph_Name( FT_Face     face,
+                     FT_UInt     glyph_index,
+                     FT_Pointer  buffer,
+                     FT_UInt     buffer_max )
+  {
+    FT_Error  error = FT_Err_Invalid_Argument;
+
+
+    /* clean up buffer */
+    if ( buffer && buffer_max > 0 )
+      ((FT_Byte*)buffer)[0] = 0;
+
+    if ( face                                    &&
+         glyph_index < (FT_UInt)face->num_glyphs &&
+         FT_HAS_GLYPH_NAMES( face )              )
+    {
+      /* now, lookup for glyph name */
+      FT_Driver        driver = face->driver;
+      FT_Module_Class* clazz  = FT_MODULE_CLASS( driver );
+
+
+      if ( clazz->get_interface )
+      {
+        FT_Glyph_Name_Requester  requester;
+
+
+        requester = (FT_Glyph_Name_Requester)clazz->get_interface(
+                      FT_MODULE( driver ), "glyph_name" );
+        if ( requester )
+          error = requester( face, glyph_index, buffer, buffer_max );
+      }
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( const char* )
+  FT_Get_Postscript_Name( FT_Face  face )
+  {
+    const char*  result = NULL;
+    
+    if ( !face )
+      goto Exit;
+
+    result = face->internal->postscript_name;
+    if ( !result )
+    {
+      /* now, lookup for glyph name */
+      FT_Driver        driver = face->driver;
+      FT_Module_Class* clazz  = FT_MODULE_CLASS( driver );
+
+      if ( clazz->get_interface )
+      {
+        FT_PSName_Requester  requester;
+
+        requester = (FT_PSName_Requester)clazz->get_interface(
+                      FT_MODULE( driver ), "postscript_name" );
+        if ( requester )
+          result = requester( face );
+      }
+    }
+  Exit:
+    return result;
+  }
+
+
+  /* documentation is in tttables.h */
+
+  FT_EXPORT_DEF( void* )
+  FT_Get_Sfnt_Table( FT_Face      face,
+                     FT_Sfnt_Tag  tag )
+  {
+    void*                   table = 0;
+    FT_Get_Sfnt_Table_Func  func;
+    FT_Driver               driver;
+
+
+    if ( !face || !FT_IS_SFNT( face ) )
+      goto Exit;
+
+    driver = face->driver;
+    func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
+                                     FT_MODULE( driver ), "get_sfnt" );
+    if ( func )
+      table = func( face, tag );
+
+  Exit:
+    return table;
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Activate_Size( FT_Size  size )
+  {
+    FT_Face  face;
+    
+
+    if ( size == NULL )
+      return FT_Err_Bad_Argument;
+      
+    face = size->face;
+    if ( face == NULL || face->driver == NULL )
+      return FT_Err_Bad_Argument;
+    
+    /* we don't need anything more complex than that; all size objects */
+    /* are already listed by the face                                  */
+    face->size = size;
+    
+    return FT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                        R E N D E R E R S                        ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* lookup a renderer by glyph format in the library's list */
+  FT_BASE_DEF( FT_Renderer )
+  FT_Lookup_Renderer( FT_Library       library,
+                      FT_Glyph_Format  format,
+                      FT_ListNode*     node )
+  {
+    FT_ListNode   cur;
+    FT_Renderer   result = 0;
+
+
+    if ( !library )
+      goto Exit;
+
+    cur = library->renderers.head;
+
+    if ( node )
+    {
+      if ( *node )
+        cur = (*node)->next;
+      *node = 0;
+    }
+
+    while ( cur )
+    {
+      FT_Renderer  renderer = FT_RENDERER( cur->data );
+
+
+      if ( renderer->glyph_format == format )
+      {
+        if ( node )
+          *node = cur;
+
+        result = renderer;
+        break;
+      }
+      cur = cur->next;
+    }
+
+  Exit:
+    return result;
+  }
+
+
+  static FT_Renderer
+  ft_lookup_glyph_renderer( FT_GlyphSlot  slot )
+  {
+    FT_Face      face    = slot->face;
+    FT_Library   library = FT_FACE_LIBRARY( face );
+    FT_Renderer  result  = library->cur_renderer;
+
+
+    if ( !result || result->glyph_format != slot->format )
+      result = FT_Lookup_Renderer( library, slot->format, 0 );
+
+    return result;
+  }
+
+
+  static void
+  ft_set_current_renderer( FT_Library  library )
+  {
+    FT_Renderer  renderer;
+
+
+    renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 );
+    library->cur_renderer = renderer;
+  }
+
+
+  static FT_Error
+  ft_add_renderer( FT_Module  module )
+  {
+    FT_Library   library = module->library;
+    FT_Memory    memory  = library->memory;
+    FT_Error     error;
+    FT_ListNode  node;
+
+
+    if ( ALLOC( node, sizeof ( *node ) ) )
+      goto Exit;
+
+    {
+      FT_Renderer         render = FT_RENDERER( module );
+      FT_Renderer_Class*  clazz  = (FT_Renderer_Class*)module->clazz;
+
+
+      render->clazz        = clazz;
+      render->glyph_format = clazz->glyph_format;
+
+      /* allocate raster object if needed */
+      if ( clazz->glyph_format == ft_glyph_format_outline &&
+           clazz->raster_class->raster_new )
+      {
+        error = clazz->raster_class->raster_new( memory, &render->raster );
+        if ( error )
+          goto Fail;
+
+        render->raster_render = clazz->raster_class->raster_render;
+        render->render        = clazz->render_glyph;
+      }
+
+      /* add to list */
+      node->data = module;
+      FT_List_Add( &library->renderers, node );
+
+      ft_set_current_renderer( library );
+    }
+
+  Fail:
+    if ( error )
+      FREE( node );
+
+  Exit:
+    return error;
+  }
+
+
+  static void
+  ft_remove_renderer( FT_Module  module )
+  {
+    FT_Library   library = module->library;
+    FT_Memory    memory  = library->memory;
+    FT_ListNode  node;
+
+
+    node = FT_List_Find( &library->renderers, module );
+    if ( node )
+    {
+      FT_Renderer  render = FT_RENDERER( module );
+
+
+      /* release raster object, if any */
+      if ( render->raster )
+        render->clazz->raster_class->raster_done( render->raster );
+
+      /* remove from list */
+      FT_List_Remove( &library->renderers, node );
+      FREE( node );
+
+      ft_set_current_renderer( library );
+    }
+  }
+
+
+  /* documentation is in ftrender.h */
+
+  FT_EXPORT_DEF( FT_Renderer )
+  FT_Get_Renderer( FT_Library       library,
+                   FT_Glyph_Format  format )
+  {
+    /* test for valid `library' delayed to FT_Lookup_Renderer() */
+
+    return  FT_Lookup_Renderer( library, format, 0 );
+  }
+
+
+  /* documentation is in ftrender.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Set_Renderer( FT_Library     library,
+                   FT_Renderer    renderer,
+                   FT_UInt        num_params,
+                   FT_Parameter*  parameters )
+  {
+    FT_ListNode  node;
+    FT_Error     error = FT_Err_Ok;
+
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    if ( !renderer )
+      return FT_Err_Invalid_Argument;
+
+    node = FT_List_Find( &library->renderers, renderer );
+    if ( !node )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    FT_List_Up( &library->renderers, node );
+
+    if ( renderer->glyph_format == ft_glyph_format_outline )
+      library->cur_renderer = renderer;
+
+    if ( num_params > 0 )
+    {
+      FTRenderer_setMode  set_mode = renderer->clazz->set_mode;
+
+
+      for ( ; num_params > 0; num_params-- )
+      {
+        error = set_mode( renderer, parameters->tag, parameters->data );
+        if ( error )
+          break;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Render_Glyph_Internal( FT_Library    library,
+                            FT_GlyphSlot  slot,
+                            FT_UInt       render_mode )
+  {
+    FT_Error     error = FT_Err_Ok;
+    FT_Renderer  renderer;
+
+
+    /* if it is already a bitmap, no need to do anything */
+    switch ( slot->format )
+    {
+    case ft_glyph_format_bitmap:   /* already a bitmap, don't do anything */
+      break;
+
+    default:
+      {
+        FT_ListNode  node   = 0;
+        FT_Bool      update = 0;
+
+
+        /* small shortcut for the very common case */
+        if ( slot->format == ft_glyph_format_outline )
+        {
+          renderer = library->cur_renderer;
+          node     = library->renderers.head;
+        }
+        else
+          renderer = FT_Lookup_Renderer( library, slot->format, &node );
+
+        error = FT_Err_Unimplemented_Feature;
+        while ( renderer )
+        {
+          error = renderer->render( renderer, slot, render_mode, 0 );
+          if ( !error ||
+               FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
+            break;
+
+          /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
+          /* is unsupported by the current renderer for this glyph image */
+          /* format.                                                     */
+
+          /* now, look for another renderer that supports the same */
+          /* format.                                               */
+          renderer = FT_Lookup_Renderer( library, slot->format, &node );
+          update   = 1;
+        }
+
+        /* if we changed the current renderer for the glyph image format */
+        /* we need to select it as the next current one                  */
+        if ( !error && update && renderer )
+          FT_Set_Renderer( library, renderer, 0, 0 );
+      }
+    }
+
+    return error;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Render_Glyph( FT_GlyphSlot  slot,
+                   FT_UInt       render_mode )
+  {
+    FT_Library   library;
+
+
+    if ( !slot )
+      return FT_Err_Invalid_Argument;
+
+    library = FT_FACE_LIBRARY( slot->face );
+
+    return FT_Render_Glyph_Internal( library, slot, render_mode );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                         M O D U L E S                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Destroy_Module                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given module object.  For drivers, this also destroys   */
+  /*    all child faces.                                                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*     module :: A handle to the target driver object.                   */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*     The driver _must_ be LOCKED!                                      */
+  /*                                                                       */
+  static void
+  Destroy_Module( FT_Module  module )
+  {
+    FT_Memory         memory  = module->memory;
+    FT_Module_Class*  clazz   = module->clazz;
+    FT_Library        library = module->library;
+
+
+    /* finalize client-data - before anything else */
+    if ( module->generic.finalizer )
+      module->generic.finalizer( module );
+
+    if ( library && library->auto_hinter == module )
+      library->auto_hinter = 0;
+
+    /* if the module is a renderer */
+    if ( FT_MODULE_IS_RENDERER( module ) )
+      ft_remove_renderer( module );
+
+    /* if the module is a font driver, add some steps */
+    if ( FT_MODULE_IS_DRIVER( module ) )
+      Destroy_Driver( FT_DRIVER( module ) );
+
+    /* finalize the module object */
+    if ( clazz->module_done )
+      clazz->module_done( module );
+
+    /* discard it */
+    FREE( module );
+  }
+
+
+  /* documentation is in ftmodule.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Add_Module( FT_Library              library,
+                 const FT_Module_Class*  clazz )
+  {
+    FT_Error   error;
+    FT_Memory  memory;
+    FT_Module  module;
+    FT_UInt    nn;
+
+
+#define FREETYPE_VER_FIXED  ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
+                                FREETYPE_MINOR                  )
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    if ( !clazz )
+      return FT_Err_Invalid_Argument;
+
+    /* check freetype version */
+    if ( clazz->module_requires > FREETYPE_VER_FIXED )
+      return FT_Err_Invalid_Version;
+
+    /* look for a module with the same name in the library's table */
+    for ( nn = 0; nn < library->num_modules; nn++ )
+    {
+      module = library->modules[nn];
+      if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
+      {
+        /* this installed module has the same name, compare their versions */
+        if ( clazz->module_version <= module->clazz->module_version )
+          return FT_Err_Lower_Module_Version;
+
+        /* remove the module from our list, then exit the loop to replace */
+        /* it by our new version..                                        */
+        FT_Remove_Module( library, module );
+        break;
+      }
+    }
+
+    memory = library->memory;
+    error  = FT_Err_Ok;
+
+    if ( library->num_modules >= FT_MAX_MODULES )
+    {
+      error = FT_Err_Too_Many_Drivers;
+      goto Exit;
+    }
+
+    /* allocate module object */
+    if ( ALLOC( module,clazz->module_size ) )
+      goto Exit;
+
+    /* base initialization */
+    module->library = library;
+    module->memory  = memory;
+    module->clazz   = (FT_Module_Class*)clazz;
+
+    /* check whether the module is a renderer - this must be performed */
+    /* before the normal module initialization                         */
+    if ( FT_MODULE_IS_RENDERER( module ) )
+    {
+      /* add to the renderers list */
+      error = ft_add_renderer( module );
+      if ( error )
+        goto Fail;
+    }
+
+    /* is the module a auto-hinter? */
+    if ( FT_MODULE_IS_HINTER( module ) )
+      library->auto_hinter = module;
+
+    /* if the module is a font driver */
+    if ( FT_MODULE_IS_DRIVER( module ) )
+    {
+      /* allocate glyph loader if needed */
+      FT_Driver   driver = FT_DRIVER( module );
+
+
+      driver->clazz = (FT_Driver_Class*)module->clazz;
+      if ( FT_DRIVER_USES_OUTLINES( driver ) )
+      {
+        error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
+        if ( error )
+          goto Fail;
+      }
+    }
+
+    if ( clazz->module_init )
+    {
+      error = clazz->module_init( module );
+      if ( error )
+        goto Fail;
+    }
+
+    /* add module to the library's table */
+    library->modules[library->num_modules++] = module;
+
+  Exit:
+    return error;
+
+  Fail:
+    if ( FT_MODULE_IS_DRIVER( module ) )
+    {
+      FT_Driver  driver = FT_DRIVER( module );
+
+
+      if ( FT_DRIVER_USES_OUTLINES( driver ) )
+        FT_GlyphLoader_Done( driver->glyph_loader );
+    }
+
+    if ( FT_MODULE_IS_RENDERER( module ) )
+    {
+      FT_Renderer  renderer = FT_RENDERER( module );
+
+
+      if ( renderer->raster )
+        renderer->clazz->raster_class->raster_done( renderer->raster );
+    }
+
+    FREE( module );
+    goto Exit;
+  }
+
+
+  /* documentation is in ftmodule.h */
+
+  FT_EXPORT_DEF( FT_Module )
+  FT_Get_Module( FT_Library   library,
+                 const char*  module_name )
+  {
+    FT_Module   result = 0;
+    FT_Module*  cur;
+    FT_Module*  limit;
+
+
+    if ( !library || !module_name )
+      return result;
+
+    cur   = library->modules;
+    limit = cur + library->num_modules;
+
+    for ( ; cur < limit; cur++ )
+      if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
+      {
+        result = cur[0];
+        break;
+      }
+
+    return result;
+  }
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_BASE_DEF( const void* )
+  FT_Get_Module_Interface( FT_Library   library,
+                           const char*  mod_name )
+  {
+    FT_Module  module;
+
+
+    /* test for valid `library' delayed to FT_Get_Module() */
+
+    module = FT_Get_Module( library, mod_name );
+
+    return module ? module->clazz->module_interface : 0;
+  }
+
+
+  /* documentation is in ftmodule.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Remove_Module( FT_Library  library,
+                    FT_Module   module )
+  {
+    /* try to find the module from the table, then remove it from there */
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    if ( module )
+    {
+      FT_Module*  cur   = library->modules;
+      FT_Module*  limit = cur + library->num_modules;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        if ( cur[0] == module )
+        {
+          /* remove it from the table */
+          library->num_modules--;
+          limit--;
+          while ( cur < limit )
+          {
+            cur[0] = cur[1];
+            cur++;
+          }
+          limit[0] = 0;
+
+          /* destroy the module */
+          Destroy_Module( module );
+
+          return FT_Err_Ok;
+        }
+      }
+    }
+    return FT_Err_Invalid_Driver_Handle;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                         L I B R A R Y                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* documentation is in ftmodule.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_New_Library( FT_Memory    memory,
+                  FT_Library  *alibrary )
+  {
+    FT_Library  library = 0;
+    FT_Error    error;
+
+
+    if ( !memory )
+      return FT_Err_Invalid_Argument;
+
+    /* first of all, allocate the library object */
+    if ( ALLOC( library, sizeof ( *library ) ) )
+      return error;
+
+    library->memory = memory;
+
+    /* allocate the render pool */
+    library->raster_pool_size = FT_RENDER_POOL_SIZE;
+    if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
+      goto Fail;
+
+    /* That's ok now */
+    *alibrary = library;
+
+    return FT_Err_Ok;
+
+  Fail:
+    FREE( library );
+    return error;
+  }
+
+
+  /* documentation is in ftmodule.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Done_Library( FT_Library  library )
+  {
+    FT_Memory  memory;
+    FT_UInt    n;
+
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    memory = library->memory;
+
+    /* Discard client-data */
+    if ( library->generic.finalizer )
+      library->generic.finalizer( library );
+
+    /* Close all modules in the library */
+    for ( n = 0; n < library->num_modules; n++ )
+    {
+      FT_Module  module = library->modules[n];
+
+
+      if ( module )
+      {
+        Destroy_Module( module );
+        library->modules[n] = 0;
+      }
+    }
+
+    /* Destroy raster objects */
+    FREE( library->raster_pool );
+    library->raster_pool_size = 0;
+
+    FREE( library );
+    return FT_Err_Ok;
+  }
+
+
+  /* documentation is in ftmodule.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Set_Debug_Hook( FT_Library         library,
+                     FT_UInt            hook_index,
+                     FT_DebugHook_Func  debug_hook )
+  {
+    if ( library && debug_hook &&
+         hook_index <
+           ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
+      library->debug_hooks[hook_index] = debug_hook;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftoutln.c b/libraries/freetype-2.0.5/ftoutln.c
new file mode 100644 (file)
index 0000000..c7e3c08
--- /dev/null
@@ -0,0 +1,611 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftoutln.c                                                              */
+/*                                                                         */
+/*    FreeType outline management (body).                                  */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* All functions are declared in freetype.h.                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_OUTLINE_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_outline
+
+
+  static
+  const FT_Outline  null_outline = { 0, 0, 0, 0, 0, 0 };
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_Decompose( FT_Outline*              outline,
+                        const FT_Outline_Funcs*  interface,
+                        void*                    user )
+  {
+#undef SCALED
+#define SCALED( x )  ( ( (x) << shift ) - delta )
+
+    FT_Vector   v_last;
+    FT_Vector   v_control;
+    FT_Vector   v_start;
+
+    FT_Vector*  point;
+    FT_Vector*  limit;
+    char*       tags;
+
+    FT_Error    error;
+
+    FT_Int   n;         /* index of contour in outline     */
+    FT_UInt  first;     /* index of first point in contour */
+    FT_Int   tag;       /* current point's state           */
+
+    FT_Int   shift;
+    FT_Pos   delta;
+
+
+    if ( !outline || !interface )
+      return FT_Err_Invalid_Argument;
+
+    shift = interface->shift;
+    delta = interface->delta;
+    first = 0;
+
+    for ( n = 0; n < outline->n_contours; n++ )
+    {
+      FT_Int  last;  /* index of last point in contour */
+
+
+      last  = outline->contours[n];
+      limit = outline->points + last;
+
+      v_start = outline->points[first];
+      v_last  = outline->points[last];
+
+      v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
+      v_last.x  = SCALED( v_last.x );  v_last.y  = SCALED( v_last.y );
+
+      v_control = v_start;
+
+      point = outline->points + first;
+      tags  = outline->tags  + first;
+      tag   = FT_CURVE_TAG( tags[0] );
+
+      /* A contour cannot start with a cubic control point! */
+      if ( tag == FT_Curve_Tag_Cubic )
+        goto Invalid_Outline;
+
+      /* check first point to determine origin */
+      if ( tag == FT_Curve_Tag_Conic )
+      {
+        /* first point is conic control.  Yes, this happens. */
+        if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
+        {
+          /* start at last point if it is on the curve */
+          v_start = v_last;
+          limit--;
+        }
+        else
+        {
+          /* if both first and last points are conic,         */
+          /* start at their middle and record its position    */
+          /* for closure                                      */
+          v_start.x = ( v_start.x + v_last.x ) / 2;
+          v_start.y = ( v_start.y + v_last.y ) / 2;
+
+          v_last = v_start;
+        }
+        point--;
+        tags--;
+      }
+
+      error = interface->move_to( &v_start, user );
+      if ( error )
+        goto Exit;
+
+      while ( point < limit )
+      {
+        point++;
+        tags++;
+
+        tag = FT_CURVE_TAG( tags[0] );
+        switch ( tag )
+        {
+        case FT_Curve_Tag_On:  /* emit a single line_to */
+          {
+            FT_Vector  vec;
+
+
+            vec.x = SCALED( point->x );
+            vec.y = SCALED( point->y );
+
+            error = interface->line_to( &vec, user );
+            if ( error )
+              goto Exit;
+            continue;
+          }
+
+        case FT_Curve_Tag_Conic:  /* consume conic arcs */
+          v_control.x = SCALED( point->x );
+          v_control.y = SCALED( point->y );
+
+        Do_Conic:
+          if ( point < limit )
+          {
+            FT_Vector  vec;
+            FT_Vector  v_middle;
+
+
+            point++;
+            tags++;
+            tag = FT_CURVE_TAG( tags[0] );
+
+            vec.x = SCALED( point->x );
+            vec.y = SCALED( point->y );
+
+            if ( tag == FT_Curve_Tag_On )
+            {
+              error = interface->conic_to( &v_control, &vec, user );
+              if ( error )
+                goto Exit;
+              continue;
+            }
+
+            if ( tag != FT_Curve_Tag_Conic )
+              goto Invalid_Outline;
+
+            v_middle.x = ( v_control.x + vec.x ) / 2;
+            v_middle.y = ( v_control.y + vec.y ) / 2;
+
+            error = interface->conic_to( &v_control, &v_middle, user );
+            if ( error )
+              goto Exit;
+
+            v_control = vec;
+            goto Do_Conic;
+          }
+
+          error = interface->conic_to( &v_control, &v_start, user );
+          goto Close;
+
+        default:  /* FT_Curve_Tag_Cubic */
+          {
+            FT_Vector  vec1, vec2;
+
+
+            if ( point + 1 > limit                             ||
+                 FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+              goto Invalid_Outline;
+
+            point += 2;
+            tags  += 2;
+
+            vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
+            vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
+
+            if ( point <= limit )
+            {
+              FT_Vector  vec;
+
+
+              vec.x = SCALED( point->x );
+              vec.y = SCALED( point->y );
+
+              error = interface->cubic_to( &vec1, &vec2, &vec, user );
+              if ( error )
+                goto Exit;
+              continue;
+            }
+
+            error = interface->cubic_to( &vec1, &vec2, &v_start, user );
+            goto Close;
+          }
+        }
+      }
+
+      /* close the contour with a line segment */
+      error = interface->line_to( &v_start, user );
+
+    Close:
+      if ( error )
+        goto Exit;
+
+      first = last + 1;
+    }
+
+    return 0;
+
+  Exit:
+    return error;
+
+  Invalid_Outline:
+    return FT_Err_Invalid_Outline;
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_New_Internal( FT_Memory    memory,
+                           FT_UInt      numPoints,
+                           FT_Int       numContours,
+                           FT_Outline  *anoutline )
+  {
+    FT_Error  error;
+
+
+    if ( !anoutline || !memory )
+      return FT_Err_Invalid_Argument;
+
+    *anoutline = null_outline;
+
+    if ( ALLOC_ARRAY( anoutline->points,   numPoints * 2L, FT_Pos    ) ||
+         ALLOC_ARRAY( anoutline->tags,     numPoints,      FT_Byte   ) ||
+         ALLOC_ARRAY( anoutline->contours, numContours,    FT_UShort ) )
+      goto Fail;
+
+    anoutline->n_points    = (FT_UShort)numPoints;
+    anoutline->n_contours  = (FT_Short)numContours;
+    anoutline->flags      |= ft_outline_owner;
+
+    return FT_Err_Ok;
+
+  Fail:
+    anoutline->flags |= ft_outline_owner;
+    FT_Outline_Done_Internal( memory, anoutline );
+
+    return error;
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_New( FT_Library   library,
+                  FT_UInt      numPoints,
+                  FT_Int       numContours,
+                  FT_Outline  *anoutline )
+  {
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    return FT_Outline_New_Internal( library->memory, numPoints,
+                                    numContours, anoutline );
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_Copy( FT_Outline*  source,
+                   FT_Outline  *target )
+  {
+    FT_Int  is_owner;
+
+
+    if ( !source            || !target            ||
+         source->n_points   != target->n_points   ||
+         source->n_contours != target->n_contours )
+      return FT_Err_Invalid_Argument;
+
+    MEM_Copy( target->points, source->points,
+              source->n_points * sizeof ( FT_Vector ) );
+
+    MEM_Copy( target->tags, source->tags,
+              source->n_points * sizeof ( FT_Byte ) );
+
+    MEM_Copy( target->contours, source->contours,
+              source->n_contours * sizeof ( FT_Short ) );
+
+    /* copy all flags, except the `ft_outline_owner' one */
+    is_owner      = target->flags & ft_outline_owner;
+    target->flags = source->flags;
+
+    target->flags &= ~ft_outline_owner;
+    target->flags |= is_owner;
+
+    return FT_Err_Ok;
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_Done_Internal( FT_Memory    memory,
+                            FT_Outline*  outline )
+  {
+    if ( outline )
+    {
+      if ( outline->flags & ft_outline_owner )
+      {
+        FREE( outline->points   );
+        FREE( outline->tags     );
+        FREE( outline->contours );
+      }
+      *outline = null_outline;
+
+      return FT_Err_Ok;
+    }
+    else
+      return FT_Err_Invalid_Argument;
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_Done( FT_Library   library,
+                   FT_Outline*  outline )
+  {
+    /* check for valid `outline' in FT_Outline_Done_Internal() */
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    return FT_Outline_Done_Internal( library->memory, outline );
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Outline_Get_CBox( FT_Outline*  outline,
+                       FT_BBox     *acbox )
+  {
+    FT_Pos  xMin, yMin, xMax, yMax;
+
+
+    if ( outline && acbox )
+    {
+      if ( outline->n_points == 0 )
+      {
+        xMin = 0;
+        yMin = 0;
+        xMax = 0;
+        yMax = 0;
+      }
+      else
+      {
+        FT_Vector*  vec   = outline->points;
+        FT_Vector*  limit = vec + outline->n_points;
+
+
+        xMin = xMax = vec->x;
+        yMin = yMax = vec->y;
+        vec++;
+
+        for ( ; vec < limit; vec++ )
+        {
+          FT_Pos  x, y;
+
+
+          x = vec->x;
+          if ( x < xMin ) xMin = x;
+          if ( x > xMax ) xMax = x;
+
+          y = vec->y;
+          if ( y < yMin ) yMin = y;
+          if ( y > yMax ) yMax = y;
+        }
+      }
+      acbox->xMin = xMin;
+      acbox->xMax = xMax;
+      acbox->yMin = yMin;
+      acbox->yMax = yMax;
+    }
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Outline_Translate( FT_Outline*  outline,
+                        FT_Pos       xOffset,
+                        FT_Pos       yOffset )
+  {
+    FT_UShort   n;
+    FT_Vector*  vec = outline->points;
+
+
+    for ( n = 0; n < outline->n_points; n++ )
+    {
+      vec->x += xOffset;
+      vec->y += yOffset;
+      vec++;
+    }
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Outline_Reverse( FT_Outline*  outline )
+  {
+    FT_UShort  n;
+    FT_Int     first, last;
+
+
+    first = 0;
+
+    for ( n = 0; n < outline->n_contours; n++ )
+    {
+      last  = outline->contours[n];
+
+      /* reverse point table */
+      {
+        FT_Vector*  p = outline->points + first;
+        FT_Vector*  q = outline->points + last;
+        FT_Vector   swap;
+
+
+        while ( p < q )
+        {
+          swap = *p;
+          *p   = *q;
+          *q   = swap;
+          p++;
+          q--;
+        }
+      }
+
+      /* reverse tags table */
+      {
+        char*  p = outline->tags + first;
+        char*  q = outline->tags + last;
+        char   swap;
+
+
+        while ( p < q )
+        {
+          swap = *p;
+          *p   = *q;
+          *q   = swap;
+          p++;
+          q--;
+        }
+      }
+
+      first = last + 1;
+    }
+
+    outline->flags ^= ft_outline_reverse_fill;
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_Render( FT_Library         library,
+                     FT_Outline*        outline,
+                     FT_Raster_Params*  params )
+  {
+    FT_Error     error;
+    FT_Bool      update = 0;
+    FT_Renderer  renderer;
+    FT_ListNode  node;
+
+
+    if ( !library )
+      return FT_Err_Invalid_Library_Handle;
+
+    if ( !params )
+      return FT_Err_Invalid_Argument;
+
+    renderer = library->cur_renderer;
+    node     = library->renderers.head;
+
+    params->source = (void*)outline;
+
+    error = FT_Err_Cannot_Render_Glyph;
+    while ( renderer )
+    {
+      error = renderer->raster_render( renderer->raster, params );
+      if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
+        break;
+
+      /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
+      /* is unsupported by the current renderer for this glyph image */
+      /* format                                                      */
+
+      /* now, look for another renderer that supports the same */
+      /* format                                                */
+      renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline,
+                                     &node );
+      update   = 1;
+    }
+
+    /* if we changed the current renderer for the glyph image format */
+    /* we need to select it as the next current one                  */
+    if ( !error && update && renderer )
+      FT_Set_Renderer( library, renderer, 0, 0 );
+
+    return error;
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_Get_Bitmap( FT_Library   library,
+                         FT_Outline*  outline,
+                         FT_Bitmap   *abitmap )
+  {
+    FT_Raster_Params  params;
+
+
+    if ( !abitmap )
+      return FT_Err_Invalid_Argument;
+
+    /* other checks are delayed to FT_Outline_Render() */
+
+    params.target = abitmap;
+    params.flags  = 0;
+
+    if ( abitmap->pixel_mode == ft_pixel_mode_grays )
+      params.flags |= ft_raster_flag_aa;
+
+    return FT_Outline_Render( library, outline, &params );
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Vector_Transform( FT_Vector*  vector,
+                       FT_Matrix*  matrix )
+  {
+    FT_Pos xz, yz;
+
+
+    if ( !vector || !matrix )
+      return;
+
+    xz = FT_MulFix( vector->x, matrix->xx ) +
+         FT_MulFix( vector->y, matrix->xy );
+
+    yz = FT_MulFix( vector->x, matrix->yx ) +
+         FT_MulFix( vector->y, matrix->yy );
+
+    vector->x = xz;
+    vector->y = yz;
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Outline_Transform( FT_Outline*  outline,
+                        FT_Matrix*   matrix )
+  {
+    FT_Vector*  vec = outline->points;
+    FT_Vector*  limit = vec + outline->n_points;
+
+
+    for ( ; vec < limit; vec++ )
+      FT_Vector_Transform( vec, matrix );
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftraster.c b/libraries/freetype-2.0.5/ftraster.c
new file mode 100644 (file)
index 0000000..33d42b6
--- /dev/null
@@ -0,0 +1,3283 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftraster.c                                                             */
+/*                                                                         */
+/*    The FreeType glyph rasterizer (body).                                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This is a rewrite of the FreeType 1.x scan-line converter             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include "ftraster.h"
+#include FT_INTERNAL_CALC_H   /* for FT_MulDiv only */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A simple technical note on how the raster works                       */
+  /* -----------------------------------------------                       */
+  /*                                                                       */
+  /*   Converting an outline into a bitmap is achieved in several steps:   */
+  /*                                                                       */
+  /*   1 - Decomposing the outline into successive `profiles'.  Each       */
+  /*       profile is simply an array of scanline intersections on a given */
+  /*       dimension.  A profile's main attributes are                     */
+  /*                                                                       */
+  /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'.     */
+  /*                                                                       */
+  /*       o an array of intersection coordinates for each scanline        */
+  /*         between `Ymin' and `Ymax'.                                    */
+  /*                                                                       */
+  /*       o a direction, indicating whether it was built going `up' or    */
+  /*         `down', as this is very important for filling rules.          */
+  /*                                                                       */
+  /*   2 - Sweeping the target map's scanlines in order to compute segment */
+  /*       `spans' which are then filled.  Additionally, this pass         */
+  /*       performs drop-out control.                                      */
+  /*                                                                       */
+  /*   The outline data is parsed during step 1 only.  The profiles are    */
+  /*   built from the bottom of the render pool, used as a stack.  The     */
+  /*   following graphics shows the profile list under construction:       */
+  /*                                                                       */
+  /*     ____________________________________________________________ _ _  */
+  /*    |         |                   |         |                 |        */
+  /*    | profile | coordinates for   | profile | coordinates for |-->     */
+  /*    |    1    |  profile 1        |    2    |  profile 2      |-->     */
+  /*    |_________|___________________|_________|_________________|__ _ _  */
+  /*                                                                       */
+  /*    ^                                                         ^        */
+  /*    |                                                         |        */
+  /*  start of render pool                                       top       */
+  /*                                                                       */
+  /*   The top of the profile stack is kept in the `top' variable.         */
+  /*                                                                       */
+  /*   As you can see, a profile record is pushed on top of the render     */
+  /*   pool, which is then followed by its coordinates/intersections.  If  */
+  /*   a change of direction is detected in the outline, a new profile is  */
+  /*   generated until the end of the outline.                             */
+  /*                                                                       */
+  /*   Note that when all profiles have been generated, the function       */
+  /*   Finalize_Profile_Table() is used to record, for each profile, its   */
+  /*   bottom-most scanline as well as the scanline above its upmost       */
+  /*   boundary.  These positions are called `y-turns' because they (sort  */
+  /*   of) correspond to local extrema.  They are stored in a sorted list  */
+  /*   built from the top of the render pool as a downwards stack:         */
+  /*                                                                       */
+  /*      _ _ _______________________________________                      */
+  /*                            |                    |                     */
+  /*                         <--| sorted list of     |                     */
+  /*                         <--|  extrema scanlines |                     */
+  /*      _ _ __________________|____________________|                     */
+  /*                                                                       */
+  /*                            ^                    ^                     */
+  /*                            |                    |                     */
+  /*                         maxBuff           sizeBuff = end of pool      */
+  /*                                                                       */
+  /*   This list is later used during the sweep phase in order to          */
+  /*   optimize performance (see technical note on the sweep below).       */
+  /*                                                                       */
+  /*   Of course, the raster detects whether the two stacks collide and    */
+  /*   handles the situation propertly.                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  CONFIGURATION MACROS                                               **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* define DEBUG_RASTER if you want to compile a debugging version */
+#define xxxDEBUG_RASTER
+
+  /* The default render pool size in bytes */
+#define RASTER_RENDER_POOL  8192
+
+  /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
+  /* 5-levels anti-aliasing                                                */
+#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
+#define FT_RASTER_OPTION_ANTI_ALIASING
+#endif
+
+  /* The size of the two-lines intermediate bitmap used */
+  /* for anti-aliasing, in bytes.                       */
+#define RASTER_GRAY_LINES  2048
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  OTHER MACROS (do not change)                                       **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_raster
+
+
+#ifdef _STANDALONE_
+
+
+  /* This macro is used to indicate that a function parameter is unused. */
+  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
+  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+  /* ANSI compilers (e.g. LCC).                                          */
+#define FT_UNUSED( x )  (x) = (x)
+
+  /* Disable the tracing mechanism for simplicity -- developers can      */
+  /* activate it easily by redefining these two macros.                  */
+#ifndef FT_ERROR
+#define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+#define Raster_Err_None          0
+#define Raster_Err_Not_Ini      -1
+#define Raster_Err_Overflow     -2
+#define Raster_Err_Neg_Height   -3
+#define Raster_Err_Invalid      -4
+#define Raster_Err_Unsupported  -5
+
+
+#else /* _STANDALONE_ */
+
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H        /* for FT_TRACE() and FT_ERROR() */
+
+#include "rasterrs.h"
+
+#define Raster_Err_None         Raster_Err_Ok
+#define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized
+#define Raster_Err_Overflow     Raster_Err_Raster_Overflow
+#define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height
+#define Raster_Err_Invalid      Raster_Err_Invalid_Outline
+#define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
+
+
+#endif /* _STANDALONE_ */
+
+
+  /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
+  /* typically a small value and the result of a*b is known to fit into */
+  /* 32 bits.                                                           */
+#define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
+
+  /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
+  /* for clipping computations.  It simply uses the FT_MulDiv() function   */
+  /* defined in `ftcalc.h'.                                                */
+#define SMulDiv  FT_MulDiv
+
+  /* The rasterizer is a very general purpose component; please leave */
+  /* the following redefinitions there (you never know your target    */
+  /* environment).                                                    */
+
+#ifndef TRUE
+#define TRUE   1
+#endif
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#ifndef NULL
+#define NULL  (void*)0
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS  0
+#endif
+
+#ifndef FAILURE
+#define FAILURE  1
+#endif
+
+
+#define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
+                        /* Setting this constant to more than 32 is a   */
+                        /* pure waste of space.                         */
+
+#define Pixel_Bits  6   /* fractional bits of *input* coordinates */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  SIMPLE TYPE DECLARATIONS                                           **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  typedef int             Int;
+  typedef unsigned int    UInt;
+  typedef short           Short;
+  typedef unsigned short  UShort, *PUShort;
+  typedef long            Long, *PLong;
+  typedef unsigned long   ULong;
+
+  typedef unsigned char   Byte, *PByte;
+  typedef char            Bool;
+
+  typedef struct  TPoint_
+  {
+    Long  x;
+    Long  y;
+
+  } TPoint;
+
+
+  typedef enum  TFlow_
+  {
+    Flow_None = 0,
+    Flow_Up   = 1,
+    Flow_Down = -1
+
+  } TFlow;
+
+
+  /* States of each line, arc, and profile */
+  typedef enum  TStates_
+  {
+    Unknown,
+    Ascending,
+    Descending,
+    Flat
+
+  } TStates;
+
+
+  typedef struct TProfile_  TProfile;
+  typedef TProfile*         PProfile;
+
+  struct  TProfile_
+  {
+    FT_F26Dot6  X;           /* current coordinate during sweep        */
+    PProfile    link;        /* link to next profile - various purpose */
+    PLong       offset;      /* start of profile's data in render pool */
+    int         flow;        /* Profile orientation: Asc/Descending    */
+    long        height;      /* profile's height in scanlines          */
+    long        start;       /* profile's starting scanline            */
+
+    unsigned    countL;      /* number of lines to step before this    */
+                             /* profile becomes drawable               */
+
+    PProfile    next;        /* next profile in same contour, used     */
+                             /* during drop-out control                */
+  };
+
+  typedef PProfile   TProfileList;
+  typedef PProfile*  PProfileList;
+
+
+  /* Simple record used to implement a stack of bands, required */
+  /* by the sub-banding mechanism                               */
+  typedef struct  TBand_
+  {
+    Short  y_min;   /* band's minimum */
+    Short  y_max;   /* band's maximum */
+
+  } TBand;
+
+
+#define AlignProfileSize \
+          ( ( sizeof ( TProfile ) + sizeof ( long ) - 1 ) / sizeof ( long ) )
+
+
+#ifdef TT_STATIC_RASTER
+
+
+#define RAS_ARGS       /* void */
+#define RAS_ARG        /* void */
+
+#define RAS_VARS       /* void */
+#define RAS_VAR        /* void */
+
+#define FT_UNUSED_RASTER  do ; while ( 0 )
+
+
+#else /* TT_STATIC_RASTER */
+
+
+#define RAS_ARGS       TRaster_Instance*  raster,
+#define RAS_ARG        TRaster_Instance*  raster
+
+#define RAS_VARS       raster,
+#define RAS_VAR        raster
+
+#define FT_UNUSED_RASTER  FT_UNUSED( raster )
+
+
+#endif /* TT_STATIC_RASTER */
+
+
+  typedef struct TRaster_Instance_  TRaster_Instance;
+
+
+  /* prototypes used for sweep function dispatch */
+  typedef void
+  Function_Sweep_Init( RAS_ARGS Short*  min,
+                                Short*  max );
+
+  typedef void
+  Function_Sweep_Span( RAS_ARGS Short       y,
+                                FT_F26Dot6  x1,
+                                FT_F26Dot6  x2,
+                                PProfile    left,
+                                PProfile    right );
+
+  typedef void
+  Function_Sweep_Step( RAS_ARG );
+
+
+  /* NOTE: These operations are only valid on 2's complement processors */
+
+#define FLOOR( x )    ( (x) & -ras.precision )
+#define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
+#define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
+#define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
+#define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )
+
+  /* Note that I have moved the location of some fields in the */
+  /* structure to ensure that the most used variables are used */
+  /* at the top.  Thus, their offset can be coded with less    */
+  /* opcodes, and it results in a smaller executable.          */
+
+  struct  TRaster_Instance_
+  {
+    Int       precision_bits;       /* precision related variables         */
+    Int       precision;
+    Int       precision_half;
+    Long      precision_mask;
+    Int       precision_shift;
+    Int       precision_step;
+    Int       precision_jitter;
+
+    Int       scale_shift;          /* == precision_shift   for bitmaps    */
+                                    /* == precision_shift+1 for pixmaps    */
+
+    PLong     buff;                 /* The profiles buffer                 */
+    PLong     sizeBuff;             /* Render pool size                    */
+    PLong     maxBuff;              /* Profiles buffer size                */
+    PLong     top;                  /* Current cursor in buffer            */
+
+    FT_Error  error;
+
+    Int       numTurns;             /* number of Y-turns in outline        */
+
+    TPoint*   arc;                  /* current Bezier arc pointer          */
+
+    UShort    bWidth;               /* target bitmap width                 */
+    PByte     bTarget;              /* target bitmap buffer                */
+    PByte     gTarget;              /* target pixmap buffer                */
+
+    Long      lastX, lastY, minY, maxY;
+
+    UShort    num_Profs;            /* current number of profiles          */
+
+    Bool      fresh;                /* signals a fresh new profile which   */
+                                    /* 'start' field must be completed     */
+    Bool      joint;                /* signals that the last arc ended     */
+                                    /* exactly on a scanline.  Allows      */
+                                    /* removal of doublets                 */
+    PProfile  cProfile;             /* current profile                     */
+    PProfile  fProfile;             /* head of linked list of profiles     */
+    PProfile  gProfile;             /* contour's first profile in case     */
+                                    /* of impact                           */
+
+    TStates   state;                /* rendering state                     */
+
+    FT_Bitmap   target;             /* description of target bit/pixmap    */
+    FT_Outline  outline;
+
+    Long      traceOfs;             /* current offset in target bitmap     */
+    Long      traceG;               /* current offset in target pixmap     */
+
+    Short     traceIncr;            /* sweep's increment in target bitmap  */
+
+    Short     gray_min_x;           /* current min x during gray rendering */
+    Short     gray_max_x;           /* current max x during gray rendering */
+
+    /* dispatch variables */
+
+    Function_Sweep_Init*  Proc_Sweep_Init;
+    Function_Sweep_Span*  Proc_Sweep_Span;
+    Function_Sweep_Span*  Proc_Sweep_Drop;
+    Function_Sweep_Step*  Proc_Sweep_Step;
+
+    Byte      dropOutControl;       /* current drop_out control method     */
+
+    Bool      second_pass;          /* indicates wether a horizontal pass  */
+                                    /* should be performed to control      */
+                                    /* drop-out accurately when calling    */
+                                    /* Render_Glyph.  Note that there is   */
+                                    /* no horizontal pass during gray      */
+                                    /* rendering.                          */
+
+    TPoint    arcs[3 * MaxBezier + 1]; /* The Bezier stack                 */
+
+    TBand     band_stack[16];       /* band stack used for sub-banding     */
+    Int       band_top;             /* band stack top                      */
+
+    Int       count_table[256];     /* Look-up table used to quickly count */
+                                    /* set bits in a gray 2x2 cell         */
+
+    void*     memory;
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    Byte      grays[5];             /* Palette of gray levels used for     */
+                                    /* render.                             */
+
+    Byte      gray_lines[RASTER_GRAY_LINES];
+                                /* Intermediate table used to render the   */
+                                /* graylevels pixmaps.                     */
+                                /* gray_lines is a buffer holding two      */
+                                /* monochrome scanlines                    */
+
+    Short     gray_width;       /* width in bytes of one monochrome        */
+                                /* intermediate scanline of gray_lines.    */
+                                /* Each gray pixel takes 2 bits long there */
+
+                       /* The gray_lines must hold 2 lines, thus with size */
+                       /* in bytes of at least `gray_width*2'.             */
+
+#endif /* FT_RASTER_ANTI_ALIASING */
+
+#if 0
+    PByte       flags;              /* current flags table                 */
+    PUShort     outs;               /* current outlines table              */
+    FT_Vector*  coords;
+
+    UShort      nPoints;            /* number of points in current glyph   */
+    Short       nContours;          /* number of contours in current glyph */
+#endif
+
+  };
+
+
+#ifdef FT_CONFIG_OPTION_STATIC_RASTER
+
+  static TRaster_Instance  cur_ras;
+#define ras  cur_ras
+
+#else
+
+#define ras  (*raster)
+
+#endif /* FT_CONFIG_OPTION_STATIC_RASTER */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  PROFILES COMPUTATION                                               **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_High_Precision                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets precision variables according to param flag.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    High :: Set to True for high precision (typically for ppem < 18),  */
+  /*            false otherwise.                                           */
+  /*                                                                       */
+  static void
+  Set_High_Precision( RAS_ARGS Int  High )
+  {
+    if ( High )
+    {
+      ras.precision_bits   = 10;
+      ras.precision_step   = 128;
+      ras.precision_jitter = 24;
+    }
+    else
+    {
+      ras.precision_bits   = 6;
+      ras.precision_step   = 32;
+      ras.precision_jitter = 2;
+    }
+
+    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
+
+    ras.precision       = 1L << ras.precision_bits;
+    ras.precision_half  = ras.precision / 2;
+    ras.precision_shift = ras.precision_bits - Pixel_Bits;
+    ras.precision_mask  = -ras.precision;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    New_Profile                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new profile in the render pool.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    aState :: The state/orientation of the new profile.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static Bool
+  New_Profile( RAS_ARGS TStates  aState )
+  {
+    if ( !ras.fProfile )
+    {
+      ras.cProfile  = (PProfile)ras.top;
+      ras.fProfile  = ras.cProfile;
+      ras.top      += AlignProfileSize;
+    }
+
+    if ( ras.top >= ras.maxBuff )
+    {
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    switch ( aState )
+    {
+    case Ascending:
+      ras.cProfile->flow = Flow_Up;
+      FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
+      break;
+
+    case Descending:
+      ras.cProfile->flow = Flow_Down;
+      FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
+      break;
+
+    default:
+      FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
+      ras.error = Raster_Err_Invalid;
+      return FAILURE;
+    }
+
+    ras.cProfile->start  = 0;
+    ras.cProfile->height = 0;
+    ras.cProfile->offset = ras.top;
+    ras.cProfile->link   = (PProfile)0;
+    ras.cProfile->next   = (PProfile)0;
+
+    if ( !ras.gProfile )
+      ras.gProfile = ras.cProfile;
+
+    ras.state = aState;
+    ras.fresh = TRUE;
+    ras.joint = FALSE;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    End_Profile                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes the current profile.                                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
+  /*                                                                       */
+  static Bool
+  End_Profile( RAS_ARG )
+  {
+    Long      h;
+    PProfile  oldProfile;
+
+
+    h = (Long)( ras.top - ras.cProfile->offset );
+
+    if ( h < 0 )
+    {
+      FT_ERROR(( "End_Profile: negative height encountered!\n" ));
+      ras.error = Raster_Err_Neg_Height;
+      return FAILURE;
+    }
+
+    if ( h > 0 )
+    {
+      FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
+                  (long)ras.cProfile, ras.cProfile->start, h ));
+
+      oldProfile           = ras.cProfile;
+      ras.cProfile->height = h;
+      ras.cProfile         = (PProfile)ras.top;
+
+      ras.top             += AlignProfileSize;
+
+      ras.cProfile->height = 0;
+      ras.cProfile->offset = ras.top;
+      oldProfile->next     = ras.cProfile;
+      ras.num_Profs++;
+    }
+
+    if ( ras.top >= ras.maxBuff )
+    {
+      FT_TRACE1(( "overflow in End_Profile\n" ));
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    ras.joint = FALSE;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Insert_Y_Turn                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Inserts a salient into the sorted list placed on top of the render */
+  /*    pool.                                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    New y scanline position.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
+  /*                                                                       */
+  static Bool
+  Insert_Y_Turn( RAS_ARGS Int  y )
+  {
+    PLong     y_turns;
+    Int       y2, n;
+
+
+    n       = ras.numTurns - 1;
+    y_turns = ras.sizeBuff - ras.numTurns;
+
+    /* look for first y value that is <= */
+    while ( n >= 0 && y < y_turns[n] )
+      n--;
+
+    /* if it is <, simply insert it, ignore if == */
+    if ( n >= 0 && y > y_turns[n] )
+      while ( n >= 0 )
+      {
+        y2 = y_turns[n];
+        y_turns[n] = y;
+        y = y2;
+        n--;
+      }
+
+    if ( n < 0 )
+    {
+      if ( ras.maxBuff <= ras.top )
+      {
+        ras.error = Raster_Err_Overflow;
+        return FAILURE;
+      }
+      ras.maxBuff--;
+      ras.numTurns++;
+      ras.sizeBuff[-ras.numTurns] = y;
+    }
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Finalize_Profile_Table                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adjusts all links in the profiles list.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
+  /*                                                                       */
+  static Bool
+  Finalize_Profile_Table( RAS_ARG )
+  {
+    Int       bottom, top;
+    UShort    n;
+    PProfile  p;
+
+
+    n = ras.num_Profs;
+
+    if ( n > 1 )
+    {
+      p = ras.fProfile;
+      while ( n > 0 )
+      {
+        if ( n > 1 )
+          p->link = (PProfile)( p->offset + p->height );
+        else
+          p->link = NULL;
+
+        switch ( p->flow )
+        {
+        case Flow_Down:
+          bottom     = p->start - p->height+1;
+          top        = p->start;
+          p->start   = bottom;
+          p->offset += p->height - 1;
+          break;
+
+        case Flow_Up:
+        default:
+          bottom = p->start;
+          top    = p->start + p->height - 1;
+        }
+
+        if ( Insert_Y_Turn( RAS_VARS bottom )   ||
+             Insert_Y_Turn( RAS_VARS top + 1 )  )
+          return FAILURE;
+
+        p = p->link;
+        n--;
+      }
+    }
+    else
+      ras.fProfile = NULL;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Split_Conic                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Subdivides one conic Bezier into two joint sub-arcs in the Bezier  */
+  /*    stack.                                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    None (subdivided Bezier is taken from the top of the stack).       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This routine is the `beef' of this component.  It is  _the_ inner  */
+  /*    loop that should be optimized to hell to get the best performance. */
+  /*                                                                       */
+  static void
+  Split_Conic( TPoint*  base )
+  {
+    Long  a, b;
+
+
+    base[4].x = base[2].x;
+    b = base[1].x;
+    a = base[3].x = ( base[2].x + b ) / 2;
+    b = base[1].x = ( base[0].x + b ) / 2;
+    base[2].x = ( a + b ) / 2;
+
+    base[4].y = base[2].y;
+    b = base[1].y;
+    a = base[3].y = ( base[2].y + b ) / 2;
+    b = base[1].y = ( base[0].y + b ) / 2;
+    base[2].y = ( a + b ) / 2;
+
+    /* hand optimized.  gcc doesn't seem to be too good at common      */
+    /* expression substitution and instruction scheduling ;-)          */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Split_Cubic                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Subdivides a third-order Bezier arc into two joint sub-arcs in the */
+  /*    Bezier stack.                                                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This routine is the `beef' of the component.  It is one of _the_   */
+  /*    inner loops that should be optimized like hell to get the best     */
+  /*    performance.                                                       */
+  /*                                                                       */
+  static void
+  Split_Cubic( TPoint*  base )
+  {
+    Long  a, b, c, d;
+
+
+    base[6].x = base[3].x;
+    c = base[1].x;
+    d = base[2].x;
+    base[1].x = a = ( base[0].x + c + 1 ) >> 1;
+    base[5].x = b = ( base[3].x + d + 1 ) >> 1;
+    c = ( c + d + 1 ) >> 1;
+    base[2].x = a = ( a + c + 1 ) >> 1;
+    base[4].x = b = ( b + c + 1 ) >> 1;
+    base[3].x = ( a + b + 1 ) >> 1;
+
+    base[6].y = base[3].y;
+    c = base[1].y;
+    d = base[2].y;
+    base[1].y = a = ( base[0].y + c + 1 ) >> 1;
+    base[5].y = b = ( base[3].y + d + 1 ) >> 1;
+    c = ( c + d + 1 ) >> 1;
+    base[2].y = a = ( a + c + 1 ) >> 1;
+    base[4].y = b = ( b + c + 1 ) >> 1;
+    base[3].y = ( a + b + 1 ) >> 1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_Up                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an ascending line segment and stores */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x1   :: The x-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    y1   :: The y-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    x2   :: The x-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    y2   :: The y-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    miny :: A lower vertical clipping bound value.                     */
+  /*                                                                       */
+  /*    maxy :: An upper vertical clipping bound value.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static Bool
+  Line_Up( RAS_ARGS Long  x1,
+                    Long  y1,
+                    Long  x2,
+                    Long  y2,
+                    Long  miny,
+                    Long  maxy )
+  {
+    Long   Dx, Dy;
+    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
+    Long   Ix, Rx, Ax;
+
+    PLong  top;
+
+
+    Dx = x2 - x1;
+    Dy = y2 - y1;
+
+    if ( Dy <= 0 || y2 < miny || y1 > maxy )
+      return SUCCESS;
+
+    if ( y1 < miny )
+    {
+      /* Take care: miny-y1 can be a very large value; we use     */
+      /*            a slow MulDiv function to avoid clipping bugs */
+      x1 += SMulDiv( Dx, miny - y1, Dy );
+      e1  = TRUNC( miny );
+      f1  = 0;
+    }
+    else
+    {
+      e1 = TRUNC( y1 );
+      f1 = FRAC( y1 );
+    }
+
+    if ( y2 > maxy )
+    {
+      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
+      e2  = TRUNC( maxy );
+      f2  = 0;
+    }
+    else
+    {
+      e2 = TRUNC( y2 );
+      f2 = FRAC( y2 );
+    }
+
+    if ( f1 > 0 )
+    {
+      if ( e1 == e2 )
+        return SUCCESS;
+      else
+      {
+        x1 += FMulDiv( Dx, ras.precision - f1, Dy );
+        e1 += 1;
+      }
+    }
+    else
+      if ( ras.joint )
+      {
+        ras.top--;
+        ras.joint = FALSE;
+      }
+
+    ras.joint = (char)( f2 == 0 );
+
+    if ( ras.fresh )
+    {
+      ras.cProfile->start = e1;
+      ras.fresh           = FALSE;
+    }
+
+    size = e2 - e1 + 1;
+    if ( ras.top + size >= ras.maxBuff )
+    {
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    if ( Dx > 0 )
+    {
+      Ix = ( ras.precision * Dx ) / Dy;
+      Rx = ( ras.precision * Dx ) % Dy;
+      Dx = 1;
+    }
+    else
+    {
+      Ix = -( ( ras.precision * -Dx ) / Dy );
+      Rx =    ( ras.precision * -Dx ) % Dy;
+      Dx = -1;
+    }
+
+    Ax  = -Dy;
+    top = ras.top;
+
+    while ( size > 0 )
+    {
+      *top++ = x1;
+
+      x1 += Ix;
+      Ax += Rx;
+      if ( Ax >= 0 )
+      {
+        Ax -= Dy;
+        x1 += Dx;
+      }
+      size--;
+    }
+
+    ras.top = top;
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_Down                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an descending line segment and       */
+  /*    stores them in the render pool.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x1   :: The x-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    y1   :: The y-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    x2   :: The x-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    y2   :: The y-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    miny :: A lower vertical clipping bound value.                     */
+  /*                                                                       */
+  /*    maxy :: An upper vertical clipping bound value.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static Bool
+  Line_Down( RAS_ARGS Long  x1,
+                      Long  y1,
+                      Long  x2,
+                      Long  y2,
+                      Long  miny,
+                      Long  maxy )
+  {
+    Bool  result, fresh;
+
+
+    fresh  = ras.fresh;
+
+    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
+
+    if ( fresh && !ras.fresh )
+      ras.cProfile->start = -ras.cProfile->start;
+
+    return result;
+  }
+
+
+  /* A function type describing the functions used to split Bezier arcs */
+  typedef void  (*TSplitter)( TPoint*  base );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Bezier_Up                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an ascending Bezier arc and stores   */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
+  /*                                                                       */
+  /*    splitter :: The function to split Bezier arcs.                     */
+  /*                                                                       */
+  /*    miny     :: A lower vertical clipping bound value.                 */
+  /*                                                                       */
+  /*    maxy     :: An upper vertical clipping bound value.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static Bool
+  Bezier_Up( RAS_ARGS Int        degree,
+                      TSplitter  splitter,
+                      Long       miny,
+                      Long       maxy )
+  {
+    Long   y1, y2, e, e2, e0;
+    Short  f1;
+
+    TPoint*  arc;
+    TPoint*  start_arc;
+
+    PLong top;
+
+
+    arc = ras.arc;
+    y1  = arc[degree].y;
+    y2  = arc[0].y;
+    top = ras.top;
+
+    if ( y2 < miny || y1 > maxy )
+      goto Fin;
+
+    e2 = FLOOR( y2 );
+
+    if ( e2 > maxy )
+      e2 = maxy;
+
+    e0 = miny;
+
+    if ( y1 < miny )
+      e = miny;
+    else
+    {
+      e  = CEILING( y1 );
+      f1 = (Short)( FRAC( y1 ) );
+      e0 = e;
+
+      if ( f1 == 0 )
+      {
+        if ( ras.joint )
+        {
+          top--;
+          ras.joint = FALSE;
+        }
+
+        *top++ = arc[degree].x;
+
+        e += ras.precision;
+      }
+    }
+
+    if ( ras.fresh )
+    {
+      ras.cProfile->start = TRUNC( e0 );
+      ras.fresh = FALSE;
+    }
+
+    if ( e2 < e )
+      goto Fin;
+
+    if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
+    {
+      ras.top   = top;
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    start_arc = arc;
+
+    while ( arc >= start_arc && e <= e2 )
+    {
+      ras.joint = FALSE;
+
+      y2 = arc[0].y;
+
+      if ( y2 > e )
+      {
+        y1 = arc[degree].y;
+        if ( y2 - y1 >= ras.precision_step )
+        {
+          splitter( arc );
+          arc += degree;
+        }
+        else
+        {
+          *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
+                                            e - y1, y2 - y1 );
+          arc -= degree;
+          e   += ras.precision;
+        }
+      }
+      else
+      {
+        if ( y2 == e )
+        {
+          ras.joint  = TRUE;
+          *top++     = arc[0].x;
+
+          e += ras.precision;
+        }
+        arc -= degree;
+      }
+    }
+
+  Fin:
+    ras.top  = top;
+    ras.arc -= degree;
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Bezier_Down                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an descending Bezier arc and stores  */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
+  /*                                                                       */
+  /*    splitter :: The function to split Bezier arcs.                     */
+  /*                                                                       */
+  /*    miny     :: A lower vertical clipping bound value.                 */
+  /*                                                                       */
+  /*    maxy     :: An upper vertical clipping bound value.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static Bool
+  Bezier_Down( RAS_ARGS Int        degree,
+                        TSplitter  splitter,
+                        Long       miny,
+                        Long       maxy )
+  {
+    TPoint*  arc = ras.arc;
+    Bool     result, fresh;
+
+
+    arc[0].y = -arc[0].y;
+    arc[1].y = -arc[1].y;
+    arc[2].y = -arc[2].y;
+    if ( degree > 2 )
+      arc[3].y = -arc[3].y;
+
+    fresh = ras.fresh;
+
+    result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
+
+    if ( fresh && !ras.fresh )
+      ras.cProfile->start = -ras.cProfile->start;
+
+    arc[0].y = -arc[0].y;
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_To                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new line segment and adjusts Profiles list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   x :: The x-coordinate of the segment's end point (its start point   */
+  /*        is stored in `LastX').                                         */
+  /*                                                                       */
+  /*   y :: The y-coordinate of the segment's end point (its start point   */
+  /*        is stored in `LastY').                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static Bool
+  Line_To( RAS_ARGS Long  x,
+                    Long  y )
+  {
+    /* First, detect a change of direction */
+
+    switch ( ras.state )
+    {
+    case Unknown:
+      if ( y > ras.lastY )
+      {
+        if ( New_Profile( RAS_VARS Ascending ) )
+          return FAILURE;
+      }
+      else
+      {
+        if ( y < ras.lastY )
+          if ( New_Profile( RAS_VARS Descending ) )
+            return FAILURE;
+      }
+      break;
+
+    case Ascending:
+      if ( y < ras.lastY )
+      {
+        if ( End_Profile( RAS_VAR )             ||
+             New_Profile( RAS_VARS Descending ) )
+          return FAILURE;
+      }
+      break;
+
+    case Descending:
+      if ( y > ras.lastY )
+      {
+        if ( End_Profile( RAS_VAR )            ||
+             New_Profile( RAS_VARS Ascending ) )
+          return FAILURE;
+      }
+      break;
+
+    default:
+      ;
+    }
+
+    /* Then compute the lines */
+
+    switch ( ras.state )
+    {
+    case Ascending:
+      if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
+                    x, y, ras.minY, ras.maxY ) )
+        return FAILURE;
+      break;
+
+    case Descending:
+      if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
+                      x, y, ras.minY, ras.maxY ) )
+        return FAILURE;
+      break;
+
+    default:
+      ;
+    }
+
+    ras.lastX = x;
+    ras.lastY = y;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Conic_To                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new conic arc and adjusts the profile list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   cx :: The x-coordinate of the arc's new control point.              */
+  /*                                                                       */
+  /*   cy :: The y-coordinate of the arc's new control point.              */
+  /*                                                                       */
+  /*   x  :: The x-coordinate of the arc's end point (its start point is   */
+  /*         stored in `LastX').                                           */
+  /*                                                                       */
+  /*   y  :: The y-coordinate of the arc's end point (its start point is   */
+  /*         stored in `LastY').                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static Bool
+  Conic_To( RAS_ARGS Long  cx,
+                     Long  cy,
+                     Long  x,
+                     Long  y )
+  {
+    Long     y1, y2, y3, x3, ymin, ymax;
+    TStates  state_bez;
+
+
+    ras.arc      = ras.arcs;
+    ras.arc[2].x = ras.lastX;
+    ras.arc[2].y = ras.lastY;
+    ras.arc[1].x = cx; ras.arc[1].y = cy;
+    ras.arc[0].x = x;  ras.arc[0].y = y;
+
+    do
+    {
+      y1 = ras.arc[2].y;
+      y2 = ras.arc[1].y;
+      y3 = ras.arc[0].y;
+      x3 = ras.arc[0].x;
+
+      /* first, categorize the Bezier arc */
+
+      if ( y1 <= y3 )
+      {
+        ymin = y1;
+        ymax = y3;
+      }
+      else
+      {
+        ymin = y3;
+        ymax = y1;
+      }
+
+      if ( y2 < ymin || y2 > ymax )
+      {
+        /* this arc has no given direction, split it! */
+        Split_Conic( ras.arc );
+        ras.arc += 2;
+      }
+      else if ( y1 == y3 )
+      {
+        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        ras.arc -= 2;
+      }
+      else
+      {
+        /* the arc is y-monotonous, either ascending or descending */
+        /* detect a change of direction                            */
+        state_bez = y1 < y3 ? Ascending : Descending;
+        if ( ras.state != state_bez )
+        {
+          /* finalize current profile if any */
+          if ( ras.state != Unknown   &&
+               End_Profile( RAS_VAR ) )
+            goto Fail;
+
+          /* create a new profile */
+          if ( New_Profile( RAS_VARS state_bez ) )
+            goto Fail;
+        }
+
+        /* now call the appropriate routine */
+        if ( state_bez == Ascending )
+        {
+          if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+            goto Fail;
+        }
+        else
+          if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+            goto Fail;
+      }
+
+    } while ( ras.arc >= ras.arcs );
+
+    ras.lastX = x3;
+    ras.lastY = y3;
+
+    return SUCCESS;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Cubic_To                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new cubic arc and adjusts the profile list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   cx1 :: The x-coordinate of the arc's first new control point.       */
+  /*                                                                       */
+  /*   cy1 :: The y-coordinate of the arc's first new control point.       */
+  /*                                                                       */
+  /*   cx2 :: The x-coordinate of the arc's second new control point.      */
+  /*                                                                       */
+  /*   cy2 :: The y-coordinate of the arc's second new control point.      */
+  /*                                                                       */
+  /*   x   :: The x-coordinate of the arc's end point (its start point is  */
+  /*          stored in `LastX').                                          */
+  /*                                                                       */
+  /*   y   :: The y-coordinate of the arc's end point (its start point is  */
+  /*          stored in `LastY').                                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static Bool
+  Cubic_To( RAS_ARGS Long  cx1,
+                     Long  cy1,
+                     Long  cx2,
+                     Long  cy2,
+                     Long  x,
+                     Long  y )
+  {
+    Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
+    TStates  state_bez;
+
+
+    ras.arc      = ras.arcs;
+    ras.arc[3].x = ras.lastX;
+    ras.arc[3].y = ras.lastY;
+    ras.arc[2].x = cx1; ras.arc[2].y = cy1;
+    ras.arc[1].x = cx2; ras.arc[1].y = cy2;
+    ras.arc[0].x = x;   ras.arc[0].y = y;
+
+    do
+    {
+      y1 = ras.arc[3].y;
+      y2 = ras.arc[2].y;
+      y3 = ras.arc[1].y;
+      y4 = ras.arc[0].y;
+      x4 = ras.arc[0].x;
+
+      /* first, categorize the Bezier arc */
+
+      if ( y1 <= y4 )
+      {
+        ymin1 = y1;
+        ymax1 = y4;
+      }
+      else
+      {
+        ymin1 = y4;
+        ymax1 = y1;
+      }
+
+      if ( y2 <= y3 )
+      {
+        ymin2 = y2;
+        ymax2 = y3;
+      }
+      else
+      {
+        ymin2 = y3;
+        ymax2 = y2;
+      }
+
+      if ( ymin2 < ymin1 || ymax2 > ymax1 )
+      {
+        /* this arc has no given direction, split it! */
+        Split_Cubic( ras.arc );
+        ras.arc += 3;
+      }
+      else if ( y1 == y4 )
+      {
+        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        ras.arc -= 3;
+      }
+      else
+      {
+        state_bez = ( y1 <= y4 ) ? Ascending : Descending;
+
+        /* detect a change of direction */
+        if ( ras.state != state_bez )
+        {
+          if ( ras.state != Unknown   &&
+               End_Profile( RAS_VAR ) )
+            goto Fail;
+
+          if ( New_Profile( RAS_VARS state_bez ) )
+            goto Fail;
+        }
+
+        /* compute intersections */
+        if ( state_bez == Ascending )
+        {
+          if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+            goto Fail;
+        }
+        else
+          if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+            goto Fail;
+      }
+
+    } while ( ras.arc >= ras.arcs );
+
+    ras.lastX = x4;
+    ras.lastY = y4;
+
+    return SUCCESS;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+#undef  SWAP_
+#define SWAP_( x, y )  do                \
+                       {                 \
+                         Long  swap = x; \
+                                         \
+                                         \
+                         x = y;          \
+                         y = swap;       \
+                       } while ( 0 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Decompose_Curve                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Scans the outline arays in order to emit individual segments and   */
+  /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */
+  /*    weird cases, like when the first point is off the curve, or when   */
+  /*    there are simply no `on' points in the contour!                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    first   :: The index of the first point in the contour.            */
+  /*                                                                       */
+  /*    last    :: The index of the last point in the contour.             */
+  /*                                                                       */
+  /*    flipped :: If set, flip the direction of the curve.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on error.                              */
+  /*                                                                       */
+  static Bool
+  Decompose_Curve( RAS_ARGS UShort  first,
+                            UShort  last,
+                            int     flipped )
+  {
+    FT_Vector   v_last;
+    FT_Vector   v_control;
+    FT_Vector   v_start;
+
+    FT_Vector*  points;
+    FT_Vector*  point;
+    FT_Vector*  limit;
+    char*       tags;
+
+    unsigned    tag;       /* current point's state           */
+
+
+    points = ras.outline.points;
+    limit  = points + last;
+
+    v_start.x = SCALED( points[first].x );
+    v_start.y = SCALED( points[first].y );
+    v_last.x  = SCALED( points[last].x );
+    v_last.y  = SCALED( points[last].y );
+
+    if ( flipped )
+    {
+      SWAP_( v_start.x, v_start.y );
+      SWAP_( v_last.x, v_last.y );
+    }
+
+    v_control = v_start;
+
+    point = points + first;
+    tags  = ras.outline.tags  + first;
+    tag   = FT_CURVE_TAG( tags[0] );
+
+    /* A contour cannot start with a cubic control point! */
+    if ( tag == FT_Curve_Tag_Cubic )
+      goto Invalid_Outline;
+
+    /* check first point to determine origin */
+    if ( tag == FT_Curve_Tag_Conic )
+    {
+      /* first point is conic control.  Yes, this happens. */
+      if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_Curve_Tag_On )
+      {
+        /* start at last point if it is on the curve */
+        v_start = v_last;
+        limit--;
+      }
+      else
+      {
+        /* if both first and last points are conic,         */
+        /* start at their middle and record its position    */
+        /* for closure                                      */
+        v_start.x = ( v_start.x + v_last.x ) / 2;
+        v_start.y = ( v_start.y + v_last.y ) / 2;
+
+        v_last = v_start;
+      }
+      point--;
+      tags--;
+    }
+
+    ras.lastX = v_start.x;
+    ras.lastY = v_start.y;
+
+    while ( point < limit )
+    {
+      point++;
+      tags++;
+
+      tag = FT_CURVE_TAG( tags[0] );
+
+      switch ( tag )
+      {
+      case FT_Curve_Tag_On:  /* emit a single line_to */
+        {
+          Long  x, y;
+
+
+          x = SCALED( point->x );
+          y = SCALED( point->y );
+          if ( flipped )
+            SWAP_( x, y );
+
+          if ( Line_To( RAS_VARS x, y ) )
+            goto Fail;
+          continue;
+        }
+
+      case FT_Curve_Tag_Conic:  /* consume conic arcs */
+        v_control.x = SCALED( point[0].x );
+        v_control.y = SCALED( point[0].y );
+
+        if ( flipped )
+          SWAP_( v_control.x, v_control.y );
+
+      Do_Conic:
+        if ( point < limit )
+        {
+          FT_Vector  v_middle;
+          Long       x, y;
+
+
+          point++;
+          tags++;
+          tag = FT_CURVE_TAG( tags[0] );
+
+          x = SCALED( point[0].x );
+          y = SCALED( point[0].y );
+
+          if ( flipped )
+            SWAP_( x, y );
+
+          if ( tag == FT_Curve_Tag_On )
+          {
+            if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
+              goto Fail;
+            continue;
+          }
+
+          if ( tag != FT_Curve_Tag_Conic )
+            goto Invalid_Outline;
+
+          v_middle.x = ( v_control.x + x ) / 2;
+          v_middle.y = ( v_control.y + y ) / 2;
+
+          if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+                                  v_middle.x,  v_middle.y ) )
+            goto Fail;
+
+          v_control.x = x;
+          v_control.y = y;
+
+          goto Do_Conic;
+        }
+
+        if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+                                v_start.x,   v_start.y ) )
+          goto Fail;
+
+        goto Close;
+
+      default:  /* FT_Curve_Tag_Cubic */
+        {
+          Long  x1, y1, x2, y2, x3, y3;
+
+
+          if ( point + 1 > limit                             ||
+               FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+            goto Invalid_Outline;
+
+          point += 2;
+          tags  += 2;
+
+          x1 = SCALED( point[-2].x );
+          y1 = SCALED( point[-2].y );
+          x2 = SCALED( point[-1].x );
+          y2 = SCALED( point[-1].y );
+          x3 = SCALED( point[ 0].x );
+          y3 = SCALED( point[ 0].y );
+
+          if ( flipped )
+          {
+            SWAP_( x1, y1 );
+            SWAP_( x2, y2 );
+            SWAP_( x3, y3 );
+          }
+
+          if ( point <= limit )
+          {
+            if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
+              goto Fail;
+            continue;
+          }
+
+          if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
+            goto Fail;
+          goto Close;
+        }
+      }
+    }
+
+    /* close the contour with a line segment */
+    if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
+      goto Fail;
+
+  Close:
+    return SUCCESS;
+
+  Invalid_Outline:
+    ras.error = Raster_Err_Invalid;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Convert_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts a glyph into a series of segments and arcs and makes a    */
+  /*    profiles list with them.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    flipped :: If set, flip the direction of curve.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE if any error was encountered during    */
+  /*    rendering.                                                         */
+  /*                                                                       */
+  static Bool
+  Convert_Glyph( RAS_ARGS int  flipped )
+  {
+    int       i;
+    unsigned  start;
+
+    PProfile  lastProfile;
+
+
+    ras.fProfile = NULL;
+    ras.joint    = FALSE;
+    ras.fresh    = FALSE;
+
+    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
+
+    ras.numTurns = 0;
+
+    ras.cProfile         = (PProfile)ras.top;
+    ras.cProfile->offset = ras.top;
+    ras.num_Profs        = 0;
+
+    start = 0;
+
+    for ( i = 0; i < ras.outline.n_contours; i++ )
+    {
+      ras.state    = Unknown;
+      ras.gProfile = NULL;
+
+      if ( Decompose_Curve( RAS_VARS (unsigned short)start,
+                            ras.outline.contours[i],
+                            flipped ) )
+        return FAILURE;
+
+      start = ras.outline.contours[i] + 1;
+
+      /* We must now see whether the extreme arcs join or not */
+      if ( FRAC( ras.lastY ) == 0 &&
+           ras.lastY >= ras.minY  &&
+           ras.lastY <= ras.maxY  )
+        if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
+          ras.top--;
+        /* Note that ras.gProfile can be nil if the contour was too small */
+        /* to be drawn.                                                   */
+
+      lastProfile = ras.cProfile;
+      if ( End_Profile( RAS_VAR ) )
+        return FAILURE;
+
+      /* close the `next profile in contour' linked list */
+      if ( ras.gProfile )
+        lastProfile->next = ras.gProfile;
+    }
+
+    if ( Finalize_Profile_Table( RAS_VAR ) )
+      return FAILURE;
+
+    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  SCAN-LINE SWEEPS AND DRAWING                                       **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Init_Linked                                                          */
+  /*                                                                       */
+  /*    Initializes an empty linked list.                                  */
+  /*                                                                       */
+  static void
+  Init_Linked( TProfileList*  l )
+  {
+    *l = NULL;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  InsNew                                                               */
+  /*                                                                       */
+  /*    Inserts a new profile in a linked list.                            */
+  /*                                                                       */
+  static void
+  InsNew( PProfileList  list,
+          PProfile      profile )
+  {
+    PProfile  *old, current;
+    Long       x;
+
+
+    old     = list;
+    current = *old;
+    x       = profile->X;
+
+    while ( current )
+    {
+      if ( x < current->X )
+        break;
+      old     = &current->link;
+      current = *old;
+    }
+
+    profile->link = current;
+    *old          = profile;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  DelOld                                                               */
+  /*                                                                       */
+  /*    Removes an old profile from a linked list.                         */
+  /*                                                                       */
+  static void
+  DelOld( PProfileList  list,
+          PProfile      profile )
+  {
+    PProfile  *old, current;
+
+
+    old     = list;
+    current = *old;
+
+    while ( current )
+    {
+      if ( current == profile )
+      {
+        *old = current->link;
+        return;
+      }
+
+      old     = &current->link;
+      current = *old;
+    }
+
+    /* we should never get there, unless the profile was not part of */
+    /* the list.                                                     */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Sort                                                                 */
+  /*                                                                       */
+  /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */
+  /*    an algorithm which is fast in this case.  Bubble sort is enough    */
+  /*    and simple.                                                        */
+  /*                                                                       */
+  static void
+  Sort( PProfileList  list )
+  {
+    PProfile  *old, current, next;
+
+
+    /* First, set the new X coordinate of each profile */
+    current = *list;
+    while ( current )
+    {
+      current->X       = *current->offset;
+      current->offset += current->flow;
+      current->height--;
+      current = current->link;
+    }
+
+    /* Then sort them */
+    old     = list;
+    current = *old;
+
+    if ( !current )
+      return;
+
+    next = current->link;
+
+    while ( next )
+    {
+      if ( current->X <= next->X )
+      {
+        old     = &current->link;
+        current = *old;
+
+        if ( !current )
+          return;
+      }
+      else
+      {
+        *old          = next;
+        current->link = next->link;
+        next->link    = current;
+
+        old     = list;
+        current = *old;
+      }
+
+      next = current->link;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Vertical Sweep Procedure Set                                         */
+  /*                                                                       */
+  /*  These four routines are used during the vertical black/white sweep   */
+  /*  phase by the generic Draw_Sweep() function.                          */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static void
+  Vertical_Sweep_Init( RAS_ARGS Short*  min,
+                                Short*  max )
+  {
+    Long  pitch = ras.target.pitch;
+
+    FT_UNUSED( max );
+
+
+    ras.traceIncr = (Short)-pitch;
+    ras.traceOfs  = -*min * pitch;
+    if ( pitch > 0 )
+      ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
+
+    ras.gray_min_x = 0;
+    ras.gray_max_x = 0;
+  }
+
+
+  static void
+  Vertical_Sweep_Span( RAS_ARGS Short       y,
+                                FT_F26Dot6  x1,
+                                FT_F26Dot6  x2,
+                                PProfile    left,
+                                PProfile    right )
+  {
+    Long   e1, e2;
+    int    c1, c2;
+    Byte   f1, f2;
+    Byte*  target;
+
+    FT_UNUSED( y );
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+
+
+    /* Drop-out control */
+
+    e1 = TRUNC( CEILING( x1 ) );
+
+    if ( x2 - x1 - ras.precision <= ras.precision_jitter )
+      e2 = e1;
+    else
+      e2 = TRUNC( FLOOR( x2 ) );
+
+    if ( e2 >= 0 && e1 < ras.bWidth )
+    {
+      if ( e1 < 0 )
+        e1 = 0;
+      if ( e2 >= ras.bWidth )
+        e2 = ras.bWidth - 1;
+
+      c1 = (Short)( e1 >> 3 );
+      c2 = (Short)( e2 >> 3 );
+
+      f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
+      f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
+
+      if ( ras.gray_min_x > c1 ) ras.gray_min_x = (short)c1;
+      if ( ras.gray_max_x < c2 ) ras.gray_max_x = (short)c2;
+
+      target = ras.bTarget + ras.traceOfs + c1;
+      c2 -= c1;
+
+      if ( c2 > 0 )
+      {
+        target[0] |= f1;
+
+        /* memset() is slower than the following code on many platforms. */
+        /* This is due to the fact that, in the vast majority of cases,  */
+        /* the span length in bytes is relatively small.                 */
+        c2--;
+        while ( c2 > 0 )
+        {
+          *(++target) = 0xFF;
+          c2--;
+        }
+        target[1] |= f2;
+      }
+      else
+        *target |= ( f1 & f2 );
+    }
+  }
+
+
+  static void
+  Vertical_Sweep_Drop( RAS_ARGS Short       y,
+                                FT_F26Dot6  x1,
+                                FT_F26Dot6  x2,
+                                PProfile    left,
+                                PProfile    right )
+  {
+    Long   e1, e2;
+    Short  c1, f1;
+
+
+    /* Drop-out control */
+
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( (x1 + x2 + 1) / 2 );
+          break;
+
+        case 2:
+        case 5:
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+          /* Here, we only get rid of stubs recognized if:          */
+          /*                                                        */
+          /*  upper stub:                                           */
+          /*                                                        */
+          /*   - P_Left and P_Right are in the same contour         */
+          /*   - P_Right is the successor of P_Left in that contour */
+          /*   - y is the top of P_Left and P_Right                 */
+          /*                                                        */
+          /*  lower stub:                                           */
+          /*                                                        */
+          /*   - P_Left and P_Right are in the same contour         */
+          /*   - P_Left is the successor of P_Right in that contour */
+          /*   - y is the bottom of P_Left                          */
+          /*                                                        */
+
+          /* FIXXXME: uncommenting this line solves the disappearing */
+          /*          bit problem in the `7' of verdana 10pts, but   */
+          /*          makes a new one in the `C' of arial 14pts      */
+
+#if 0
+          if ( x2 - x1 < ras.precision_half )
+#endif
+          {
+            /* upper stub test */
+            if ( left->next == right && left->height <= 0 )
+              return;
+
+            /* lower stub test */
+            if ( right->next == left && left->start == y )
+              return;
+          }
+
+          /* check that the rightmost pixel isn't set */
+
+          e1 = TRUNC( e1 );
+
+          c1 = (Short)( e1 >> 3 );
+          f1 = (Short)( e1 &  7 );
+
+          if ( e1 >= 0 && e1 < ras.bWidth                      &&
+               ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    e1 = TRUNC( e1 );
+
+    if ( e1 >= 0 && e1 < ras.bWidth )
+    {
+      c1 = (Short)( e1 >> 3 );
+      f1 = (Short)( e1 & 7 );
+
+      if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+      if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
+
+      ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
+    }
+  }
+
+
+  static void
+  Vertical_Sweep_Step( RAS_ARG )
+  {
+    ras.traceOfs += ras.traceIncr;
+  }
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /*  Horizontal Sweep Procedure Set                                     */
+  /*                                                                     */
+  /*  These four routines are used during the horizontal black/white     */
+  /*  sweep phase by the generic Draw_Sweep() function.                  */
+  /*                                                                     */
+  /***********************************************************************/
+
+  static void
+  Horizontal_Sweep_Init( RAS_ARGS Short*  min,
+                                  Short*  max )
+  {
+    /* nothing, really */
+    FT_UNUSED( raster );
+    FT_UNUSED( min );
+    FT_UNUSED( max );
+  }
+
+
+  static void
+  Horizontal_Sweep_Span( RAS_ARGS Short       y,
+                                  FT_F26Dot6  x1,
+                                  FT_F26Dot6  x2,
+                                  PProfile    left,
+                                  PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  bits;
+    Byte   f1;
+
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+
+
+    if ( x2 - x1 < ras.precision )
+    {
+      e1 = CEILING( x1 );
+      e2 = FLOOR  ( x2 );
+
+      if ( e1 == e2 )
+      {
+        bits = ras.bTarget + ( y >> 3 );
+        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+        e1 = TRUNC( e1 );
+
+        if ( e1 >= 0 && e1 < ras.target.rows )
+        {
+          PByte  p;
+
+
+          p = bits - e1*ras.target.pitch;
+          if ( ras.target.pitch > 0 )
+            p += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+          p[0] |= f1;
+        }
+      }
+    }
+  }
+
+
+  static void
+  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
+                                  FT_F26Dot6  x1,
+                                  FT_F26Dot6  x2,
+                                  PProfile    left,
+                                  PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  bits;
+    Byte   f1;
+
+
+    /* During the horizontal sweep, we only take care of drop-outs */
+
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+          break;
+
+        case 2:
+        case 5:
+
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+
+          /* rightmost stub test */
+          if ( left->next == right && left->height <= 0 )
+            return;
+
+          /* leftmost stub test */
+          if ( right->next == left && left->start == y )
+            return;
+
+          /* check that the rightmost pixel isn't set */
+
+          e1 = TRUNC( e1 );
+
+          bits = ras.bTarget + ( y >> 3 );
+          f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+          bits -= e1 * ras.target.pitch;
+          if ( ras.target.pitch > 0 )
+            bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+          if ( e1 >= 0              &&
+               e1 < ras.target.rows &&
+               *bits & f1 )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    bits = ras.bTarget + ( y >> 3 );
+    f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+    e1 = TRUNC( e1 );
+
+    if ( e1 >= 0 && e1 < ras.target.rows )
+    {
+      bits -= e1 * ras.target.pitch;
+      if ( ras.target.pitch > 0 )
+        bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+      bits[0] |= f1;
+    }
+  }
+
+
+  static void
+  Horizontal_Sweep_Step( RAS_ARG )
+  {
+    /* Nothing, really */
+    FT_UNUSED( raster );
+  }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Vertical Gray Sweep Procedure Set                                    */
+  /*                                                                       */
+  /*  These two routines are used during the vertical gray-levels sweep    */
+  /*  phase by the generic Draw_Sweep() function.                          */
+  /*                                                                       */
+  /*  NOTES                                                                */
+  /*                                                                       */
+  /*  - The target pixmap's width *must* be a multiple of 4.               */
+  /*                                                                       */
+  /*  - You have to use the function Vertical_Sweep_Span() for the gray    */
+  /*    span call.                                                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static void
+  Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,
+                                     Short*  max )
+  {
+    Long  pitch, byte_len;
+
+
+    *min = *min & -2;
+    *max = ( *max + 3 ) & -2;
+
+    ras.traceOfs  = 0;
+    pitch         = ras.target.pitch;
+    byte_len      = -pitch;
+    ras.traceIncr = (Short)byte_len;
+    ras.traceG    = ( *min / 2 ) * byte_len;
+
+    if ( pitch > 0 )
+    {
+      ras.traceG += ( ras.target.rows - 1 ) * pitch;
+      byte_len    = -byte_len;
+    }
+
+    ras.gray_min_x =  (Short)byte_len;
+    ras.gray_max_x = -(Short)byte_len;
+  }
+
+
+  static void
+  Vertical_Gray_Sweep_Step( RAS_ARG )
+  {
+    Int    c1, c2;
+    PByte  pix, bit, bit2;
+    Int*   count = ras.count_table;
+    Byte*  grays;
+
+
+    ras.traceOfs += ras.gray_width;
+
+    if ( ras.traceOfs > ras.gray_width )
+    {
+      pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
+      grays = ras.grays;
+
+      if ( ras.gray_max_x >= 0 )
+      {
+        Long   last_pixel = ras.target.width - 1;
+        Int    last_cell  = last_pixel >> 2;
+        Int    last_bit   = last_pixel & 3;
+        Bool   over       = 0;
+
+
+        if ( ras.gray_max_x >= last_cell && last_bit != 3 )
+        {
+          ras.gray_max_x = last_cell - 1;
+          over = 1;
+        }
+
+        if ( ras.gray_min_x < 0 )
+          ras.gray_min_x = 0;
+
+        bit   = ras.bTarget + ras.gray_min_x;
+        bit2  = bit + ras.gray_width;
+
+        c1 = ras.gray_max_x - ras.gray_min_x;
+
+        while ( c1 >= 0 )
+        {
+          c2 = count[*bit] + count[*bit2];
+
+          if ( c2 )
+          {
+            pix[0] = grays[(c2 >> 12) & 0x000F];
+            pix[1] = grays[(c2 >> 8 ) & 0x000F];
+            pix[2] = grays[(c2 >> 4 ) & 0x000F];
+            pix[3] = grays[ c2        & 0x000F];
+
+            *bit  = 0;
+            *bit2 = 0;
+          }
+
+          bit++;
+          bit2++;
+          pix += 4;
+          c1--;
+        }
+
+        if ( over )
+        {
+          c2 = count[*bit] + count[*bit2];
+          if ( c2 )
+          {
+            switch ( last_bit )
+            {
+            case 2:
+              pix[2] = grays[(c2 >> 4 ) & 0x000F];
+            case 1:
+              pix[1] = grays[(c2 >> 8 ) & 0x000F];
+            default:
+              pix[0] = grays[(c2 >> 12) & 0x000F];
+            }
+
+            *bit  = 0;
+            *bit2 = 0;
+          }
+        }
+      }
+
+      ras.traceOfs = 0;
+      ras.traceG  += ras.traceIncr;
+
+      ras.gray_min_x =  32000;
+      ras.gray_max_x = -32000;
+    }
+  }
+
+
+  static void
+  Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,
+                                       FT_F26Dot6  x1,
+                                       FT_F26Dot6  x2,
+                                       PProfile    left,
+                                       PProfile    right )
+  {
+    /* nothing, really */
+    FT_UNUSED( raster );
+    FT_UNUSED( y );
+    FT_UNUSED( x1 );
+    FT_UNUSED( x2 );
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+  }
+
+
+  static void
+  Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,
+                                       FT_F26Dot6  x1,
+                                       FT_F26Dot6  x2,
+                                       PProfile    left,
+                                       PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  pixel;
+    Byte   color;
+
+
+    /* During the horizontal sweep, we only take care of drop-outs */
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+          break;
+
+        case 2:
+        case 5:
+
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+
+          /* rightmost stub test */
+          if ( left->next == right && left->height <= 0 )
+            return;
+
+          /* leftmost stub test */
+          if ( right->next == left && left->start == y )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    if ( e1 >= 0 )
+    {
+      if ( x2 - x1 >= ras.precision_half )
+        color = ras.grays[2];
+      else
+        color = ras.grays[1];
+
+      e1 = TRUNC( e1 ) / 2;
+      if ( e1 < ras.target.rows )
+      {
+        pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
+        if ( ras.target.pitch > 0 )
+          pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+        if ( pixel[0] == ras.grays[0] )
+          pixel[0] = color;
+      }
+    }
+  }
+
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Generic Sweep Drawing routine                                        */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static Bool
+  Draw_Sweep( RAS_ARG )
+  {
+    Short         y, y_change, y_height;
+
+    PProfile      P, Q, P_Left, P_Right;
+
+    Short         min_Y, max_Y, top, bottom, dropouts;
+
+    Long          x1, x2, xs, e1, e2;
+
+    TProfileList  wait;
+    TProfileList  draw_left, draw_right;
+
+
+    /* Init empty linked lists */
+
+    Init_Linked( &wait );
+
+    Init_Linked( &draw_left  );
+    Init_Linked( &draw_right );
+
+    /* first, compute min and max Y */
+
+    P     = ras.fProfile;
+    max_Y = (Short)TRUNC( ras.minY );
+    min_Y = (Short)TRUNC( ras.maxY );
+
+    while ( P )
+    {
+      Q = P->link;
+
+      bottom = (Short)P->start;
+      top    = (Short)( P->start + P->height - 1 );
+
+      if ( min_Y > bottom ) min_Y = bottom;
+      if ( max_Y < top    ) max_Y = top;
+
+      P->X = 0;
+      InsNew( &wait, P );
+
+      P = Q;
+    }
+
+    /* Check the Y-turns */
+    if ( ras.numTurns == 0 )
+    {
+      ras.error = Raster_Err_Invalid;
+      return FAILURE;
+    }
+
+    /* Now inits the sweep */
+
+    ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
+
+    /* Then compute the distance of each profile from min_Y */
+
+    P = wait;
+
+    while ( P )
+    {
+      P->countL = (UShort)( P->start - min_Y );
+      P = P->link;
+    }
+
+    /* Let's go */
+
+    y        = min_Y;
+    y_height = 0;
+
+    if ( ras.numTurns > 0 &&
+         ras.sizeBuff[-ras.numTurns] == min_Y )
+      ras.numTurns--;
+
+    while ( ras.numTurns > 0 )
+    {
+      /* look in the wait list for new activations */
+
+      P = wait;
+
+      while ( P )
+      {
+        Q = P->link;
+        P->countL -= y_height;
+        if ( P->countL == 0 )
+        {
+          DelOld( &wait, P );
+
+          switch ( P->flow )
+          {
+          case Flow_Up:
+            InsNew( &draw_left,  P );
+            break;
+
+          case Flow_Down:
+            InsNew( &draw_right, P );
+            break;
+          }
+        }
+
+        P = Q;
+      }
+
+      /* Sort the drawing lists */
+
+      Sort( &draw_left );
+      Sort( &draw_right );
+
+      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
+      y_height = (Short)( y_change - y );
+
+      while ( y < y_change )
+      {
+        /* Let's trace */
+
+        dropouts = 0;
+
+        P_Left  = draw_left;
+        P_Right = draw_right;
+
+        while ( P_Left )
+        {
+          x1 = P_Left ->X;
+          x2 = P_Right->X;
+
+          if ( x1 > x2 )
+          {
+            xs = x1;
+            x1 = x2;
+            x2 = xs;
+          }
+
+          if ( x2 - x1 <= ras.precision )
+          {
+            e1 = FLOOR( x1 );
+            e2 = CEILING( x2 );
+
+            if ( ras.dropOutControl != 0                 &&
+                 ( e1 > e2 || e2 == e1 + ras.precision ) )
+            {
+              /* a drop out was detected */
+
+              P_Left ->X = x1;
+              P_Right->X = x2;
+
+              /* mark profile for drop-out processing */
+              P_Left->countL = 1;
+              dropouts++;
+
+              goto Skip_To_Next;
+            }
+          }
+
+          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
+
+        Skip_To_Next:
+
+          P_Left  = P_Left->link;
+          P_Right = P_Right->link;
+        }
+
+        /* now perform the dropouts _after_ the span drawing -- */
+        /* drop-outs processing has been moved out of the loop  */
+        /* for performance tuning                               */
+        if ( dropouts > 0 )
+          goto Scan_DropOuts;
+
+      Next_Line:
+
+        ras.Proc_Sweep_Step( RAS_VAR );
+
+        y++;
+
+        if ( y < y_change )
+        {
+          Sort( &draw_left  );
+          Sort( &draw_right );
+        }
+      }
+
+      /* Now finalize the profiles that needs it */
+
+      P = draw_left;
+      while ( P )
+      {
+        Q = P->link;
+        if ( P->height == 0 )
+          DelOld( &draw_left, P );
+        P = Q;
+      }
+
+      P = draw_right;
+      while ( P )
+      {
+        Q = P->link;
+        if ( P->height == 0 )
+          DelOld( &draw_right, P );
+        P = Q;
+      }
+    }
+
+    /* for gray-scaling, flushes the bitmap scanline cache */
+    while ( y <= max_Y )
+    {
+      ras.Proc_Sweep_Step( RAS_VAR );
+      y++;
+    }
+
+    return SUCCESS;
+
+  Scan_DropOuts:
+
+    P_Left  = draw_left;
+    P_Right = draw_right;
+
+    while ( P_Left )
+    {
+      if ( P_Left->countL )
+      {
+        P_Left->countL = 0;
+#if 0
+        dropouts--;  /* -- this is useful when debugging only */
+#endif
+        ras.Proc_Sweep_Drop( RAS_VARS y,
+                                      P_Left->X,
+                                      P_Right->X,
+                                      P_Left,
+                                      P_Right );
+      }
+
+      P_Left  = P_Left->link;
+      P_Right = P_Right->link;
+    }
+
+    goto Next_Line;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Single_Pass                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Performs one sweep with sub-banding.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    flipped :: If set, flip the direction of the outline.              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Renderer error code.                                               */
+  /*                                                                       */
+  static int
+  Render_Single_Pass( RAS_ARGS Bool  flipped )
+  {
+    Short  i, j, k;
+
+
+    while ( ras.band_top >= 0 )
+    {
+      ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
+      ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
+
+      ras.top = ras.buff;
+
+      ras.error = Raster_Err_None;
+
+      if ( Convert_Glyph( RAS_VARS flipped ) )
+      {
+        if ( ras.error != Raster_Err_Overflow )
+          return FAILURE;
+
+        ras.error = Raster_Err_None;
+
+        /* sub-banding */
+
+#ifdef DEBUG_RASTER
+        ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
+#endif
+
+        i = ras.band_stack[ras.band_top].y_min;
+        j = ras.band_stack[ras.band_top].y_max;
+
+        k = (Short)( ( i + j ) / 2 );
+
+        if ( ras.band_top >= 7 || k < i )
+        {
+          ras.band_top = 0;
+          ras.error    = Raster_Err_Invalid;
+
+          return ras.error;
+        }
+
+        ras.band_stack[ras.band_top + 1].y_min = k;
+        ras.band_stack[ras.band_top + 1].y_max = j;
+
+        ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
+
+        ras.band_top++;
+      }
+      else
+      {
+        if ( ras.fProfile )
+          if ( Draw_Sweep( RAS_VAR ) )
+             return ras.error;
+        ras.band_top--;
+      }
+    }
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Glyph                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders a glyph in a bitmap.  Sub-banding if needed.               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  Render_Glyph( RAS_ARG )
+  {
+    FT_Error  error;
+
+
+    Set_High_Precision( RAS_VARS ras.outline.flags &
+                        ft_outline_high_precision );
+    ras.scale_shift    = ras.precision_shift;
+    ras.dropOutControl = 2;
+    ras.second_pass    = (FT_Byte)( !( ras.outline.flags &
+                                       ft_outline_single_pass ) );
+
+    /* Vertical Sweep */
+    ras.Proc_Sweep_Init = Vertical_Sweep_Init;
+    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+    ras.Proc_Sweep_Step = Vertical_Sweep_Step;
+
+    ras.band_top            = 0;
+    ras.band_stack[0].y_min = 0;
+    ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );
+
+    ras.bWidth  = (unsigned short)ras.target.width;
+    ras.bTarget = (Byte*)ras.target.buffer;
+
+    if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
+      return error;
+
+    /* Horizontal Sweep */
+    if ( ras.second_pass && ras.dropOutControl != 0 )
+    {
+      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+      ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
+      ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
+      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+      ras.band_top            = 0;
+      ras.band_stack[0].y_min = 0;
+      ras.band_stack[0].y_max = (short)( ras.target.width - 1 );
+
+      if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
+        return error;
+    }
+
+    return Raster_Err_Ok;
+  }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Gray_Glyph                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders a glyph with grayscaling.  Sub-banding if needed.          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  Render_Gray_Glyph( RAS_ARG )
+  {
+    Long      pixel_width;
+    FT_Error  error;
+
+
+    Set_High_Precision( RAS_VARS ras.outline.flags &
+                        ft_outline_high_precision );
+    ras.scale_shift    = ras.precision_shift + 1;
+    ras.dropOutControl = 2;
+    ras.second_pass    = !( ras.outline.flags & ft_outline_single_pass );
+
+    /* Vertical Sweep */
+
+    ras.band_top            = 0;
+    ras.band_stack[0].y_min = 0;
+    ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
+
+    ras.bWidth  = ras.gray_width;
+    pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
+
+    if ( ras.bWidth > pixel_width )
+      ras.bWidth = pixel_width;
+
+    ras.bWidth  = ras.bWidth * 8;
+    ras.bTarget = (Byte*)ras.gray_lines;
+    ras.gTarget = (Byte*)ras.target.buffer;
+
+    ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
+    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+    ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
+
+    error = Render_Single_Pass( RAS_VARS 0 );
+    if ( error )
+      return error;
+
+    /* Horizontal Sweep */
+    if ( ras.second_pass && ras.dropOutControl != 0 )
+    {
+      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+      ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
+      ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
+      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+      ras.band_top            = 0;
+      ras.band_stack[0].y_min = 0;
+      ras.band_stack[0].y_max = ras.target.width * 2 - 1;
+
+      error = Render_Single_Pass( RAS_VARS 1 );
+      if ( error )
+        return error;
+    }
+
+    return Raster_Err_Ok;
+  }
+
+#else /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+  FT_LOCAL_DEF
+  FT_Error  Render_Gray_Glyph( RAS_ARG )
+  {
+    FT_UNUSED_RASTER;
+
+    return Raster_Err_Cannot_Render_Glyph;
+  }
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+  static void
+  ft_black_init( TRaster_Instance*  raster )
+  {
+    FT_UInt  n;
+    FT_ULong c;
+
+
+    /* setup count table */
+    for ( n = 0; n < 256; n++ )
+    {
+      c = ( n & 0x55 ) + ( ( n & 0xAA ) >> 1 );
+
+      c = ( ( c << 6 ) & 0x3000 ) |
+          ( ( c << 4 ) & 0x0300 ) |
+          ( ( c << 2 ) & 0x0030 ) |
+                   (c  & 0x0003 );
+
+      raster->count_table[n] = c;
+    }
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    /* set default 5-levels gray palette */
+    for ( n = 0; n < 5; n++ )
+      raster->grays[n] = n * 255 / 4;
+
+    raster->gray_width = RASTER_GRAY_LINES / 2;
+
+#endif
+  }
+
+
+  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+  /****                         a static object.                  *****/
+
+
+#ifdef _STANDALONE_
+
+
+  static int
+  ft_black_new( void*      memory,
+                FT_Raster  *araster )
+  {
+     static FT_RasterRec_  the_raster;
+
+
+     *araster = &the_raster;
+     memset( &the_raster, sizeof ( the_raster ), 0 );
+     ft_black_init( &the_raster );
+
+     return 0;
+  }
+
+
+  static void
+  ft_black_done( FT_Raster  raster )
+  {
+    /* nothing */
+    raster->init = 0;
+  }
+
+
+#else /* _STANDALONE_ */
+
+
+  static int
+  ft_black_new( FT_Memory           memory,
+                TRaster_Instance**  araster )
+  {
+    FT_Error           error;
+    TRaster_Instance*  raster;
+
+
+    *araster = 0;
+    if ( !ALLOC( raster, sizeof ( *raster ) ) )
+    {
+      raster->memory = memory;
+      ft_black_init( raster );
+
+      *araster = raster;
+    }
+
+    return error;
+  }
+
+
+  static void
+  ft_black_done( TRaster_Instance*  raster )
+  {
+    FT_Memory  memory = (FT_Memory)raster->memory;
+    FREE( raster );
+  }
+
+
+#endif /* _STANDALONE_ */
+
+
+  static void
+  ft_black_reset( TRaster_Instance*  raster,
+                  const char*        pool_base,
+                  long               pool_size )
+  {
+    if ( raster && pool_base && pool_size >= 4096 )
+    {
+      /* save the pool */
+      raster->buff     = (PLong)pool_base;
+      raster->sizeBuff = raster->buff + pool_size / sizeof ( Long );
+    }
+  }
+
+
+  static void
+  ft_black_set_mode( TRaster_Instance* raster,
+                     unsigned long     mode,
+                     const char*       palette )
+  {
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
+    {
+      /* set 5-levels gray palette */
+      raster->grays[0] = palette[0];
+      raster->grays[1] = palette[1];
+      raster->grays[2] = palette[2];
+      raster->grays[3] = palette[3];
+      raster->grays[4] = palette[4];
+    }
+
+#else
+
+    FT_UNUSED( raster );
+    FT_UNUSED( mode );
+    FT_UNUSED( palette );
+
+#endif
+  }
+
+
+  static int
+  ft_black_render( TRaster_Instance*  raster,
+                   FT_Raster_Params*  params )
+  {
+    FT_Outline*  outline    = (FT_Outline*)params->source;
+    FT_Bitmap*   target_map = params->target;
+
+
+    if ( !raster || !raster->buff || !raster->sizeBuff )
+      return Raster_Err_Not_Ini;
+
+    /* return immediately if the outline is empty */
+    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+      return Raster_Err_None;
+
+    if ( !outline || !outline->contours || !outline->points )
+      return Raster_Err_Invalid;
+
+    if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
+      return Raster_Err_Invalid;
+
+    /* this version of the raster does not support direct rendering, sorry */
+    if ( params->flags & ft_raster_flag_direct )
+      return Raster_Err_Unsupported;
+
+    if ( !target_map || !target_map->buffer )
+      return Raster_Err_Invalid;
+
+    ras.outline  = *outline;
+    ras.target   = *target_map;
+
+    return ( ( params->flags & ft_raster_flag_aa )
+               ? Render_Gray_Glyph( raster )
+               : Render_Glyph( raster ) );
+  }
+
+
+  const FT_Raster_Funcs  ft_standard_raster =
+  {
+    ft_glyph_format_outline,
+    (FT_Raster_New_Func)     ft_black_new,
+    (FT_Raster_Reset_Func)   ft_black_reset,
+    (FT_Raster_Set_Mode_Func)ft_black_set_mode,
+    (FT_Raster_Render_Func)  ft_black_render,
+    (FT_Raster_Done_Func)    ft_black_done
+  };
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftrend1.c b/libraries/freetype-2.0.5/ftrend1.c
new file mode 100644 (file)
index 0000000..5a29125
--- /dev/null
@@ -0,0 +1,270 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftrend1.c                                                              */
+/*                                                                         */
+/*    The FreeType glyph rasterizer interface (body).                      */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_OUTLINE_H
+#include "ftrend1.h"
+#include "ftraster.h"
+
+#include "rasterrs.h"
+
+
+  /* initialize renderer -- init its raster */
+  static FT_Error
+  ft_raster1_init( FT_Renderer  render )
+  {
+    FT_Library  library = FT_MODULE_LIBRARY( render );
+
+
+    render->clazz->raster_class->raster_reset( render->raster,
+                                               library->raster_pool,
+                                               library->raster_pool_size );
+
+    return Raster_Err_Ok;
+  }
+
+
+  /* set render-specific mode */
+  static FT_Error
+  ft_raster1_set_mode( FT_Renderer  render,
+                       FT_ULong     mode_tag,
+                       FT_Pointer   data )
+  {
+    /* we simply pass it to the raster */
+    return render->clazz->raster_class->raster_set_mode( render->raster,
+                                                         mode_tag,
+                                                         data );
+  }
+
+
+  /* transform a given glyph image */
+  static FT_Error
+  ft_raster1_transform( FT_Renderer   render,
+                        FT_GlyphSlot  slot,
+                        FT_Matrix*    matrix,
+                        FT_Vector*    delta )
+  {
+    FT_Error error = Raster_Err_Ok;
+
+
+    if ( slot->format != render->glyph_format )
+    {
+      error = Raster_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    if ( matrix )
+      FT_Outline_Transform( &slot->outline, matrix );
+
+    if ( delta )
+      FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+  Exit:
+    return error;
+  }
+
+
+  /* return the glyph's control box */
+  static void
+  ft_raster1_get_cbox( FT_Renderer   render,
+                       FT_GlyphSlot  slot,
+                       FT_BBox*      cbox )
+  {
+    MEM_Set( cbox, 0, sizeof ( *cbox ) );
+
+    if ( slot->format == render->glyph_format )
+      FT_Outline_Get_CBox( &slot->outline, cbox );
+  }
+
+
+  /* convert a slot's glyph image into a bitmap */
+  static FT_Error
+  ft_raster1_render( FT_Renderer   render,
+                     FT_GlyphSlot  slot,
+                     FT_UInt       mode,
+                     FT_Vector*    origin )
+  {
+    FT_Error     error;
+    FT_Outline*  outline;
+    FT_BBox      cbox;
+    FT_UInt      width, height, pitch;
+    FT_Bitmap*   bitmap;
+    FT_Memory    memory;
+
+    FT_Raster_Params  params;
+
+
+    /* check glyph image format */
+    if ( slot->format != render->glyph_format )
+    {
+      error = Raster_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* check rendering mode */
+    if ( mode != ft_render_mode_mono )
+    {
+      /* raster1 is only capable of producing monochrome bitmaps */
+      if ( render->clazz == &ft_raster1_renderer_class )
+        return Raster_Err_Cannot_Render_Glyph;
+    }
+    else
+    {
+      /* raster5 is only capable of producing 5-gray-levels bitmaps */
+      if ( render->clazz == &ft_raster5_renderer_class )
+        return Raster_Err_Cannot_Render_Glyph;
+    }
+
+    outline = &slot->outline;
+
+    /* translate the outline to the new origin if needed */
+    if ( origin )
+      FT_Outline_Translate( outline, origin->x, origin->y );
+
+    /* compute the control box, and grid fit it */
+    FT_Outline_Get_CBox( outline, &cbox );
+
+    cbox.xMin &= -64;
+    cbox.yMin &= -64;
+    cbox.xMax  = ( cbox.xMax + 63 ) & -64;
+    cbox.yMax  = ( cbox.yMax + 63 ) & -64;
+
+    width  = ( cbox.xMax - cbox.xMin ) >> 6;
+    height = ( cbox.yMax - cbox.yMin ) >> 6;
+    bitmap = &slot->bitmap;
+    memory = render->root.memory;
+
+    /* release old bitmap buffer */
+    if ( slot->flags & ft_glyph_own_bitmap )
+    {
+      FREE( bitmap->buffer );
+      slot->flags &= ~ft_glyph_own_bitmap;
+    }
+
+    /* allocate new one, depends on pixel format */
+    if ( !( mode & ft_render_mode_mono ) )
+    {
+      /* we pad to 32 bits, only for backwards compatibility with FT 1.x */
+      pitch = ( width + 3 ) & -4;
+      bitmap->pixel_mode = ft_pixel_mode_grays;
+      bitmap->num_grays  = 256;
+    }
+    else
+    {
+      pitch = ( width + 7 ) >> 3;
+      bitmap->pixel_mode = ft_pixel_mode_mono;
+    }
+
+    bitmap->width = width;
+    bitmap->rows  = height;
+    bitmap->pitch = pitch;
+
+    if ( ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+      goto Exit;
+
+    slot->flags |= ft_glyph_own_bitmap;
+
+    /* translate outline to render it into the bitmap */
+    FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+
+    /* set up parameters */
+    params.target = bitmap;
+    params.source = outline;
+    params.flags  = 0;
+
+    if ( bitmap->pixel_mode == ft_pixel_mode_grays )
+      params.flags |= ft_raster_flag_aa;
+
+    /* render outline into the bitmap */
+    error = render->raster_render( render->raster, &params );
+    if ( error )
+      goto Exit;
+
+    slot->format      = ft_glyph_format_bitmap;
+    slot->bitmap_left = cbox.xMin >> 6;
+    slot->bitmap_top  = cbox.yMax >> 6;
+
+  Exit:
+    return error;
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Renderer_Class  ft_raster1_renderer_class =
+  {
+    {
+      ft_module_renderer,
+      sizeof( FT_RendererRec ),
+
+      "raster1",
+      0x10000L,
+      0x20000L,
+
+      0,    /* module specific interface */
+
+      (FT_Module_Constructor)ft_raster1_init,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    ft_glyph_format_outline,
+
+    (FTRenderer_render)   ft_raster1_render,
+    (FTRenderer_transform)ft_raster1_transform,
+    (FTRenderer_getCBox)  ft_raster1_get_cbox,
+    (FTRenderer_setMode)  ft_raster1_set_mode,
+
+    (FT_Raster_Funcs*)    &ft_standard_raster
+  };
+
+
+  /* This renderer is _NOT_ part of the default modules; you will need */
+  /* to register it by hand in your application.  It should only be    */
+  /* used for backwards-compatibility with FT 1.x anyway.              */
+  /*                                                                   */
+  FT_CALLBACK_TABLE_DEF
+  const FT_Renderer_Class  ft_raster5_renderer_class =
+  {
+    {
+      ft_module_renderer,
+      sizeof( FT_RendererRec ),
+
+      "raster5",
+      0x10000L,
+      0x20000L,
+
+      0,    /* module specific interface */
+
+      (FT_Module_Constructor)ft_raster1_init,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    ft_glyph_format_outline,
+
+    (FTRenderer_render)   ft_raster1_render,
+    (FTRenderer_transform)ft_raster1_transform,
+    (FTRenderer_getCBox)  ft_raster1_get_cbox,
+    (FTRenderer_setMode)  ft_raster1_set_mode,
+
+    (FT_Raster_Funcs*)    &ft_standard_raster
+  };
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftsmooth.c b/libraries/freetype-2.0.5/ftsmooth.c
new file mode 100644 (file)
index 0000000..735ef22
--- /dev/null
@@ -0,0 +1,213 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsmooth.c                                                             */
+/*                                                                         */
+/*    Anti-aliasing renderer interface (body).                             */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_OUTLINE_H
+#include "ftsmooth.h"
+#include "ftgrays.h"
+
+#include "ftsmerrs.h"
+
+
+  /* initialize renderer -- init its raster */
+  static FT_Error
+  ft_smooth_init( FT_Renderer  render )
+  {
+    FT_Library  library = FT_MODULE_LIBRARY( render );
+
+
+    render->clazz->raster_class->raster_reset( render->raster,
+                                               library->raster_pool,
+                                               library->raster_pool_size );
+
+    return 0;
+  }
+
+
+  /* sets render-specific mode */
+  static FT_Error
+  ft_smooth_set_mode( FT_Renderer  render,
+                      FT_ULong     mode_tag,
+                      FT_Pointer   data )
+  {
+    /* we simply pass it to the raster */
+    return render->clazz->raster_class->raster_set_mode( render->raster,
+                                                         mode_tag,
+                                                         data );
+  }
+
+  /* transform a given glyph image */
+  static FT_Error
+  ft_smooth_transform( FT_Renderer   render,
+                       FT_GlyphSlot  slot,
+                       FT_Matrix*    matrix,
+                       FT_Vector*    delta )
+  {
+    FT_Error  error = Smooth_Err_Ok;
+
+
+    if ( slot->format != render->glyph_format )
+    {
+      error = Smooth_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    if ( matrix )
+      FT_Outline_Transform( &slot->outline, matrix );
+
+    if ( delta )
+      FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+  Exit:
+    return error;
+  }
+
+
+  /* return the glyph's control box */
+  static void
+  ft_smooth_get_cbox( FT_Renderer   render,
+                      FT_GlyphSlot  slot,
+                      FT_BBox*      cbox )
+  {
+    MEM_Set( cbox, 0, sizeof ( *cbox ) );
+
+    if ( slot->format == render->glyph_format )
+      FT_Outline_Get_CBox( &slot->outline, cbox );
+  }
+
+
+  /* convert a slot's glyph image into a bitmap */
+  static FT_Error
+  ft_smooth_render( FT_Renderer   render,
+                    FT_GlyphSlot  slot,
+                    FT_UInt       mode,
+                    FT_Vector*    origin )
+  {
+    FT_Error     error;
+    FT_Outline*  outline;
+    FT_BBox      cbox;
+    FT_UInt      width, height, pitch;
+    FT_Bitmap*   bitmap;
+    FT_Memory    memory;
+
+    FT_Raster_Params  params;
+
+
+    /* check glyph image format */
+    if ( slot->format != render->glyph_format )
+    {
+      error = Smooth_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* check mode */
+    if ( mode != ft_render_mode_normal )
+      return Smooth_Err_Cannot_Render_Glyph;
+
+    outline = &slot->outline;
+
+    /* translate the outline to the new origin if needed */
+    if ( origin )
+      FT_Outline_Translate( outline, origin->x, origin->y );
+
+    /* compute the control box, and grid fit it */
+    FT_Outline_Get_CBox( outline, &cbox );
+
+    cbox.xMin &= -64;
+    cbox.yMin &= -64;
+    cbox.xMax  = ( cbox.xMax + 63 ) & -64;
+    cbox.yMax  = ( cbox.yMax + 63 ) & -64;
+
+    width  = ( cbox.xMax - cbox.xMin ) >> 6;
+    height = ( cbox.yMax - cbox.yMin ) >> 6;
+    bitmap = &slot->bitmap;
+    memory = render->root.memory;
+
+    /* release old bitmap buffer */
+    if ( slot->flags & ft_glyph_own_bitmap )
+    {
+      FREE( bitmap->buffer );
+      slot->flags &= ~ft_glyph_own_bitmap;
+    }
+
+    /* allocate new one, depends on pixel format */
+    pitch = width;
+    bitmap->pixel_mode = ft_pixel_mode_grays;
+    bitmap->num_grays  = 256;
+    bitmap->width      = width;
+    bitmap->rows       = height;
+    bitmap->pitch      = pitch;
+
+    if ( ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
+      goto Exit;
+
+    slot->flags |= ft_glyph_own_bitmap;
+
+    /* translate outline to render it into the bitmap */
+    FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+
+    /* set up parameters */
+    params.target = bitmap;
+    params.source = outline;
+    params.flags  = ft_raster_flag_aa;
+
+    /* render outline into the bitmap */
+    error = render->raster_render( render->raster, &params );
+    if ( error )
+      goto Exit;
+
+    slot->format      = ft_glyph_format_bitmap;
+    slot->bitmap_left = cbox.xMin >> 6;
+    slot->bitmap_top  = cbox.yMax >> 6;
+
+  Exit:
+    return error;
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Renderer_Class  ft_smooth_renderer_class =
+  {
+    {
+      ft_module_renderer,
+      sizeof( FT_RendererRec ),
+
+      "smooth",
+      0x10000L,
+      0x20000L,
+
+      0,    /* module specific interface */
+
+      (FT_Module_Constructor)ft_smooth_init,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    ft_glyph_format_outline,
+
+    (FTRenderer_render)   ft_smooth_render,
+    (FTRenderer_transform)ft_smooth_transform,
+    (FTRenderer_getCBox)  ft_smooth_get_cbox,
+    (FTRenderer_setMode)  ft_smooth_set_mode,
+
+    (FT_Raster_Funcs*)    &ft_grays_raster
+  };
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftstream.c b/libraries/freetype-2.0.5/ftstream.c
new file mode 100644 (file)
index 0000000..96683a2
--- /dev/null
@@ -0,0 +1,804 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftstream.c                                                             */
+/*                                                                         */
+/*    I/O stream support (body).                                           */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_DEBUG_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_stream
+
+
+  FT_BASE_DEF( void )
+  FT_New_Memory_Stream( FT_Library  library,
+                        FT_Byte*    base,
+                        FT_ULong    size,
+                        FT_Stream   stream )
+  {
+    stream->memory = library->memory;
+    stream->base   = base;
+    stream->size   = size;
+    stream->pos    = 0;
+    stream->cursor = 0;
+    stream->read   = 0;
+    stream->close  = 0;
+  }
+
+
+  FT_BASE_DEF( FT_Error )
+  FT_Seek_Stream( FT_Stream  stream,
+                  FT_ULong   pos )
+  {
+    FT_Error  error;
+
+
+    stream->pos = pos;
+
+    if ( stream->read )
+    {
+      if ( stream->read( stream, pos, 0, 0 ) )
+      {
+        FT_ERROR(( "FT_Seek_Stream:" ));
+        FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+                   pos, stream->size ));
+
+        error = FT_Err_Invalid_Stream_Operation;
+      }
+      else
+        error = FT_Err_Ok;
+    }
+    /* note that seeking to the first position after the file is valid */
+    else if ( pos > stream->size )
+    {
+      FT_ERROR(( "FT_Seek_Stream:" ));
+      FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+                 pos, stream->size ));
+
+      error = FT_Err_Invalid_Stream_Operation;
+    }
+
+    else
+      error = FT_Err_Ok;
+
+    return error;
+  }
+
+
+  FT_BASE_DEF( FT_Error )
+  FT_Skip_Stream( FT_Stream  stream,
+                  FT_Long    distance )
+  {
+    return FT_Seek_Stream( stream, (FT_ULong)( stream->pos + distance ) );
+  }
+
+
+  FT_BASE_DEF( FT_Long )
+  FT_Stream_Pos( FT_Stream  stream )
+  {
+    return stream->pos;
+  }
+
+
+  FT_BASE_DEF( FT_Error )
+  FT_Read_Stream( FT_Stream  stream,
+                  FT_Byte*   buffer,
+                  FT_ULong   count )
+  {
+    return FT_Read_Stream_At( stream, stream->pos, buffer, count );
+  }
+
+
+  FT_BASE_DEF( FT_Error )
+  FT_Read_Stream_At( FT_Stream  stream,
+                     FT_ULong   pos,
+                     FT_Byte*   buffer,
+                     FT_ULong   count )
+  {
+    FT_Error  error = FT_Err_Ok;
+    FT_ULong  read_bytes;
+
+
+    if ( pos >= stream->size )
+    {
+      FT_ERROR(( "FT_Read_Stream_At:" ));
+      FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+                 pos, stream->size ));
+
+      return FT_Err_Invalid_Stream_Operation;
+    }
+
+    if ( stream->read )
+      read_bytes = stream->read( stream, pos, buffer, count );
+    else
+    {
+      read_bytes = stream->size - pos;
+      if ( read_bytes > count )
+        read_bytes = count;
+
+      MEM_Copy( buffer, stream->base + pos, read_bytes );
+    }
+
+    stream->pos = pos + read_bytes;
+
+    if ( read_bytes < count )
+    {
+      FT_ERROR(( "FT_Read_Stream_At:" ));
+      FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
+                 count, read_bytes ));
+
+      error = FT_Err_Invalid_Stream_Operation;
+    }
+
+    return error;
+  }
+
+
+  FT_BASE_DEF( FT_Error )
+  FT_Extract_Frame( FT_Stream  stream,
+                    FT_ULong   count,
+                    FT_Byte**  pbytes )
+  {
+    FT_Error  error;
+
+
+    error = FT_Access_Frame( stream, count );
+    if ( !error )
+    {
+      *pbytes = (FT_Byte*)stream->cursor;
+
+      /* equivalent to FT_Forget_Frame(), with no memory block release */
+      stream->cursor = 0;
+      stream->limit  = 0;
+    }
+
+    return error;
+  }
+
+
+  FT_BASE_DEF( void )
+  FT_Release_Frame( FT_Stream  stream,
+                    FT_Byte**  pbytes )
+  {
+    if ( stream->read )
+    {
+      FT_Memory  memory = stream->memory;
+
+
+      FREE( *pbytes );
+    }
+    *pbytes = 0;
+  }
+
+
+  FT_BASE_DEF( FT_Error )
+  FT_Access_Frame( FT_Stream  stream,
+                   FT_ULong   count )
+  {
+    FT_Error  error = FT_Err_Ok;
+    FT_ULong  read_bytes;
+
+
+    /* check for nested frame access */
+    FT_Assert( stream && stream->cursor == 0 );
+
+    if ( stream->read )
+    {
+      /* allocate the frame in memory */
+      FT_Memory  memory = stream->memory;
+
+
+      if ( ALLOC( stream->base, count ) )
+        goto Exit;
+
+      /* read it */
+      read_bytes = stream->read( stream, stream->pos,
+                                 stream->base, count );
+      if ( read_bytes < count )
+      {
+        FT_ERROR(( "FT_Access_Frame:" ));
+        FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
+                   count, read_bytes ));
+
+        FREE( stream->base );
+        error = FT_Err_Invalid_Stream_Operation;
+      }
+      stream->cursor = stream->base;
+      stream->limit  = stream->cursor + count;
+      stream->pos   += read_bytes;
+    }
+    else
+    {
+      /* check current and new position */
+      if ( stream->pos >= stream->size        ||
+           stream->pos + count > stream->size )
+      {
+        FT_ERROR(( "FT_Access_Frame:" ));
+        FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
+                   stream->pos, count, stream->size ));
+
+        error = FT_Err_Invalid_Stream_Operation;
+        goto Exit;
+      }
+
+      /* set cursor */
+      stream->cursor = stream->base + stream->pos;
+      stream->limit  = stream->cursor + count;
+      stream->pos   += count;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  FT_BASE_DEF( void )
+  FT_Forget_Frame( FT_Stream  stream )
+  {
+    /* IMPORTANT: The assertion stream->cursor != 0 was removed, given    */
+    /*            that it is possible to access a frame of length 0 in    */
+    /*            some weird fonts (usually, when accessing an array of   */
+    /*            0 records, like in some strange kern tables).           */
+    /*                                                                    */
+    /*  In this case, the loader code handles the 0-length table          */
+    /*  gracefully; however, stream.cursor is really set to 0 by the      */
+    /*  FT_Access_Frame() call, and this is not an error.                 */
+    /*                                                                    */
+    FT_Assert( stream );
+
+    if ( stream->read )
+    {
+      FT_Memory  memory = stream->memory;
+
+
+      FREE( stream->base );
+    }
+    stream->cursor = 0;
+    stream->limit  = 0;
+  }
+
+
+  FT_BASE_DEF( FT_Char )
+  FT_Get_Char( FT_Stream  stream )
+  {
+    FT_Char  result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result = 0;
+    if ( stream->cursor < stream->limit )
+      result = *stream->cursor++;
+
+    return result;
+  }
+
+
+  FT_BASE_DEF( FT_Short )
+  FT_Get_Short( FT_Stream  stream )
+  {
+    FT_Byte*  p;
+    FT_Short  result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result         = 0;
+    p              = stream->cursor;
+    if ( p + 1 < stream->limit )
+      result       = NEXT_Short( p );
+    stream->cursor = p;
+
+    return result;
+  }
+
+
+  FT_BASE_DEF( FT_Short )
+  FT_Get_ShortLE( FT_Stream  stream )
+  {
+    FT_Byte*  p;
+    FT_Short  result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result         = 0;
+    p              = stream->cursor;
+    if ( p + 1 < stream->limit )
+      result       = NEXT_ShortLE( p );
+    stream->cursor = p;
+
+    return result;
+  }
+
+
+  FT_BASE_DEF( FT_Long )
+  FT_Get_Offset( FT_Stream  stream )
+  {
+    FT_Byte*  p;
+    FT_Long   result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result         = 0;
+    p              = stream->cursor;
+    if ( p + 2 < stream->limit )
+      result       = NEXT_Offset( p );
+    stream->cursor = p;
+    return result;
+  }
+
+
+  FT_BASE_DEF( FT_Long )
+  FT_Get_Long( FT_Stream  stream )
+  {
+    FT_Byte*  p;
+    FT_Long   result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result         = 0;
+    p              = stream->cursor;
+    if ( p + 3 < stream->limit )
+      result       = NEXT_Long( p );
+    stream->cursor = p;
+    return result;
+  }
+
+
+  FT_BASE_DEF( FT_Long )
+  FT_Get_LongLE( FT_Stream  stream )
+  {
+    FT_Byte*  p;
+    FT_Long   result;
+
+
+    FT_Assert( stream && stream->cursor );
+
+    result         = 0;
+    p              = stream->cursor;
+    if ( p + 3 < stream->limit )
+      result       = NEXT_LongLE( p );
+    stream->cursor = p;
+    return result;
+  }
+
+
+  FT_BASE_DEF( FT_Char )
+  FT_Read_Char( FT_Stream  stream,
+                FT_Error*  error )
+  {
+    FT_Byte  result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->read )
+    {
+      if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
+        goto Fail;
+    }
+    else
+    {
+      if ( stream->pos < stream->size )
+        result = stream->base[stream->pos];
+      else
+        goto Fail;
+    }
+    stream->pos++;
+
+    return result;
+
+  Fail:
+    *error = FT_Err_Invalid_Stream_Operation;
+    FT_ERROR(( "FT_Read_Char:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+
+    return 0;
+  }
+
+
+  FT_BASE_DEF( FT_Short )
+  FT_Read_Short( FT_Stream  stream,
+                 FT_Error*  error )
+  {
+    FT_Byte   reads[2];
+    FT_Byte*  p = 0;
+    FT_Short  result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->pos + 1 < stream->size )
+    {
+      if ( stream->read )
+      {
+        if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
+          goto Fail;
+
+        p = reads;
+      }
+      else
+      {
+        p = stream->base + stream->pos;
+      }
+
+      if ( p )
+        result = NEXT_Short( p );
+    }
+    else
+      goto Fail;
+
+    stream->pos += 2;
+
+    return result;
+
+  Fail:
+    *error = FT_Err_Invalid_Stream_Operation;
+    FT_ERROR(( "FT_Read_Short:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+
+    return 0;
+  }
+
+
+  FT_BASE_DEF( FT_Short )
+  FT_Read_ShortLE( FT_Stream  stream,
+                   FT_Error*  error )
+  {
+    FT_Byte   reads[2];
+    FT_Byte*  p = 0;
+    FT_Short  result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->pos + 1 < stream->size )
+    {
+      if ( stream->read )
+      {
+        if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
+          goto Fail;
+
+        p = reads;
+      }
+      else
+      {
+        p = stream->base + stream->pos;
+      }
+
+      if ( p )
+        result = NEXT_ShortLE( p );
+    }
+    else
+      goto Fail;
+
+    stream->pos += 2;
+
+    return result;
+
+  Fail:
+    *error = FT_Err_Invalid_Stream_Operation;
+    FT_ERROR(( "FT_Read_Short:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+
+    return 0;
+  }
+
+
+  FT_BASE_DEF( FT_Long )
+  FT_Read_Offset( FT_Stream  stream,
+                  FT_Error*  error )
+  {
+    FT_Byte   reads[3];
+    FT_Byte*  p = 0;
+    FT_Long   result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->pos + 2 < stream->size )
+    {
+      if ( stream->read )
+      {
+        if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
+          goto Fail;
+
+        p = reads;
+      }
+      else
+      {
+        p = stream->base + stream->pos;
+      }
+
+      if ( p )
+        result = NEXT_Offset( p );
+    }
+    else
+      goto Fail;
+
+    stream->pos += 3;
+
+    return result;
+
+  Fail:
+    *error = FT_Err_Invalid_Stream_Operation;
+    FT_ERROR(( "FT_Read_Offset:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+
+    return 0;
+  }
+
+
+  FT_BASE_DEF( FT_Long )
+  FT_Read_Long( FT_Stream  stream,
+                FT_Error*  error )
+  {
+    FT_Byte   reads[4];
+    FT_Byte*  p = 0;
+    FT_Long   result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->pos + 3 < stream->size )
+    {
+      if ( stream->read )
+      {
+        if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
+          goto Fail;
+
+        p = reads;
+      }
+      else
+      {
+        p = stream->base + stream->pos;
+      }
+
+      if ( p )
+        result = NEXT_Long( p );
+    }
+    else
+      goto Fail;
+
+    stream->pos += 4;
+
+    return result;
+
+  Fail:
+    FT_ERROR(( "FT_Read_Long:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+    *error = FT_Err_Invalid_Stream_Operation;
+
+    return 0;
+  }
+
+
+  FT_BASE_DEF( FT_Long )
+  FT_Read_LongLE( FT_Stream  stream,
+                  FT_Error*  error )
+  {
+    FT_Byte   reads[4];
+    FT_Byte*  p = 0;
+    FT_Long   result = 0;
+
+
+    FT_Assert( stream );
+
+    *error = FT_Err_Ok;
+
+    if ( stream->pos + 3 < stream->size )
+    {
+      if ( stream->read )
+      {
+        if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
+          goto Fail;
+
+        p = reads;
+      }
+      else
+      {
+        p = stream->base + stream->pos;
+      }
+
+      if ( p )
+        result = NEXT_LongLE( p );
+    }
+    else
+      goto Fail;
+
+    stream->pos += 4;
+
+    return result;
+
+  Fail:
+    FT_ERROR(( "FT_Read_Long:" ));
+    FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
+               stream->pos, stream->size ));
+    *error = FT_Err_Invalid_Stream_Operation;
+
+    return 0;
+  }
+
+
+  FT_BASE_DEF( FT_Error )
+  FT_Read_Fields( FT_Stream              stream,
+                  const FT_Frame_Field*  fields,
+                  void*                  structure )
+  {
+    FT_Error  error;
+    FT_Bool   frame_accessed = 0;
+    FT_Byte*  cursor = stream->cursor;
+
+
+    if ( !fields || !stream )
+      return FT_Err_Invalid_Argument;
+
+    error = FT_Err_Ok;
+    do
+    {
+      FT_ULong  value;
+      FT_Int    sign_shift;
+      FT_Byte*  p;
+
+
+      switch ( fields->value )
+      {
+      case ft_frame_start:  /* access a new frame */
+        error = FT_Access_Frame( stream, fields->offset );
+        if ( error )
+          goto Exit;
+
+        frame_accessed = 1;
+        cursor         = stream->cursor;
+        fields++;
+        continue;  /* loop! */
+
+      case ft_frame_bytes:  /* read a byte sequence */
+      case ft_frame_skip:   /* skip some bytes      */
+        {
+          FT_UInt  len = fields->size;
+
+
+          if ( cursor + len > stream->limit )
+          {
+            error = FT_Err_Invalid_Stream_Operation;
+            goto Exit;
+          }
+
+          if ( fields->value == ft_frame_bytes )
+          {
+            p = (FT_Byte*)structure + fields->offset;
+            MEM_Copy( p, cursor, len );
+          }
+          cursor += len;
+          fields++;
+          continue;
+        }
+
+      case ft_frame_byte:
+      case ft_frame_schar:  /* read a single byte */
+        value = NEXT_Byte(cursor);
+        sign_shift = 24;
+        break;
+
+      case ft_frame_short_be:
+      case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
+        value = NEXT_UShort(cursor);
+        sign_shift = 16;
+        break;
+
+      case ft_frame_short_le:
+      case ft_frame_ushort_le:  /* read a 2-byte little-endian short */
+        value = NEXT_UShortLE(cursor);
+        sign_shift = 16;
+        break;
+
+      case ft_frame_long_be:
+      case ft_frame_ulong_be:  /* read a 4-byte big-endian long */
+        value = NEXT_ULong(cursor);
+        sign_shift = 0;
+        break;
+
+      case ft_frame_long_le:
+      case ft_frame_ulong_le:  /* read a 4-byte little-endian long */
+        value = NEXT_ULongLE(cursor);
+        sign_shift = 0;
+        break;
+
+      case ft_frame_off3_be:
+      case ft_frame_uoff3_be:  /* read a 3-byte big-endian long */
+        value = NEXT_UOffset(cursor);
+        sign_shift = 8;
+        break;
+
+      case ft_frame_off3_le:
+      case ft_frame_uoff3_le:  /* read a 3-byte little-endian long */
+        value = NEXT_UOffsetLE(cursor);
+        sign_shift = 8;
+        break;
+
+      default:
+        /* otherwise, exit the loop */
+        stream->cursor = cursor;
+        goto Exit;
+      }
+
+      /* now, compute the signed value is necessary */
+      if ( fields->value & FT_FRAME_OP_SIGNED )
+        value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
+
+      /* finally, store the value in the object */
+
+      p = (FT_Byte*)structure + fields->offset;
+      switch ( fields->size )
+      {
+      case 1:
+        *(FT_Byte*)p = (FT_Byte)value;
+        break;
+
+      case 2:
+        *(FT_UShort*)p = (FT_UShort)value;
+        break;
+
+      case 4:
+        *(FT_UInt32*)p = (FT_UInt32)value;
+        break;
+
+      default:  /* for 64-bit systems */
+        *(FT_ULong*)p = (FT_ULong)value;
+      }
+
+      /* go to next field */
+      fields++;
+    }
+    while ( 1 );
+
+  Exit:
+    /* close the frame if it was opened by this read */
+    if ( frame_accessed )
+      FT_Forget_Frame( stream );
+
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftsynth.c b/libraries/freetype-2.0.5/ftsynth.c
new file mode 100644 (file)
index 0000000..e82747b
--- /dev/null
@@ -0,0 +1,399 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsynth.c                                                              */
+/*                                                                         */
+/*    FreeType synthesizing code for emboldening and slanting (body).      */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_CALC_H
+#include FT_OUTLINE_H
+#include FT_SYNTHESIS_H
+
+
+#define FT_BOLD_THRESHOLD  0x0100
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   EXPERIMENTAL OBLIQUING SUPPORT                                ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_Oblique( FT_GlyphSlot  original,
+                      FT_Outline*   outline,
+                      FT_Pos*       advance )
+  {
+    FT_Matrix  transform;
+
+    FT_UNUSED( original );
+    /* we don't touch the advance width */
+    FT_UNUSED( advance );
+
+
+
+    /* For italic, simply apply a shear transform, with an angle */
+    /* of about 12 degrees.                                      */
+
+    transform.xx = 0x10000L;
+    transform.yx = 0x00000L;
+
+    transform.xy = 0x06000L;
+    transform.yy = 0x10000L;
+
+    FT_Outline_Transform( outline, &transform );
+
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT                    ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* Compute the norm of a vector */
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+  static FT_Pos
+  ft_norm( FT_Vector*  vec )
+  {
+    FT_Int64  t1, t2;
+
+
+    MUL_64( vec->x, vec->x, t1 );
+    MUL_64( vec->y, vec->y, t2 );
+    ADD_64( t1, t2, t1 );
+
+    return (FT_Pos)SQRT_64( t1 );
+  }
+
+#else /* FT_CONFIG_OPTION_OLD_CALCS */
+
+  static FT_Pos
+  ft_norm( FT_Vector*  vec )
+  {
+    FT_F26Dot6  u, v, d;
+    FT_Int      shift;
+    FT_ULong    H, L, L2, hi, lo, med;
+
+
+    u = vec->x; if ( u < 0 ) u = -u;
+    v = vec->y; if ( v < 0 ) v = -v;
+
+    if ( u < v )
+    {
+      d = u;
+      u = v;
+      v = d;
+    }
+
+    /* check that we are not trying to normalize zero! */
+    if ( u == 0 )
+      return 0;
+
+    /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */
+    hi  = (FT_ULong)u >> 16;
+    lo  = (FT_ULong)u & 0xFFFF;
+    med = hi * lo;
+
+    H     = hi * hi + ( med >> 15 );
+    med <<= 17;
+    L     = lo * lo + med;
+    if ( L < med )
+      H++;
+
+    hi  = (FT_ULong)v >> 16;
+    lo  = (FT_ULong)v & 0xFFFF;
+    med = hi * lo;
+
+    H    += hi * hi + ( med >> 15 );
+    med <<= 17;
+    L2    = lo * lo + med;
+    if ( L2 < med )
+      H++;
+
+    L += L2;
+    if ( L < L2 )
+      H++;
+
+    /* if the value is smaller than 32 bits */
+    shift = 0;
+    if ( H == 0 )
+    {
+      while ( ( L & 0xC0000000UL ) == 0 )
+      {
+        L <<= 2;
+        shift++;
+      }
+      return ( FT_Sqrt32( L ) >> shift );
+    }
+    else
+    {
+      while ( H )
+      {
+        L   = ( L >> 2 ) | ( H << 30 );
+        H >>= 2;
+        shift++;
+      }
+      return ( FT_Sqrt32( L ) << shift );
+    }
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+  static int
+  ft_test_extrema( FT_Outline*  outline,
+                   int          n )
+  {
+    FT_Vector  *prev, *cur, *next;
+    FT_Pos      product;
+    FT_Int      c, first, last;
+
+
+    /* we need to compute the `previous' and `next' point */
+    /* for these extrema.                                 */
+    cur   = outline->points + n;
+    prev  = cur - 1;
+    next  = cur + 1;
+
+    first = 0;
+    for ( c = 0; c < outline->n_contours; c++ )
+    {
+      last  = outline->contours[c];
+
+      if ( n == first )
+        prev = outline->points + last;
+
+      if ( n == last )
+        next = outline->points + first;
+
+      first = last + 1;
+    }
+
+    product = FT_MulDiv( cur->x - prev->x,   /* in.x  */
+                         next->y - cur->y,   /* out.y */
+                         0x40 )
+              -
+              FT_MulDiv( cur->y - prev->y,   /* in.y  */
+                         next->x - cur->x,   /* out.x */
+                         0x40 );
+
+    if ( product )
+      product = product > 0 ? 1 : -1;
+
+    return product;
+  }
+
+
+  /* Compute the orientation of path filling.  It differs between TrueType */
+  /* and Type1 formats.  We could use the `ft_outline_reverse_fill' flag,  */
+  /* but it is better to re-compute it directly (it seems that this flag   */
+  /* isn't correctly set for some weird composite glyphs currently).       */
+  /*                                                                       */
+  /* We do this by computing bounding box points, and computing their      */
+  /* curvature.                                                            */
+  /*                                                                       */
+  /* The function returns either 1 or -1.                                  */
+  /*                                                                       */
+  static int
+  ft_get_orientation( FT_Outline*  outline )
+  {
+    FT_BBox  box;
+    FT_BBox  indices;
+    int      n, last;
+
+
+    indices.xMin = -1;
+    indices.yMin = -1;
+    indices.xMax = -1;
+    indices.yMax = -1;
+
+    box.xMin = box.yMin =  32767;
+    box.xMax = box.yMax = -32768;
+
+    /* is it empty ? */
+    if ( outline->n_contours < 1 )
+      return 1;
+
+    last = outline->contours[outline->n_contours - 1];
+
+    for ( n = 0; n <= last; n++ )
+    {
+      FT_Pos  x, y;
+
+
+      x = outline->points[n].x;
+      if ( x < box.xMin )
+      {
+        box.xMin     = x;
+        indices.xMin = n;
+      }
+      if ( x > box.xMax )
+      {
+        box.xMax     = x;
+        indices.xMax = n;
+      }
+
+      y = outline->points[n].y;
+      if ( y < box.yMin )
+      {
+        box.yMin     = y;
+        indices.yMin = n;
+      }
+      if ( y > box.yMax )
+      {
+        box.yMax     = y;
+        indices.yMax = n;
+      }
+    }
+
+    /* test orientation of the xmin */
+    n = ft_test_extrema( outline, indices.xMin );
+    if ( n )
+      goto Exit;
+
+    n = ft_test_extrema( outline, indices.yMin );
+    if ( n )
+      goto Exit;
+
+    n = ft_test_extrema( outline, indices.xMax );
+    if ( n )
+      goto Exit;
+
+    n = ft_test_extrema( outline, indices.yMax );
+    if ( !n )
+      n = 1;
+
+  Exit:
+    return n;
+  }
+
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_Embolden( FT_GlyphSlot original,
+                       FT_Outline*  outline,
+                       FT_Pos*      advance )
+  {
+    FT_Vector   u, v;
+    FT_Vector*  points;
+    FT_Vector   cur, prev, next;
+    FT_Pos      distance;
+    FT_Face     face = FT_SLOT_FACE( original );
+    int         c, n, first, orientation;
+
+    FT_UNUSED( advance );
+
+
+    /* compute control distance */
+    distance = FT_MulFix( face->units_per_EM / 60,
+                          face->size->metrics.y_scale );
+
+    orientation = ft_get_orientation( &original->outline );
+
+    points = original->outline.points;
+
+    first = 0;
+    for ( c = 0; c < outline->n_contours; c++ )
+    {
+      int  last = outline->contours[c];
+
+
+      prev = points[last];
+
+      for ( n = first; n <= last; n++ )
+      {
+        FT_Pos     norm, delta, d;
+        FT_Vector  in, out;
+
+
+        cur = points[n];
+        if ( n < last ) next = points[n + 1];
+        else            next = points[first];
+
+        /* compute the in and out vectors */
+        in.x  = cur.x - prev.x;
+        in.y  = cur.y - prev.y;
+
+        out.x = next.x - cur.x;
+        out.y = next.y - cur.y;
+
+        /* compute U and V */
+        norm = ft_norm( &in );
+        u.x = orientation *  FT_DivFix( in.y, norm );
+        u.y = orientation * -FT_DivFix( in.x, norm );
+
+        norm = ft_norm( &out );
+        v.x = orientation *  FT_DivFix( out.y, norm );
+        v.y = orientation * -FT_DivFix( out.x, norm );
+
+        d = distance;
+
+        if ( ( outline->tags[n] & FT_Curve_Tag_On ) == 0 )
+          d *= 2;
+
+        /* Check discriminant for parallel vectors */
+        delta = FT_MulFix( u.x, v.y ) - FT_MulFix( u.y, v.x );
+        if ( delta > FT_BOLD_THRESHOLD || delta < -FT_BOLD_THRESHOLD )
+        {
+          /* Move point -- compute A and B */
+          FT_Pos  x, y, A, B;
+
+
+          A = d + FT_MulFix( cur.x, u.x ) + FT_MulFix( cur.y, u.y );
+          B = d + FT_MulFix( cur.x, v.x ) + FT_MulFix( cur.y, v.y );
+
+          x = FT_MulFix( A, v.y ) - FT_MulFix( B, u.y );
+          y = FT_MulFix( B, u.x ) - FT_MulFix( A, v.x );
+
+          outline->points[n].x = distance + FT_DivFix( x, delta );
+          outline->points[n].y = distance + FT_DivFix( y, delta );
+        }
+        else
+        {
+          /* Vectors are nearly parallel */
+          FT_Pos  x, y;
+
+
+          x = distance + cur.x + FT_MulFix( d, u.x + v.x ) / 2;
+          y = distance + cur.y + FT_MulFix( d, u.y + v.y ) / 2;
+
+          outline->points[n].x = x;
+          outline->points[n].y = y;
+        }
+
+        prev = cur;
+      }
+
+      first = last + 1;
+    }
+
+    if ( advance )
+      *advance = ( *advance + distance * 4 ) & -64;
+
+    return 0;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ftsystem.c b/libraries/freetype-2.0.5/ftsystem.c
new file mode 100644 (file)
index 0000000..0bee111
--- /dev/null
@@ -0,0 +1,287 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsystem.c                                                             */
+/*                                                                         */
+/*    ANSI-specific FreeType low-level system interface (body).            */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file contains the default interface used by FreeType to access   */
+  /* low-level, i.e. memory management, i/o access as well as thread       */
+  /* synchronisation.  It can be replaced by user-specific routines if     */
+  /* necessary.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_SYSTEM_H
+#include FT_ERRORS_H
+#include FT_TYPES_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       MEMORY MANAGEMENT INTERFACE                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* It is not necessary to do any error checking for the                  */
+  /* allocation-related functions.  This will be done by the higher level  */
+  /* routines like FT_Alloc() or FT_Realloc().                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_alloc                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The memory allocation function.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A pointer to the memory object.                          */
+  /*                                                                       */
+  /*    size   :: The requested size in bytes.                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of newly allocated block.                              */
+  /*                                                                       */
+  FT_CALLBACK_DEF( void* )
+  ft_alloc( FT_Memory  memory,
+            long       size )
+  {
+    FT_UNUSED( memory );
+
+    return malloc( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_realloc                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The memory reallocation function.                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory   :: A pointer to the memory object.                        */
+  /*                                                                       */
+  /*    cur_size :: The current size of the allocated memory block.        */
+  /*                                                                       */
+  /*    new_size :: The newly requested size in bytes.                     */
+  /*                                                                       */
+  /*    block    :: The current address of the block in memory.            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the reallocated memory block.                       */
+  /*                                                                       */
+  FT_CALLBACK_DEF( void* )
+  ft_realloc( FT_Memory  memory,
+              long       cur_size,
+              long       new_size,
+              void*      block )
+  {
+    FT_UNUSED( memory );
+    FT_UNUSED( cur_size );
+
+    return realloc( block, new_size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_free                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The memory release function.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory  :: A pointer to the memory object.                         */
+  /*                                                                       */
+  /*    block   :: The address of block in memory to be freed.             */
+  /*                                                                       */
+  FT_CALLBACK_DEF( void )
+  ft_free( FT_Memory  memory,
+           void*      block )
+  {
+    FT_UNUSED( memory );
+
+    free( block );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                     RESOURCE MANAGEMENT INTERFACE                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_io
+
+  /* We use the macro STREAM_FILE for convenience to extract the       */
+  /* system-specific stream handle from a given FreeType stream object */
+#define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_close_stream                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The function to close a stream.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: A pointer to the stream object.                          */
+  /*                                                                       */
+  FT_CALLBACK_DEF( void )
+  ft_close_stream( FT_Stream  stream )
+  {
+    fclose( STREAM_FILE( stream ) );
+
+    stream->descriptor.pointer = NULL;
+    stream->size               = 0;
+    stream->base               = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_io_stream                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The function to open a stream.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: A pointer to the stream object.                          */
+  /*                                                                       */
+  /*    offset :: The position in the data stream to start reading.        */
+  /*                                                                       */
+  /*    buffer :: The address of buffer to store the read data.            */
+  /*                                                                       */
+  /*    count  :: The number of bytes to read from the stream.             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The number of bytes actually read.                                 */
+  /*                                                                       */
+  FT_CALLBACK_DEF( unsigned long )
+  ft_io_stream( FT_Stream       stream,
+                unsigned long   offset,
+                unsigned char*  buffer,
+                unsigned long   count )
+  {
+    FILE*  file;
+
+
+    file = STREAM_FILE( stream );
+
+    fseek( file, offset, SEEK_SET );
+
+    return (unsigned long)fread( buffer, 1, count, file );
+  }
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_New_Stream( const char*  filepathname,
+                 FT_Stream    astream )
+  {
+    FILE*  file;
+
+
+    if ( !astream )
+      return FT_Err_Invalid_Stream_Handle;
+
+    file = fopen( filepathname, "rb" );
+    if ( !file )
+    {
+      FT_ERROR(( "FT_New_Stream:" ));
+      FT_ERROR(( " could not open `%s'\n", filepathname ));
+
+      return FT_Err_Cannot_Open_Resource;
+    }
+
+    fseek( file, 0, SEEK_END );
+    astream->size = ftell( file );
+    fseek( file, 0, SEEK_SET );
+
+    astream->descriptor.pointer = file;
+    astream->pathname.pointer   = (char*)filepathname;
+    astream->pos                = 0;
+
+    astream->read  = ft_io_stream;
+    astream->close = ft_close_stream;
+
+    FT_TRACE1(( "FT_New_Stream:" ));
+    FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
+                filepathname, astream->size ));
+
+    return FT_Err_Ok;
+  }
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_EXPORT_DEF( FT_Memory )
+  FT_New_Memory( void )
+  {
+    FT_Memory  memory;
+
+
+    memory = (FT_Memory)malloc( sizeof ( *memory ) );
+    if ( memory )
+    {
+      memory->user    = 0;
+      memory->alloc   = ft_alloc;
+      memory->realloc = ft_realloc;
+      memory->free    = ft_free;
+    }
+
+    return memory;
+  }
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Done_Memory( FT_Memory  memory )
+  {
+    memory->free( memory, memory );
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/fttrigon.c b/libraries/freetype-2.0.5/fttrigon.c
new file mode 100644 (file)
index 0000000..cd19803
--- /dev/null
@@ -0,0 +1,450 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fttrigon.c                                                             */
+/*                                                                         */
+/*    FreeType trigonometric functions (body).                             */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_TRIGONOMETRY_H
+
+
+  /* the following is 0.2715717684432231 * 2^30 */
+#define FT_TRIG_COSCALE  0x11616E8EUL
+
+  /* this table was generated for FT_PI = 180L << 16, i.e. degrees */
+#define FT_TRIG_MAX_ITERS  23
+
+  static const FT_Fixed
+  ft_trig_arctan_table[24] =
+  {
+    4157273L, 2949120L, 1740967L, 919879L, 466945L, 234379L, 117304L,
+    58666L, 29335L, 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
+    57L, 29L, 14L, 7L, 4L, 2L, 1L
+  };
+
+  /* the Cordic shrink factor, multiplied by 2^32 */
+#define FT_TRIG_SCALE    1166391785UL  /* 0x4585BA38UL */
+
+
+#ifdef FT_CONFIG_HAS_INT64
+
+  /* multiply a given value by the CORDIC shrink factor */
+  static FT_Fixed
+  ft_trig_downscale( FT_Fixed  val )
+  {
+    FT_Fixed  s;
+    FT_Int64  v;
+
+
+    s   = val;
+    val = ( val >= 0 ) ? val : -val;
+
+    v   = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
+    val = (FT_Fixed)( v >> 32 );
+
+    return ( s >= 0 ) ? val : -val;
+  }
+
+#else /* !FT_CONFIG_HAS_INT64 */
+
+  /* multiply a given value by the CORDIC shrink factor */
+  static FT_Fixed
+  ft_trig_downscale( FT_Fixed  val )
+  {
+    FT_Fixed   s;
+    FT_UInt32  v1, v2, k1, k2, hi, lo1, lo2, lo3;
+
+
+    s   = val;
+    val = ( val >= 0 ) ? val : -val;
+
+    v1 = (FT_UInt32)val >> 16;
+    v2 = (FT_UInt32)val & 0xFFFF;
+
+    k1 = FT_TRIG_SCALE >> 16;       /* constant */
+    k2 = FT_TRIG_SCALE & 0xFFFF;    /* constant */
+
+    hi   = k1 * v1;
+    lo1  = k1 * v2 + k2 * v1;       /* can't overflow */
+
+    lo2  = ( k2 * v2 ) >> 16;
+    lo3  = ( lo1 >= lo2 ) ? lo1 : lo2;
+    lo1 += lo2;
+
+    hi  += lo1 >> 16;
+    if ( lo1 < lo3 )
+      hi += 0x10000UL;
+
+    val  = (FT_Fixed)hi;
+
+    return ( s >= 0 ) ? val : -val;
+  }
+
+#endif /* !FT_CONFIG_HAS_INT64 */
+
+
+  static FT_Int
+  ft_trig_prenorm( FT_Vector*  vec )
+  {
+    FT_Fixed  x, y, z;
+    FT_Int    shift;
+
+
+    x = vec->x;
+    y = vec->y;
+
+    z     = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );
+    shift = 0;
+
+    if ( z < ( 1L << 27 ) )
+    {
+      do
+      {
+        shift++;
+        z <<= 1;
+      } while ( z < ( 1L << 27 ) );
+
+      vec->x = x << shift;
+      vec->y = y << shift;
+    }
+    else if ( z > ( 1L << 28 ) )
+    {
+      do
+      {
+        shift++;
+        z >>= 1;
+      } while ( z > ( 1L << 28 ) );
+
+      vec->x = x >> shift;
+      vec->y = y >> shift;
+      shift  = -shift;
+    }
+    return shift;
+  }
+
+
+  static void
+  ft_trig_pseudo_rotate( FT_Vector*  vec,
+                         FT_Angle    theta )
+  {
+    FT_Int           i;
+    FT_Fixed         x, y, xtemp;
+    const FT_Fixed  *arctanptr;
+
+
+    x = vec->x;
+    y = vec->y;
+
+    /* Get angle between -90 and 90 degrees */
+    while ( theta <= -FT_ANGLE_PI2 )
+    {
+      x = -x;
+      y = -y;
+      theta += FT_ANGLE_PI;
+    }
+
+    while ( theta > FT_ANGLE_PI2 )
+    {
+      x = -x;
+      y = -y;
+      theta -= FT_ANGLE_PI;
+    }
+
+    /* Initial pseudorotation, with left shift */
+    arctanptr = ft_trig_arctan_table;
+
+    if ( theta < 0 )
+    {
+      xtemp  = x + ( y << 1 );
+      y      = y - ( x << 1 );
+      x      = xtemp;
+      theta += *arctanptr++;
+    }
+    else
+    {
+      xtemp  = x - ( y << 1 );
+      y      = y + ( x << 1 );
+      x      = xtemp;
+      theta -= *arctanptr++;
+    }
+
+    /* Subsequent pseudorotations, with right shifts */
+    i = 0;
+    do
+    {
+      if ( theta < 0 )
+      {
+        xtemp  = x + ( y >> i );
+        y      = y - ( x >> i );
+        x      = xtemp;
+        theta += *arctanptr++;
+      }
+      else
+      {
+        xtemp  = x - ( y >> i );
+        y      = y + ( x >> i );
+        x      = xtemp;
+        theta -= *arctanptr++;
+      }
+    } while ( ++i < FT_TRIG_MAX_ITERS );
+
+    vec->x = x;
+    vec->y = y;
+  }
+
+
+  static void
+  ft_trig_pseudo_polarize( FT_Vector*  vec )
+  {
+    FT_Fixed         theta;
+    FT_Fixed         yi, i;
+    FT_Fixed         x, y;
+    const FT_Fixed  *arctanptr;
+
+
+    x = vec->x;
+    y = vec->y;
+
+    /* Get the vector into the right half plane */
+    theta = 0;
+    if ( x < 0 )
+    {
+      x = -x;
+      y = -y;
+      theta = 2 * FT_ANGLE_PI2;
+    }
+
+    if ( y > 0 )
+      theta = - theta;
+
+    arctanptr = ft_trig_arctan_table;
+
+    if ( y < 0 )
+    {
+      /* Rotate positive */
+      yi     = y + ( x << 1 );
+      x      = x - ( y << 1 );
+      y      = yi;
+      theta -= *arctanptr++;  /* Subtract angle */
+    }
+    else
+    {
+      /* Rotate negative */
+      yi     = y - ( x << 1 );
+      x      = x + ( y << 1 );
+      y      = yi;
+      theta += *arctanptr++;  /* Add angle */
+    }
+
+    i = 0;
+    do
+    {
+      if ( y < 0 )
+      {
+        /* Rotate positive */
+        yi     = y + ( x >> i );
+        x      = x - ( y >> i );
+        y      = yi;
+        theta -= *arctanptr++;
+      }
+      else
+      {
+        /* Rotate negative */
+        yi     = y - ( x >> i );
+        x      = x + ( y >> i );
+        y      = yi;
+        theta += *arctanptr++;
+      }
+    } while ( ++i < FT_TRIG_MAX_ITERS );
+
+    /* round theta */
+    if ( theta >= 0 )
+      theta = ( theta + 16 ) & -32;
+    else
+      theta = - (( -theta + 16 ) & -32);
+
+    vec->x = x;
+    vec->y = theta;
+  }
+
+
+  /* documentation is in fttrigon.h */
+
+  FT_EXPORT_DEF( FT_Fixed )
+  FT_Cos( FT_Angle  angle )
+  {
+    FT_Vector  v;
+
+
+    v.x = FT_TRIG_COSCALE >> 2;
+    v.y = 0;
+    ft_trig_pseudo_rotate( &v, angle );
+
+    return v.x >> 12;
+  }
+
+
+  /* documentation is in fttrigon.h */
+
+  FT_EXPORT_DEF( FT_Fixed )
+  FT_Sin( FT_Angle  angle )
+  {
+    return FT_Cos( FT_ANGLE_PI2 - angle );
+  }
+
+
+  /* documentation is in fttrigon.h */
+
+  FT_EXPORT_DEF( FT_Fixed )
+  FT_Tan( FT_Angle  angle )
+  {
+    FT_Vector  v;
+
+
+    v.x = FT_TRIG_COSCALE >> 2;
+    v.y = 0;
+    ft_trig_pseudo_rotate( &v, angle );
+
+    return FT_DivFix( v.y, v.x );
+  }
+
+
+  /* documentation is in fttrigon.h */
+
+  FT_EXPORT_DEF( FT_Angle )
+  FT_Atan2( FT_Fixed  dx,
+            FT_Fixed  dy )
+  {
+    FT_Vector  v;
+
+
+    if ( dx == 0 && dy == 0 )
+      return 0;
+
+    v.x = dx;
+    v.y = dy;
+    ft_trig_prenorm( &v );
+    ft_trig_pseudo_polarize( &v );
+
+    return v.y;
+  }
+
+
+  /* documentation is in fttrigon.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Vector_Unit( FT_Vector*  vec,
+                  FT_Angle    angle )
+  {
+    vec->x = FT_TRIG_COSCALE >> 2;
+    vec->y = 0;
+    ft_trig_pseudo_rotate( vec, angle );
+    vec->x >>= 12;
+    vec->y >>= 12;
+  }
+
+
+  /* documentation is in fttrigon.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Vector_Rotate( FT_Vector*  vec,
+                    FT_Angle    angle )
+  {
+    FT_Int     shift;
+    FT_Vector  v;
+
+
+    v.x   = vec->x;
+    v.y   = vec->y;
+
+    if ( angle && ( v.x != 0 || v.y != 0 ) )
+    {
+      shift = ft_trig_prenorm( &v );
+      ft_trig_pseudo_rotate( &v, angle );
+      v.x = ft_trig_downscale( v.x );
+      v.y = ft_trig_downscale( v.y );
+
+      if ( shift >= 0 )
+      {
+        vec->x = v.x >> shift;
+        vec->y = v.y >> shift;
+      }
+      else
+      {
+        shift  = -shift;
+        vec->x = v.x << shift;
+        vec->y = v.y << shift;
+      }
+    }
+  }
+
+
+  /* documentation is in fttrigon.h */
+
+  FT_EXPORT_DEF( FT_Fixed )
+  FT_Vector_Length( FT_Vector*  vec )
+  {
+    FT_Int     shift;
+    FT_Vector  v;
+
+
+    v = *vec;
+
+    /* handle trivial cases */
+    if ( v.x == 0 )
+    {
+      return ( v.y >= 0 ) ? v.y : -v.y;
+    }
+    else if ( v.y == 0 )
+    {
+      return ( v.x >= 0 ) ? v.x : -v.x;
+    }
+
+    /* general case */
+    shift = ft_trig_prenorm( &v );
+    ft_trig_pseudo_polarize( &v );
+
+    v.x = ft_trig_downscale( v.x );
+    return ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift );
+  }
+
+
+  /* documentation is in fttrigon.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Vector_Polarize( FT_Vector*  vec,
+                      FT_Fixed   *length,
+                      FT_Angle   *angle )
+  {
+    FT_Int     shift;
+    FT_Vector  v;
+
+
+    v = *vec;
+
+    if ( v.x == 0 && v.y == 0 )
+      return;
+
+    shift = ft_trig_prenorm( &v );
+    ft_trig_pseudo_polarize( &v );
+
+    v.x = ft_trig_downscale( v.x );
+
+    *length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift );
+    *angle  = v.y;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/Makefile.am b/libraries/freetype-2.0.5/include/Makefile.am
new file mode 100644 (file)
index 0000000..1003015
--- /dev/null
@@ -0,0 +1,10 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_HEADERS = \
+ ahangles.h   ahoptim.h    cffparse.h   cidriver.h   ftrend1.h    psauxerr.h   sfdriver.h   t1gload.h    tterrors.h   ttsbit.h \
+ aherrors.h   ahtypes.h    cfftoken.h   cidtoken.h   ftsmerrs.h   psauxmod.h   sferrors.h   t1load.h     ttgload.h    winfnt.h \
+ ahglobal.h   cffdrivr.h   ciderrs.h    fnterrs.h    ftsmooth.h   psmodule.h   sfobjs.h     t1objs.h     ttinterp.h   \
+ ahglyph.h    cfferrs.h    cidgload.h   ft2build.h   pcf.h        psnamerr.h   t1afm.h      t1parse.h    ttload.h     \
+ ahhint.h     cffgload.h   cidload.h    ftcerror.h   pcfdriver.h  psobjs.h     t1decode.h   t1tokens.h   ttobjs.h     \
+ ahloader.h   cffload.h    cidobjs.h    ftgrays.h    pcferror.h   pstables.h   t1driver.h   ttcmap.h     ttpload.h    \
+ ahmodule.h   cffobjs.h    cidparse.h   ftraster.h   pcfutil.h    rasterrs.h   t1errors.h   ttdriver.h   ttpost.h     
diff --git a/libraries/freetype-2.0.5/include/ahangles.h b/libraries/freetype-2.0.5/include/ahangles.h
new file mode 100644 (file)
index 0000000..8ed62aa
--- /dev/null
@@ -0,0 +1,59 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahangles.h                                                             */
+/*                                                                         */
+/*    A routine used to compute vector angles with limited accuracy        */
+/*    and very high speed (specification).                                 */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __AHANGLES_H__
+#define __AHANGLES_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include "ahtypes.h"
+
+
+FT_BEGIN_HEADER
+
+
+  /* PI expressed in ah_angles -- we don't really need an important */
+  /* precision, so 256 should be enough                             */
+#define AH_PI       256
+#define AH_2PI      ( AH_PI * 2 )
+#define AH_HALF_PI  ( AH_PI / 2 )
+#define AH_2PIMASK  ( AH_2PI - 1 )
+
+  /* the number of bits used to express an arc tangent; */
+  /* see the structure of the lookup table              */
+#define AH_ATAN_BITS  8
+
+  extern
+  const AH_Angle  ah_arctan[1L << AH_ATAN_BITS];
+
+
+  FT_LOCAL AH_Angle
+  ah_angle( FT_Vector*  v );
+
+
+FT_END_HEADER
+
+#endif /* __AHANGLES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/aherrors.h b/libraries/freetype-2.0.5/include/aherrors.h
new file mode 100644 (file)
index 0000000..bce6107
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/*                                                                         */
+/*  aherrors.h                                                             */
+/*                                                                         */
+/*    Autohinter error codes (specification only).                         */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the Autohinter error enumeration          */
+  /* constants.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __AHERRORS_H__
+#define __AHERRORS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  AH_Err_
+#define FT_ERR_BASE    FT_Mod_Err_Autohint
+
+#include FT_ERRORS_H
+
+#endif /* __AHERRORS_H__ */
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ahglobal.h b/libraries/freetype-2.0.5/include/ahglobal.h
new file mode 100644 (file)
index 0000000..e9d424f
--- /dev/null
@@ -0,0 +1,49 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahglobal.h                                                             */
+/*                                                                         */
+/*    Routines used to compute global metrics automatically                */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __AHGLOBAL_H__
+#define __AHGLOBAL_H__
+
+
+#include <ft2build.h>
+#include "ahtypes.h"
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+#define AH_IS_TOP_BLUE( b )  ( (b) == ah_blue_capital_top || \
+                               (b) == ah_blue_small_top   )
+
+
+  /* compute global metrics automatically */
+  FT_LOCAL
+  FT_Error  ah_hinter_compute_globals( AH_Hinter*  hinter );
+
+
+FT_END_HEADER
+
+#endif /* __AHGLOBAL_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ahglyph.h b/libraries/freetype-2.0.5/include/ahglyph.h
new file mode 100644 (file)
index 0000000..3c50ee7
--- /dev/null
@@ -0,0 +1,93 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahglyph.h                                                              */
+/*                                                                         */
+/*    Routines used to load and analyze a given glyph before hinting       */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __AHGLYPH_H__
+#define __AHGLYPH_H__
+
+
+#include <ft2build.h>
+#include "ahtypes.h"
+
+
+FT_BEGIN_HEADER
+
+
+  typedef enum  AH_UV_
+  {
+    ah_uv_fxy,
+    ah_uv_fyx,
+    ah_uv_oxy,
+    ah_uv_oyx,
+    ah_uv_ox,
+    ah_uv_oy,
+    ah_uv_yx,
+    ah_uv_xy  /* should always be last! */
+
+  } AH_UV;
+
+
+  FT_LOCAL void
+  ah_setup_uv( AH_Outline*  outline,
+               AH_UV        source );
+
+
+  /* AH_Outline functions - they should be typically called in this order */
+
+  FT_LOCAL FT_Error
+  ah_outline_new( FT_Memory     memory,
+                  AH_Outline**  aoutline );
+
+  FT_LOCAL FT_Error
+  ah_outline_load( AH_Outline*  outline,
+                   FT_Face      face );
+
+  FT_LOCAL void
+  ah_outline_compute_segments( AH_Outline*  outline );
+
+  FT_LOCAL void
+  ah_outline_link_segments( AH_Outline*  outline );
+
+  FT_LOCAL void
+  ah_outline_detect_features( AH_Outline*  outline );
+
+  FT_LOCAL void
+  ah_outline_compute_blue_edges( AH_Outline*       outline,
+                                 AH_Face_Globals*  globals );
+
+  FT_LOCAL void
+  ah_outline_scale_blue_edges( AH_Outline*       outline,
+                               AH_Face_Globals*  globals );
+
+  FT_LOCAL void
+  ah_outline_save( AH_Outline*  outline,
+                   AH_Loader*   loader );
+
+  FT_LOCAL void
+  ah_outline_done( AH_Outline*  outline );
+
+
+FT_END_HEADER
+
+#endif /* __AHGLYPH_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ahhint.h b/libraries/freetype-2.0.5/include/ahhint.h
new file mode 100644 (file)
index 0000000..c527609
--- /dev/null
@@ -0,0 +1,75 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahhint.h                                                               */
+/*                                                                         */
+/*    Glyph hinter (declaration).                                          */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __AHHINT_H__
+#define __AHHINT_H__
+
+
+#include <ft2build.h>
+#include "ahglobal.h"
+
+
+FT_BEGIN_HEADER
+
+
+#define AH_HINT_DEFAULT        0
+#define AH_HINT_NO_ALIGNMENT   1
+#define AH_HINT_NO_HORZ_EDGES  0x20000L
+#define AH_HINT_NO_VERT_EDGES  0x40000L
+
+
+  /* create a new empty hinter object */
+  FT_LOCAL FT_Error
+  ah_hinter_new( FT_Library   library,
+                 AH_Hinter**  ahinter );
+
+  /* Load a hinted glyph in the hinter */
+  FT_LOCAL FT_Error
+  ah_hinter_load_glyph( AH_Hinter*    hinter,
+                        FT_GlyphSlot  slot,
+                        FT_Size       size,
+                        FT_UInt       glyph_index,
+                        FT_Int        load_flags );
+
+  /* finalize a hinter object */
+  FT_LOCAL void
+  ah_hinter_done( AH_Hinter*  hinter );
+
+  FT_LOCAL void
+  ah_hinter_done_face_globals( AH_Face_Globals*  globals );
+
+  FT_LOCAL void
+  ah_hinter_get_global_hints( AH_Hinter*  hinter,
+                              FT_Face     face,
+                              void**      global_hints,
+                              long*       global_len );
+
+  FT_LOCAL void
+  ah_hinter_done_global_hints( AH_Hinter*  hinter,
+                               void*       global_hints );
+
+
+FT_END_HEADER
+
+#endif /* __AHHINT_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ahloader.h b/libraries/freetype-2.0.5/include/ahloader.h
new file mode 100644 (file)
index 0000000..1f9b3a5
--- /dev/null
@@ -0,0 +1,133 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahloader.h                                                             */
+/*                                                                         */
+/*    Glyph loader for the auto-hinting module (declaration only).         */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This defines the AH_GlyphLoader type in two different ways:           */
+  /*                                                                       */
+  /* - If the module is compiled within FreeType 2, the type is simply a   */
+  /*   typedef to FT_GlyphLoader.                                          */
+  /*                                                                       */
+  /* - If the module is compiled as a standalone object, AH_GlyphLoader    */
+  /*   has its own implementation.                                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __AHLOADER_H__
+#define __AHLOADER_H__
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+
+#ifdef _STANDALONE_
+
+  typedef struct  AH_GlyphLoad_
+  {
+    FT_Outline    outline;       /* outline             */
+    FT_UInt       num_subglyphs; /* number of subglyphs */
+    FT_SubGlyph*  subglyphs;     /* subglyphs           */
+    FT_Vector*    extra_points;  /* extra points table  */
+
+  } AH_GlyphLoad;
+
+
+  struct  AH_GlyphLoader_
+  {
+    FT_Memory     memory;
+    FT_UInt       max_points;
+    FT_UInt       max_contours;
+    FT_UInt       max_subglyphs;
+    FT_Bool       use_extra;
+
+    AH_GlyphLoad  base;
+    AH_GlyphLoad  current;
+
+    void*         other;        /* for possible future extensions */
+  };
+
+
+  FT_LOCAL FT_Error
+  AH_GlyphLoader_New( FT_Memory         memory,
+                      AH_GlyphLoader**  aloader );
+
+  FT_LOCAL FT_Error
+  AH_GlyphLoader_Create_Extra( AH_GlyphLoader*  loader );
+
+  FT_LOCAL void
+  AH_GlyphLoader_Done( AH_GlyphLoader*  loader );
+
+  FT_LOCAL void
+  AH_GlyphLoader_Reset( AH_GlyphLoader*  loader );
+
+  FT_LOCAL void
+  AH_GlyphLoader_Rewind( AH_GlyphLoader*  loader );
+
+  FT_LOCAL FT_Error
+  AH_GlyphLoader_Check_Points( AH_GlyphLoader*  loader,
+                               FT_UInt          n_points,
+                               FT_UInt          n_contours );
+
+  FT_LOCAL FT_Error
+  AH_GlyphLoader_Check_Subglyphs( AH_GlyphLoader*  loader,
+                                  FT_UInt          n_subs );
+
+  FT_LOCAL void
+  AH_GlyphLoader_Prepare( AH_GlyphLoader*  loader );
+
+  FT_LOCAL void
+  AH_GlyphLoader_Add( AH_GlyphLoader*  loader );
+
+  FT_LOCAL FT_Error
+  AH_GlyphLoader_Copy_Points( AH_GlyphLoader*  target,
+                              FT_GlyphLoader*  source );
+
+#else /* _STANDALONE */
+
+#include FT_INTERNAL_OBJECTS_H
+
+  #define AH_Load    FT_GlyphLoad
+  #define AH_Loader  FT_GlyphLoader
+
+  #define ah_loader_new              FT_GlyphLoader_New
+  #define ah_loader_done             FT_GlyphLoader_Done
+  #define ah_loader_reset            FT_GlyphLoader_Reset
+  #define ah_loader_rewind           FT_GlyphLoader_Rewind
+  #define ah_loader_create_extra     FT_GlyphLoader_Create_Extra
+  #define ah_loader_check_points     FT_GlyphLoader_Check_Points
+  #define ah_loader_check_subglyphs  FT_GlyphLoader_Check_Subglyphs
+  #define ah_loader_prepare          FT_GlyphLoader_Prepare
+  #define ah_loader_add              FT_GlyphLoader_Add
+  #define ah_loader_copy_points      FT_GlyphLoader_Copy_Points
+
+#endif /* _STANDALONE_ */
+
+
+FT_END_HEADER
+
+#endif /* __AHLOADER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ahmodule.h b/libraries/freetype-2.0.5/include/ahmodule.h
new file mode 100644 (file)
index 0000000..43b1dbe
--- /dev/null
@@ -0,0 +1,42 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahmodule.h                                                             */
+/*                                                                         */
+/*    Auto-hinting module (declaration).                                   */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __AHMODULE_H__
+#define __AHMODULE_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_CALLBACK_TABLE
+  const FT_Module_Class  autohint_module_class;
+
+
+FT_END_HEADER
+
+#endif /* __AHMODULE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ahoptim.h b/libraries/freetype-2.0.5/include/ahoptim.h
new file mode 100644 (file)
index 0000000..c3e927d
--- /dev/null
@@ -0,0 +1,137 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahoptim.h                                                              */
+/*                                                                         */
+/*    FreeType auto hinting outline optimization (declaration).            */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __AHOPTIM_H__
+#define __AHOPTIM_H__
+
+
+#include <ft2build.h>
+#include "ahtypes.h"
+
+
+FT_BEGIN_HEADER
+
+
+  /* the maximal number of stem configurations to record */
+  /* during optimization                                 */
+#define AH_MAX_CONFIGS  8
+
+
+  typedef struct  AH_Stem_
+  {
+    FT_Pos    pos;       /* current position        */
+    FT_Pos    velocity;  /* current velocity        */
+    FT_Pos    force;     /* sum of current forces   */
+    FT_Pos    width;     /* normalized width        */
+
+    FT_Pos    min_pos;   /* minimum grid position */
+    FT_Pos    max_pos;   /* maximum grid position */
+
+    AH_Edge*  edge1;     /* left/bottom edge */
+    AH_Edge*  edge2;     /* right/top edge   */
+
+    FT_Pos    opos;      /* original position */
+    FT_Pos    owidth;    /* original width    */
+
+    FT_Pos    min_coord; /* minimum coordinate */
+    FT_Pos    max_coord; /* maximum coordinate */
+
+  } AH_Stem;
+
+
+  /* A spring between two stems */
+  typedef struct  AH_Spring_
+  {
+    AH_Stem*  stem1;
+    AH_Stem*  stem2;
+    FT_Pos    owidth;   /* original width  */
+    FT_Pos    tension;  /* current tension */
+
+  } AH_Spring;
+
+
+  /* A configuration records the position of each stem at a given time  */
+  /* as well as the associated distortion                               */
+  typedef struct AH_Configuration_
+  {
+    FT_Pos*  positions;
+    FT_Long  distortion;
+
+  } AH_Configuration;
+
+
+  typedef struct  AH_Optimizer_
+  {
+    FT_Memory         memory;
+    AH_Outline*       outline;
+
+    FT_Int            num_hstems;
+    AH_Stem*          horz_stems;
+
+    FT_Int            num_vstems;
+    AH_Stem*          vert_stems;
+
+    FT_Int            num_hsprings;
+    FT_Int            num_vsprings;
+    AH_Spring*        horz_springs;
+    AH_Spring*        vert_springs;
+
+    FT_Int            num_configs;
+    AH_Configuration  configs[AH_MAX_CONFIGS];
+    FT_Pos*           positions;
+
+    /* during each pass, use these instead */
+    FT_Int            num_stems;
+    AH_Stem*          stems;
+
+    FT_Int            num_springs;
+    AH_Spring*        springs;
+    FT_Bool           vertical;
+
+    FT_Fixed          tension_scale;
+    FT_Pos            tension_threshold;
+
+  } AH_Optimizer;
+
+
+  /* loads the outline into the optimizer */
+  int
+  AH_Optimizer_Init( AH_Optimizer*  optimizer,
+                     AH_Outline*    outline,
+                     FT_Memory      memory );
+
+
+  /* compute optimal outline */
+  void
+  AH_Optimizer_Compute( AH_Optimizer*  optimizer );
+
+
+  /* release the optimization data */
+  void
+  AH_Optimizer_Done( AH_Optimizer*  optimizer );
+
+
+FT_END_HEADER
+
+#endif /* __AHOPTIM_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ahtypes.h b/libraries/freetype-2.0.5/include/ahtypes.h
new file mode 100644 (file)
index 0000000..2b7b4f0
--- /dev/null
@@ -0,0 +1,493 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ahtypes.h                                                              */
+/*                                                                         */
+/*    General types and definitions for the auto-hint module               */
+/*    (specification only).                                                */
+/*                                                                         */
+/*  Copyright 2000-2001 Catharon Productions Inc.                          */
+/*  Author: David Turner                                                   */
+/*                                                                         */
+/*  This file is part of the Catharon Typography Project and shall only    */
+/*  be used, modified, and distributed under the terms of the Catharon     */
+/*  Open Source License that should come with this file under the name     */
+/*  `CatharonLicense.txt'.  By continuing to use, modify, or distribute    */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/*  Note that this license is compatible with the FreeType license.        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __AHTYPES_H__
+#define __AHTYPES_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include "ahloader.h"
+
+
+#define xxAH_DEBUG
+
+
+#ifdef AH_DEBUG
+
+#include <stdio.h>
+#define AH_LOG( x )  printf ## x
+
+#else
+
+#define AH_LOG( x )  do ; while ( 0 ) /* nothing */
+
+#endif /* AH_DEBUG */
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /**** COMPILE-TIME BUILD OPTIONS                                      ****/
+  /****                                                                 ****/
+  /**** Toggle these configuration macros to experiment with `features' ****/
+  /**** of the auto-hinter.                                             ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* If this option is defined, only strong interpolation will be used to  */
+  /* place the points between edges.  Otherwise, `smooth' points are       */
+  /* detected and later hinted through weak interpolation to correct some  */
+  /* unpleasant artefacts.                                                 */
+  /*                                                                       */
+#undef AH_OPTION_NO_WEAK_INTERPOLATION
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* If this option is defined, only weak interpolation will be used to    */
+  /* place the points between edges.  Otherwise, `strong' points are       */
+  /* detected and later hinted through strong interpolation to correct     */
+  /* some unpleasant artefacts.                                            */
+  /*                                                                       */
+#undef AH_OPTION_NO_STRONG_INTERPOLATION
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Undefine this macro if you don't want to hint the metrics.  There is  */
+  /* no reason to do this (at least for non-CJK scripts), except for       */
+  /* experimentation.                                                      */
+  /*                                                                       */
+#define AH_HINT_METRICS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define this macro if you do not want to insert extra edges at a       */
+  /* glyph's x and y extremum (if there isn't one already available).      */
+  /* This helps to reduce a number of artefacts and allows hinting of      */
+  /* metrics.                                                              */
+  /*                                                                       */
+#undef AH_OPTION_NO_EXTREMUM_EDGES
+
+
+  /* don't touch for now */
+#define AH_MAX_WIDTHS   12
+#define AH_MAX_HEIGHTS  12
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   TYPE DEFINITIONS                                              ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* see agangles.h */
+  typedef FT_Int  AH_Angle;
+
+
+  /* hint flags */
+#define ah_flah_none       0
+
+  /* bezier control points flags */
+#define ah_flah_conic                 1
+#define ah_flah_cubic                 2
+#define ah_flah_control               ( ah_flah_conic | ah_flah_cubic )
+
+  /* extrema flags */
+#define ah_flah_extrema_x             4
+#define ah_flah_extrema_y             8
+
+  /* roundness */
+#define ah_flah_round_x              16
+#define ah_flah_round_y              32
+
+  /* touched */
+#define ah_flah_touch_x              64
+#define ah_flah_touch_y             128
+
+  /* weak interpolation */
+#define ah_flah_weak_interpolation  256
+
+  typedef FT_Int AH_Flags;
+
+
+  /* edge hint flags */
+#define ah_edge_normal  0
+#define ah_edge_round   1
+#define ah_edge_serif   2
+#define ah_edge_done    4
+
+  typedef FT_Int  AH_Edge_Flags;
+
+
+  /* hint directions -- the values are computed so that two vectors are */
+  /* in opposite directions iff `dir1+dir2 == 0'                        */
+#define ah_dir_none    4
+#define ah_dir_right   1
+#define ah_dir_left   -1
+#define ah_dir_up      2
+#define ah_dir_down   -2
+
+  typedef FT_Int  AH_Direction;
+
+
+  typedef struct AH_Point    AH_Point;
+  typedef struct AH_Segment  AH_Segment;
+  typedef struct AH_Edge     AH_Edge;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    AH_Point                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model an outline point to the AH_Outline type. */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    flags     :: The current point hint flags.                         */
+  /*                                                                       */
+  /*    ox, oy    :: The current original scaled coordinates.              */
+  /*                                                                       */
+  /*    fx, fy    :: The current coordinates in font units.                */
+  /*                                                                       */
+  /*    x,  y     :: The current hinter coordinates.                       */
+  /*                                                                       */
+  /*    u, v      :: Point coordinates -- meaning varies with context.     */
+  /*                                                                       */
+  /*    in_dir    :: The direction of the inwards vector (prev->point).    */
+  /*                                                                       */
+  /*    out_dir   :: The direction of the outwards vector (point->next).   */
+  /*                                                                       */
+  /*    in_angle  :: The angle of the inwards vector.                      */
+  /*                                                                       */
+  /*    out_angle :: The angle of the outwards vector.                     */
+  /*                                                                       */
+  /*    next      :: The next point in same contour.                       */
+  /*                                                                       */
+  /*    prev      :: The previous point in same contour.                   */
+  /*                                                                       */
+  struct AH_Point
+  {
+    AH_Flags      flags;    /* point flags used by hinter */
+    FT_Pos        ox, oy;
+    FT_Pos        fx, fy;
+    FT_Pos        x,  y;
+    FT_Pos        u,  v;
+
+    AH_Direction  in_dir;   /* direction of inwards vector  */
+    AH_Direction  out_dir;  /* direction of outwards vector */
+
+    AH_Angle      in_angle;
+    AH_Angle      out_angle;
+
+    AH_Point*     next;     /* next point in contour     */
+    AH_Point*     prev;     /* previous point in contour */
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    AH_Segment                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe an edge segment to the auto-hinter.   */
+  /*    A segment is simply a sequence of successive points located on the */
+  /*    same horizontal or vertical `position', in a given direction.      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    flags      :: The segment edge flags (straight, rounded, etc.).    */
+  /*                                                                       */
+  /*    dir        :: The segment direction.                               */
+  /*                                                                       */
+  /*    first      :: The first point in the segment.                      */
+  /*                                                                       */
+  /*    last       :: The last point in the segment.                       */
+  /*                                                                       */
+  /*    contour    :: A pointer to the first point of the segment's        */
+  /*                  contour.                                             */
+  /*                                                                       */
+  /*    pos        :: The segment position in font units.                  */
+  /*                                                                       */
+  /*    size       :: The segment size.                                    */
+  /*                                                                       */
+  /*    edge       :: The edge of the current segment.                     */
+  /*                                                                       */
+  /*    edge_next  :: The next segment on the same edge.                   */
+  /*                                                                       */
+  /*    link       :: The pairing segment for this edge.                   */
+  /*                                                                       */
+  /*    serif      :: The primary segment for serifs.                      */
+  /*                                                                       */
+  /*    num_linked :: The number of other segments that link to this one.  */
+  /*                                                                       */
+  /*    score      :: Used to score the segment when selecting them.       */
+  /*                                                                       */
+  struct AH_Segment
+  {
+    AH_Edge_Flags  flags;
+    AH_Direction   dir;
+
+    AH_Point*      first;       /* first point in edge segment             */
+    AH_Point*      last;        /* last point in edge segment              */
+    AH_Point**     contour;     /* ptr to first point of segment's contour */
+
+    FT_Pos         pos;         /* position of segment           */
+    FT_Pos         min_coord;   /* minimum coordinate of segment */
+    FT_Pos         max_coord;   /* maximum coordinate of segment */
+
+    AH_Edge*       edge;
+    AH_Segment*    edge_next;
+
+    AH_Segment*    link;        /* link segment               */
+    AH_Segment*    serif;       /* primary segment for serifs */
+    FT_Pos         num_linked;  /* number of linked segments  */
+    FT_Int         score;
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    AH_Edge                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe an edge, which really is a horizontal */
+  /*    or vertical coordinate to be hinted depending on the segments      */
+  /*    located on it.                                                     */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    flags      :: The segment edge flags (straight, rounded, etc.).    */
+  /*                                                                       */
+  /*    dir        :: The main segment direction on this edge.             */
+  /*                                                                       */
+  /*    first      :: The first edge segment.                              */
+  /*                                                                       */
+  /*    last       :: The last edge segment.                               */
+  /*                                                                       */
+  /*    fpos       :: The original edge position in font units.            */
+  /*                                                                       */
+  /*    opos       :: The original scaled edge position.                   */
+  /*                                                                       */
+  /*    pos        :: The hinted edge position.                            */
+  /*                                                                       */
+  /*    link       :: The linked edge.                                     */
+  /*                                                                       */
+  /*    serif      :: The serif edge.                                      */
+  /*                                                                       */
+  /*    num_paired :: The number of other edges that pair to this one.     */
+  /*                                                                       */
+  /*    score      :: Used to score the edge when selecting them.          */
+  /*                                                                       */
+  /*    blue_edge  :: Indicate the blue zone edge this edge is related to. */
+  /*                  Only set for some of the horizontal edges in a Latin */
+  /*                  font.                                                */
+  /*                                                                       */
+  struct AH_Edge
+  {
+    AH_Edge_Flags  flags;
+    AH_Direction   dir;
+
+    AH_Segment*    first;
+    AH_Segment*    last;
+
+    FT_Pos         fpos;
+    FT_Pos         opos;
+    FT_Pos         pos;
+
+    AH_Edge*       link;
+    AH_Edge*       serif;
+    FT_Int         num_linked;
+
+    FT_Int         score;
+    FT_Pos*        blue_edge;
+  };
+
+
+  /* an outline as seen by the hinter */
+  typedef struct  AH_Outline_
+  {
+    FT_Memory     memory;
+
+    AH_Direction  vert_major_dir;   /* vertical major direction   */
+    AH_Direction  horz_major_dir;   /* horizontal major direction */
+
+    FT_Fixed      x_scale;
+    FT_Fixed      y_scale;
+    FT_Pos        edge_distance_threshold;
+
+    FT_Int        max_points;
+    FT_Int        num_points;
+    AH_Point*     points;
+
+    FT_Int        max_contours;
+    FT_Int        num_contours;
+    AH_Point**    contours;
+
+    FT_Int        num_hedges;
+    AH_Edge*      horz_edges;
+
+    FT_Int        num_vedges;
+    AH_Edge*      vert_edges;
+
+    FT_Int        num_hsegments;
+    AH_Segment*   horz_segments;
+
+    FT_Int        num_vsegments;
+    AH_Segment*   vert_segments;
+
+  } AH_Outline;
+
+
+#define ah_blue_capital_top     0                              /* THEZOCQS */
+#define ah_blue_capital_bottom  ( ah_blue_capital_top + 1 )    /* HEZLOCUS */
+#define ah_blue_small_top       ( ah_blue_capital_bottom + 1 ) /* xzroesc  */
+#define ah_blue_small_bottom    ( ah_blue_small_top + 1 )      /* xzroesc  */
+#define ah_blue_small_minor     ( ah_blue_small_bottom + 1 )   /* pqgjy    */
+#define ah_blue_max             ( ah_blue_small_minor + 1 )
+
+  typedef FT_Int  AH_Blue;
+
+
+#define ah_hinter_monochrome  1
+#define ah_hinter_optimize    2
+
+  typedef FT_Int  AH_Hinter_Flags;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    AH_Globals                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Holds the global metrics for a given font face (be it in design    */
+  /*    units or scaled pixel values).                                     */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_widths  :: The number of widths.                               */
+  /*                                                                       */
+  /*    num_heights :: The number of heights.                              */
+  /*                                                                       */
+  /*    widths      :: Snap widths, including standard one.                */
+  /*                                                                       */
+  /*    heights     :: Snap height, including standard one.                */
+  /*                                                                       */
+  /*    blue_refs   :: The reference positions of blue zones.              */
+  /*                                                                       */
+  /*    blue_shoots :: The overshoot positions of blue zones.              */
+  /*                                                                       */
+  typedef struct  AH_Globals_
+  {
+    FT_Int    num_widths;
+    FT_Int    num_heights;
+
+    FT_Pos    widths [AH_MAX_WIDTHS];
+    FT_Pos    heights[AH_MAX_HEIGHTS];
+
+    FT_Pos    blue_refs  [ah_blue_max];
+    FT_Pos    blue_shoots[ah_blue_max];
+
+  } AH_Globals;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    AH_Face_Globals                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Holds the complete global metrics for a given font face (i.e., the */
+  /*    design units version + a scaled version + the current scales       */
+  /*    used).                                                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    face    :: A handle to the source face object                      */
+  /*                                                                       */
+  /*    design  :: The globals in font design units.                       */
+  /*                                                                       */
+  /*    scaled  :: Scaled globals in sub-pixel values.                     */
+  /*                                                                       */
+  /*    x_scale :: The current horizontal scale.                           */
+  /*                                                                       */
+  /*    y_scale :: The current vertical scale.                             */
+  /*                                                                       */
+  typedef struct  AH_Face_Globals_
+  {
+    FT_Face     face;
+    AH_Globals  design;
+    AH_Globals  scaled;
+    FT_Fixed    x_scale;
+    FT_Fixed    y_scale;
+    FT_Bool     control_overshoot;
+
+  } AH_Face_Globals;
+
+
+  typedef struct  AH_Hinter
+  {
+    FT_Memory         memory;
+    AH_Hinter_Flags   flags;
+
+    FT_Int            algorithm;
+    FT_Face           face;
+
+    AH_Face_Globals*  globals;
+
+    AH_Outline*       glyph;
+
+    AH_Loader*        loader;
+    FT_Vector         pp1;
+    FT_Vector         pp2;
+
+    FT_Bool           transformed;
+    FT_Vector         trans_delta;
+    FT_Matrix         trans_matrix;
+
+    FT_Bool           disable_horz_edges;
+    FT_Bool           disable_vert_edges;
+  } AH_Hinter;
+
+
+FT_END_HEADER
+
+#endif /* __AHTYPES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cffdrivr.h b/libraries/freetype-2.0.5/include/cffdrivr.h
new file mode 100644 (file)
index 0000000..8fd2247
--- /dev/null
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cffdrivr.h                                                             */
+/*                                                                         */
+/*    High-level OpenType driver interface (specification).                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CFFDRIVER_H__
+#define __CFFDRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_CALLBACK_TABLE
+  const FT_Driver_Class  cff_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __CFFDRIVER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cfferrs.h b/libraries/freetype-2.0.5/include/cfferrs.h
new file mode 100644 (file)
index 0000000..1b2a5c9
--- /dev/null
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cfferrs.h                                                              */
+/*                                                                         */
+/*    CFF error codes (specification only).                                */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the CFF error enumeration constants.      */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __CFFERRS_H__
+#define __CFFERRS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  CFF_Err_
+#define FT_ERR_BASE    FT_Mod_Err_CFF
+
+
+#include FT_ERRORS_H
+
+#endif /* __CFFERRS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cffgload.h b/libraries/freetype-2.0.5/include/cffgload.h
new file mode 100644 (file)
index 0000000..187ed70
--- /dev/null
@@ -0,0 +1,203 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cffgload.h                                                             */
+/*                                                                         */
+/*    OpenType Glyph Loader (specification).                               */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CFFGLOAD_H__
+#define __CFFGLOAD_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "cffobjs.h"
+
+
+FT_BEGIN_HEADER
+
+
+#define CFF_MAX_OPERANDS     48
+#define CFF_MAX_SUBRS_CALLS  32
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Structure>                                                           */
+  /*    CFF_Builder                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*     A structure used during glyph loading to store its outline.       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    memory       :: The current memory object.                         */
+  /*                                                                       */
+  /*    face         :: The current face object.                           */
+  /*                                                                       */
+  /*    glyph        :: The current glyph slot.                            */
+  /*                                                                       */
+  /*    current      :: The current glyph outline.                         */
+  /*                                                                       */
+  /*    base         :: The base glyph outline.                            */
+  /*                                                                       */
+  /*    max_points   :: maximum points in builder outline                  */
+  /*                                                                       */
+  /*    max_contours :: Maximal number of contours in builder outline.     */
+  /*                                                                       */
+  /*    last         :: The last point position.                           */
+  /*                                                                       */
+  /*    scale_x      :: The horizontal scale (FUnits to sub-pixels).       */
+  /*                                                                       */
+  /*    scale_y      :: The vertical scale (FUnits to sub-pixels).         */
+  /*                                                                       */
+  /*    pos_x        :: The horizontal translation (if composite glyph).   */
+  /*                                                                       */
+  /*    pos_y        :: The vertical translation (if composite glyph).     */
+  /*                                                                       */
+  /*    left_bearing :: The left side bearing point.                       */
+  /*                                                                       */
+  /*    advance      :: The horizontal advance vector.                     */
+  /*                                                                       */
+  /*    bbox         :: Unused.                                            */
+  /*                                                                       */
+  /*    path_begun   :: A flag which indicates that a new path has begun.  */
+  /*                                                                       */
+  /*    load_points  :: If this flag is not set, no points are loaded.     */
+  /*                                                                       */
+  /*    no_recurse   :: Set but not used.                                  */
+  /*                                                                       */
+  /*    error        :: An error code that is only used to report memory   */
+  /*                    allocation problems.                               */
+  /*                                                                       */
+  /*    metrics_only :: A boolean indicating that we only want to compute  */
+  /*                    the metrics of a given glyph, not load all of its  */
+  /*                    points.                                            */
+  /*                                                                       */
+  typedef struct  CFF_Builder_
+  {
+    FT_Memory         memory;
+    TT_Face           face;
+    CFF_GlyphSlot     glyph;
+    FT_GlyphLoader*   loader;
+    FT_Outline*       base;
+    FT_Outline*       current;
+
+    FT_Vector         last;
+
+    FT_Fixed          scale_x;
+    FT_Fixed          scale_y;
+
+    FT_Pos            pos_x;
+    FT_Pos            pos_y;
+
+    FT_Vector         left_bearing;
+    FT_Vector         advance;
+
+    FT_BBox           bbox;          /* bounding box */
+    FT_Bool           path_begun;
+    FT_Bool           load_points;
+    FT_Bool           no_recurse;
+
+    FT_Error          error;         /* only used for memory errors */
+    FT_Bool           metrics_only;
+
+  } CFF_Builder;
+
+
+  /* execution context charstring zone */
+
+  typedef struct  CFF_Decoder_Zone_
+  {
+    FT_Byte*  base;
+    FT_Byte*  limit;
+    FT_Byte*  cursor;
+
+  } CFF_Decoder_Zone;
+
+
+  typedef struct  CFF_Decoder_
+  {
+    CFF_Builder        builder;
+    CFF_Font*          cff;
+
+    FT_Fixed           stack[CFF_MAX_OPERANDS + 1];
+    FT_Fixed*          top;
+
+    CFF_Decoder_Zone   zones[CFF_MAX_SUBRS_CALLS + 1];
+    CFF_Decoder_Zone*  zone;
+
+    FT_Int             flex_state;
+    FT_Int             num_flex_vectors;
+    FT_Vector          flex_vectors[7];
+
+    FT_Pos             glyph_width;
+    FT_Pos             nominal_width;
+
+    FT_Bool            read_width;
+    FT_Int             num_hints;
+    FT_Fixed*          buildchar;
+    FT_Int             len_buildchar;
+
+    FT_UInt            num_locals;
+    FT_UInt            num_globals;
+
+    FT_Int             locals_bias;
+    FT_Int             globals_bias;
+
+    FT_Byte**          locals;
+    FT_Byte**          globals;
+
+    FT_Byte**          glyph_names;   /* for pure CFF fonts only  */
+    FT_UInt            num_glyphs;    /* number of glyphs in font */
+
+  } CFF_Decoder;
+
+
+  FT_LOCAL void
+  CFF_Init_Decoder( CFF_Decoder*   decoder,
+                    TT_Face        face,
+                    CFF_Size       size,
+                    CFF_GlyphSlot  slot );
+
+  FT_LOCAL void
+  CFF_Prepare_Decoder( CFF_Decoder*  decoder,
+                       FT_UInt       glyph_index );
+
+#if 0  /* unused until we support pure CFF fonts */
+
+  /* Compute the maximum advance width of a font through quick parsing */
+  FT_LOCAL FT_Error
+  CFF_Compute_Max_Advance( TT_Face  face,
+                           FT_Int*  max_advance );
+
+#endif /* 0 */
+
+  FT_LOCAL FT_Error
+  CFF_Parse_CharStrings( CFF_Decoder*  decoder,
+                         FT_Byte*      charstring_base,
+                         FT_Int        charstring_len );
+
+  FT_LOCAL FT_Error
+  CFF_Load_Glyph( CFF_GlyphSlot  glyph,
+                  CFF_Size       size,
+                  FT_Int         glyph_index,
+                  FT_Int         load_flags );
+
+
+FT_END_HEADER
+
+#endif /* __CFFGLOAD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cffload.h b/libraries/freetype-2.0.5/include/cffload.h
new file mode 100644 (file)
index 0000000..967229d
--- /dev/null
@@ -0,0 +1,1085 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cffload.h                                                              */
+/*                                                                         */
+/*    OpenType & CFF data/program tables loader (specification).           */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CFFLOAD_H__
+#define __CFFLOAD_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_CFF_TYPES_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+
+
+FT_BEGIN_HEADER
+
+  const FT_UShort  cff_isoadobe_charset[229] =
+  {
+    0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11,
+    12,
+    13,
+    14,
+    15,
+    16,
+    17,
+    18,
+    19,
+    20,
+    21,
+    22,
+    23,
+    24,
+    25,
+    26,
+    27,
+    28,
+    29,
+    30,
+    31,
+    32,
+    33,
+    34,
+    35,
+    36,
+    37,
+    38,
+    39,
+    40,
+    41,
+    42,
+    43,
+    44,
+    45,
+    46,
+    47,
+    48,
+    49,
+    50,
+    51,
+    52,
+    53,
+    54,
+    55,
+    56,
+    57,
+    58,
+    59,
+    60,
+    61,
+    62,
+    63,
+    64,
+    65,
+    66,
+    67,
+    68,
+    69,
+    70,
+    71,
+    72,
+    73,
+    74,
+    75,
+    76,
+    77,
+    78,
+    79,
+    80,
+    81,
+    82,
+    83,
+    84,
+    85,
+    86,
+    87,
+    88,
+    89,
+    90,
+    91,
+    92,
+    93,
+    94,
+    95,
+    96,
+    97,
+    98,
+    99,
+    100,
+    101,
+    102,
+    103,
+    104,
+    105,
+    106,
+    107,
+    108,
+    109,
+    110,
+    111,
+    112,
+    113,
+    114,
+    115,
+    116,
+    117,
+    118,
+    119,
+    120,
+    121,
+    122,
+    123,
+    124,
+    125,
+    126,
+    127,
+    128,
+    129,
+    130,
+    131,
+    132,
+    133,
+    134,
+    135,
+    136,
+    137,
+    138,
+    139,
+    140,
+    141,
+    142,
+    143,
+    144,
+    145,
+    146,
+    147,
+    148,
+    149,
+    150,
+    151,
+    152,
+    153,
+    154,
+    155,
+    156,
+    157,
+    158,
+    159,
+    160,
+    161,
+    162,
+    163,
+    164,
+    165,
+    166,
+    167,
+    168,
+    169,
+    170,
+    171,
+    172,
+    173,
+    174,
+    175,
+    176,
+    177,
+    178,
+    179,
+    180,
+    181,
+    182,
+    183,
+    184,
+    185,
+    186,
+    187,
+    188,
+    189,
+    190,
+    191,
+    192,
+    193,
+    194,
+    195,
+    196,
+    197,
+    198,
+    199,
+    200,
+    201,
+    202,
+    203,
+    204,
+    205,
+    206,
+    207,
+    208,
+    209,
+    210,
+    211,
+    212,
+    213,
+    214,
+    215,
+    216,
+    217,
+    218,
+    219,
+    220,
+    221,
+    222,
+    223,
+    224,
+    225,
+    226,
+    227,
+    228
+  };
+
+  const FT_UShort  cff_expert_charset[166] =
+  {
+    0,
+    1,
+    229,
+    230,
+    231,
+    232,
+    233,
+    234,
+    235,
+    236,
+    237,
+    238,
+    13,
+    14,
+    15,
+    99,
+    239,
+    240,
+    241,
+    242,
+    243,
+    244,
+    245,
+    246,
+    247,
+    248,
+    27,
+    28,
+    249,
+    250,
+    251,
+    252,
+    253,
+    254,
+    255,
+    256,
+    257,
+    258,
+    259,
+    260,
+    261,
+    262,
+    263,
+    264,
+    265,
+    266,
+    109,
+    110,
+    267,
+    268,
+    269,
+    270,
+    271,
+    272,
+    273,
+    274,
+    275,
+    276,
+    277,
+    278,
+    279,
+    280,
+    281,
+    282,
+    283,
+    284,
+    285,
+    286,
+    287,
+    288,
+    289,
+    290,
+    291,
+    292,
+    293,
+    294,
+    295,
+    296,
+    297,
+    298,
+    299,
+    300,
+    301,
+    302,
+    303,
+    304,
+    305,
+    306,
+    307,
+    308,
+    309,
+    310,
+    311,
+    312,
+    313,
+    314,
+    315,
+    316,
+    317,
+    318,
+    158,
+    155,
+    163,
+    319,
+    320,
+    321,
+    322,
+    323,
+    324,
+    325,
+    326,
+    150,
+    164,
+    169,
+    327,
+    328,
+    329,
+    330,
+    331,
+    332,
+    333,
+    334,
+    335,
+    336,
+    337,
+    338,
+    339,
+    340,
+    341,
+    342,
+    343,
+    344,
+    345,
+    346,
+    347,
+    348,
+    349,
+    350,
+    351,
+    352,
+    353,
+    354,
+    355,
+    356,
+    357,
+    358,
+    359,
+    360,
+    361,
+    362,
+    363,
+    364,
+    365,
+    366,
+    367,
+    368,
+    369,
+    370,
+    371,
+    372,
+    373,
+    374,
+    375,
+    376,
+    377,
+    378
+  };
+
+  const FT_UShort  cff_expertsubset_charset[87] =
+  {
+    0,
+    1,
+    231,
+    232,
+    235,
+    236,
+    237,
+    238,
+    13,
+    14,
+    15,
+    99,
+    239,
+    240,
+    241,
+    242,
+    243,
+    244,
+    245,
+    246,
+    247,
+    248,
+    27,
+    28,
+    249,
+    250,
+    251,
+    253,
+    254,
+    255,
+    256,
+    257,
+    258,
+    259,
+    260,
+    261,
+    262,
+    263,
+    264,
+    265,
+    266,
+    109,
+    110,
+    267,
+    268,
+    269,
+    270,
+    272,
+    300,
+    301,
+    302,
+    305,
+    314,
+    315,
+    158,
+    155,
+    163,
+    320,
+    321,
+    322,
+    323,
+    324,
+    325,
+    326,
+    150,
+    164,
+    169,
+    327,
+    328,
+    329,
+    330,
+    331,
+    332,
+    333,
+    334,
+    335,
+    336,
+    337,
+    338,
+    339,
+    340,
+    341,
+    342,
+    343,
+    344,
+    345,
+    346
+  };
+
+  const FT_UShort  cff_standard_encoding[256] =
+  {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11,
+    12,
+    13,
+    14,
+    15,
+    16,
+    17,
+    18,
+    19,
+    20,
+    21,
+    22,
+    23,
+    24,
+    25,
+    26,
+    27,
+    28,
+    29,
+    30,
+    31,
+    32,
+    33,
+    34,
+    35,
+    36,
+    37,
+    38,
+    39,
+    40,
+    41,
+    42,
+    43,
+    44,
+    45,
+    46,
+    47,
+    48,
+    49,
+    50,
+    51,
+    52,
+    53,
+    54,
+    55,
+    56,
+    57,
+    58,
+    59,
+    60,
+    61,
+    62,
+    63,
+    64,
+    65,
+    66,
+    67,
+    68,
+    69,
+    70,
+    71,
+    72,
+    73,
+    74,
+    75,
+    76,
+    77,
+    78,
+    79,
+    80,
+    81,
+    82,
+    83,
+    84,
+    85,
+    86,
+    87,
+    88,
+    89,
+    90,
+    91,
+    92,
+    93,
+    94,
+    95,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    96,
+    97,
+    98,
+    99,
+    100,
+    101,
+    102,
+    103,
+    104,
+    105,
+    106,
+    107,
+    108,
+    109,
+    110,
+    0,
+    111,
+    112,
+    113,
+    114,
+    0,
+    115,
+    116,
+    117,
+    118,
+    119,
+    120,
+    121,
+    122,
+    0,
+    123,
+    0,
+    124,
+    125,
+    126,
+    127,
+    128,
+    129,
+    130,
+    131,
+    0,
+    132,
+    133,
+    0,
+    134,
+    135,
+    136,
+    137,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    138,
+    0,
+    139,
+    0,
+    0,
+    0,
+    0,
+    140,
+    141,
+    142,
+    143,
+    0,
+    0,
+    0,
+    0,
+    0,
+    144,
+    0,
+    0,
+    0,
+    145,
+    0,
+    0,
+    146,
+    147,
+    148,
+    149,
+    0,
+    0,
+    0,
+    0
+  };
+
+  const FT_UShort  cff_expert_encoding[256] =
+  {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    1,
+    229,
+    230,
+    0,
+    231,
+    232,
+    233,
+    234,
+    235,
+    236,
+    237,
+    238,
+    13,
+    14,
+    15,
+    99,
+    239,
+    240,
+    241,
+    242,
+    243,
+    244,
+    245,
+    246,
+    247,
+    248,
+    27,
+    28,
+    249,
+    250,
+    251,
+    252,
+    0,
+    253,
+    254,
+    255,
+    256,
+    257,
+    0,
+    0,
+    0,
+    258,
+    0,
+    0,
+    259,
+    260,
+    261,
+    262,
+    0,
+    0,
+    263,
+    264,
+    265,
+    0,
+    266,
+    109,
+    110,
+    267,
+    268,
+    269,
+    0,
+    270,
+    271,
+    272,
+    273,
+    274,
+    275,
+    276,
+    277,
+    278,
+    279,
+    280,
+    281,
+    282,
+    283,
+    284,
+    285,
+    286,
+    287,
+    288,
+    289,
+    290,
+    291,
+    292,
+    293,
+    294,
+    295,
+    296,
+    297,
+    298,
+    299,
+    300,
+    301,
+    302,
+    303,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    304,
+    305,
+    306,
+    0,
+    0,
+    307,
+    308,
+    309,
+    310,
+    311,
+    0,
+    312,
+    0,
+    0,
+    312,
+    0,
+    0,
+    314,
+    315,
+    0,
+    0,
+    316,
+    317,
+    318,
+    0,
+    0,
+    0,
+    158,
+    155,
+    163,
+    319,
+    320,
+    321,
+    322,
+    323,
+    324,
+    325,
+    0,
+    0,
+    326,
+    150,
+    164,
+    169,
+    327,
+    328,
+    329,
+    330,
+    331,
+    332,
+    333,
+    334,
+    335,
+    336,
+    337,
+    338,
+    339,
+    340,
+    341,
+    342,
+    343,
+    344,
+    345,
+    346,
+    347,
+    348,
+    349,
+    350,
+    351,
+    352,
+    353,
+    354,
+    355,
+    356,
+    357,
+    358,
+    359,
+    360,
+    361,
+    362,
+    363,
+    364,
+    365,
+    366,
+    367,
+    368,
+    369,
+    370,
+    371,
+    372,
+    373,
+    374,
+    375,
+    376,
+    377,
+    378
+  };
+
+
+  FT_LOCAL FT_String*
+  CFF_Get_Name( CFF_Index*  index,
+                FT_UInt     element );
+
+  FT_LOCAL FT_String*
+  CFF_Get_String( CFF_Index*          index,
+                  FT_UInt             sid,
+                  PSNames_Interface*  interface );
+
+
+  FT_LOCAL FT_Error
+  CFF_Access_Element( CFF_Index*  index,
+                      FT_UInt     element,
+                      FT_Byte**   pbytes,
+                      FT_ULong*   pbyte_len );
+
+  FT_LOCAL void
+  CFF_Forget_Element( CFF_Index*  index,
+                      FT_Byte**   pbytes );
+
+
+  FT_LOCAL FT_Error
+  CFF_Load_Font( FT_Stream  stream,
+                 FT_Int     face_index,
+                 CFF_Font*  font );
+
+  FT_LOCAL void
+  CFF_Done_Font( CFF_Font*  font );
+
+
+  FT_LOCAL FT_Byte
+  CFF_Get_FD( CFF_FD_Select*  select,
+              FT_UInt         glyph_index );
+
+
+FT_END_HEADER
+
+#endif /* __CFFLOAD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cffobjs.h b/libraries/freetype-2.0.5/include/cffobjs.h
new file mode 100644 (file)
index 0000000..10b2e61
--- /dev/null
@@ -0,0 +1,143 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cffobjs.h                                                              */
+/*                                                                         */
+/*    OpenType objects manager (specification).                            */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CFFOBJS_H__
+#define __CFFOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_CFF_TYPES_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CFF_Driver                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an OpenType driver object.                             */
+  /*                                                                       */
+  typedef struct CFF_DriverRec_*  CFF_Driver;
+
+  typedef TT_Face  CFF_Face;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CFF_Size                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an OpenType size object.                               */
+  /*                                                                       */
+  typedef FT_Size  CFF_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CFF_GlyphSlot                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an OpenType glyph slot object.                         */
+  /*                                                                       */
+  typedef struct  CFF_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+
+    FT_Bool          hint;
+    FT_Bool          scaled;
+
+    FT_Fixed         x_scale;
+    FT_Fixed         y_scale;
+
+  } CFF_GlyphSlotRec, *CFF_GlyphSlot;
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Subglyph transformation record.                                       */
+  /*                                                                       */
+  typedef struct  CFF_Transform_
+  {
+    FT_Fixed    xx, xy;     /* transformation matrix coefficients */
+    FT_Fixed    yx, yy;
+    FT_F26Dot6  ox, oy;     /* offsets        */
+
+  } CFF_Transform;
+
+
+  /* this is only used in the case of a pure CFF font with no charmap */
+  typedef struct  CFF_CharMapRec_
+  {
+    TT_CharMapRec  root;
+    PS_Unicodes    unicodes;
+
+  } CFF_CharMapRec, *CFF_CharMap;
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /* TrueType driver class.                                              */
+  /*                                                                     */
+  typedef struct  CFF_DriverRec_
+  {
+    FT_DriverRec  root;
+    void*         extension_component;
+
+  } CFF_DriverRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Face functions                                                        */
+  /*                                                                       */
+  FT_LOCAL FT_Error
+  CFF_Init_Face( FT_Stream      stream,
+                 CFF_Face       face,
+                 FT_Int         face_index,
+                 FT_Int         num_params,
+                 FT_Parameter*  params );
+
+  FT_LOCAL void
+  CFF_Done_Face( CFF_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Driver functions                                                      */
+  /*                                                                       */
+  FT_LOCAL FT_Error
+  CFF_Init_Driver( CFF_Driver  driver );
+
+  FT_LOCAL void
+  CFF_Done_Driver( CFF_Driver  driver );
+
+
+FT_END_HEADER
+
+#endif /* __CFFOBJS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cffparse.h b/libraries/freetype-2.0.5/include/cffparse.h
new file mode 100644 (file)
index 0000000..c40b198
--- /dev/null
@@ -0,0 +1,69 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cffparse.h                                                             */
+/*                                                                         */
+/*    CFF token stream parser (specification)                              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CFF_PARSE_H__
+#define __CFF_PARSE_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_CFF_TYPES_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+#define CFF_MAX_STACK_DEPTH  96
+
+#define CFF_CODE_TOPDICT  0x1000
+#define CFF_CODE_PRIVATE  0x2000
+
+
+  typedef struct  CFF_Parser_
+  {
+    FT_Byte*   start;
+    FT_Byte*   limit;
+    FT_Byte*   cursor;
+
+    FT_Byte*   stack[CFF_MAX_STACK_DEPTH + 1];
+    FT_Byte**  top;
+
+    FT_UInt    object_code;
+    void*      object;
+
+  } CFF_Parser;
+
+
+  FT_LOCAL void
+  CFF_Parser_Init( CFF_Parser*  parser,
+                   FT_UInt      code,
+                   void*        object );
+
+  FT_LOCAL FT_Error
+  CFF_Parser_Run( CFF_Parser*  parser,
+                  FT_Byte*     start,
+                  FT_Byte*     limit );
+
+
+FT_END_HEADER
+
+
+#endif /* __CFF_PARSE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cfftoken.h b/libraries/freetype-2.0.5/include/cfftoken.h
new file mode 100644 (file)
index 0000000..e58cef3
--- /dev/null
@@ -0,0 +1,97 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cfftoken.h                                                             */
+/*                                                                         */
+/*    CFF token definitions                                                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  CFF_Font_Dict
+
+#undef  CFFCODE
+#define CFFCODE        CFFCODE_TOPDICT
+
+  CFF_FIELD_STRING  ( 0,     version )
+  CFF_FIELD_STRING  ( 1,     notice )
+  CFF_FIELD_STRING  ( 0x100, copyright )
+  CFF_FIELD_STRING  ( 2,     full_name )
+  CFF_FIELD_STRING  ( 3,     family_name )
+  CFF_FIELD_STRING  ( 4,     weight )
+  CFF_FIELD_BOOL    ( 0x101, is_fixed_pitch )
+  CFF_FIELD_FIXED   ( 0x102, italic_angle )
+  CFF_FIELD_NUM     ( 0x103, underline_position )
+  CFF_FIELD_NUM     ( 0x104, underline_thickness )
+  CFF_FIELD_NUM     ( 0x105, paint_type )
+  CFF_FIELD_NUM     ( 0x106, charstring_type )
+  CFF_FIELD_CALLBACK( 0x107, font_matrix )
+  CFF_FIELD_NUM     ( 13,    unique_id )
+  CFF_FIELD_CALLBACK( 5,     font_bbox )
+  CFF_FIELD_NUM     ( 0x108, stroke_width )
+  CFF_FIELD_NUM     ( 15,    charset_offset )
+  CFF_FIELD_NUM     ( 16,    encoding_offset )
+  CFF_FIELD_NUM     ( 17,    charstrings_offset )
+  CFF_FIELD_CALLBACK( 18,    private_dict )
+  CFF_FIELD_NUM     ( 0x114, synthetic_base )
+  CFF_FIELD_STRING  ( 0x115, postscript )
+  CFF_FIELD_STRING  ( 0x116, base_font_name )
+
+#if 0
+  CFF_FIELD_DELTA   ( 0x117, base_font_blend, 16 )
+  CFF_FIELD_CALLBACK( 0x118, multiple_master )
+  CFF_FIELD_CALLBACK( 0x119, blend_axit_types )
+#endif
+
+  CFF_FIELD_CALLBACK( 0x11E, cid_ros )
+  CFF_FIELD_NUM     ( 0x11F, cid_font_version )
+  CFF_FIELD_NUM     ( 0x120, cid_font_revision )
+  CFF_FIELD_NUM     ( 0x121, cid_font_type )
+  CFF_FIELD_NUM     ( 0x122, cid_count )
+  CFF_FIELD_NUM     ( 0x123, cid_uid_base )
+  CFF_FIELD_NUM     ( 0x124, cid_fd_array_offset )
+  CFF_FIELD_NUM     ( 0x125, cid_fd_select_offset )
+  CFF_FIELD_STRING  ( 0x126, cid_font_name )
+
+#if 0
+  CFF_FIELD_NUM     ( 0x127, chameleon )
+#endif
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  CFF_Private
+#undef  CFFCODE
+#define CFFCODE       CFFCODE_PRIVATE
+
+  CFF_FIELD_DELTA( 6,     blue_values, 14 )
+  CFF_FIELD_DELTA( 7,     other_blues, 10 )
+  CFF_FIELD_DELTA( 8,     family_blues, 14 )
+  CFF_FIELD_DELTA( 9,     family_other_blues, 10 )
+  CFF_FIELD_FIXED( 0x109, blue_scale )
+  CFF_FIELD_NUM  ( 0x10A, blue_shift )
+  CFF_FIELD_NUM  ( 0x10B, blue_fuzz )
+  CFF_FIELD_NUM  ( 10,    standard_width )
+  CFF_FIELD_NUM  ( 11,    standard_height )
+  CFF_FIELD_DELTA( 0x10C, snap_widths, 13 )
+  CFF_FIELD_DELTA( 0x10D, snap_heights, 13 )
+  CFF_FIELD_BOOL ( 0x10E, force_bold )
+  CFF_FIELD_FIXED( 0x10F, force_bold_threshold )
+  CFF_FIELD_NUM  ( 0x110, lenIV )
+  CFF_FIELD_NUM  ( 0x111, language_group )
+  CFF_FIELD_FIXED( 0x112, expansion_factor )
+  CFF_FIELD_NUM  ( 0x113, initial_random_seed )
+  CFF_FIELD_NUM  ( 19,    local_subrs_offset )
+  CFF_FIELD_NUM  ( 20,    default_width )
+  CFF_FIELD_NUM  ( 21,    nominal_width )
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ciderrs.h b/libraries/freetype-2.0.5/include/ciderrs.h
new file mode 100644 (file)
index 0000000..01813e1
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ciderrs.h                                                              */
+/*                                                                         */
+/*    CID error codes (specification only).                                */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the CID error enumeration constants.      */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __CIDERRS_H__
+#define __CIDERRS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  CID_Err_
+#define FT_ERR_BASE    FT_Mod_Err_CID
+
+#include FT_ERRORS_H
+
+#endif /* __CIDERRS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cidgload.h b/libraries/freetype-2.0.5/include/cidgload.h
new file mode 100644 (file)
index 0000000..bfab081
--- /dev/null
@@ -0,0 +1,51 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidgload.h                                                             */
+/*                                                                         */
+/*    OpenType Glyph Loader (specification).                               */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CIDGLOAD_H__
+#define __CIDGLOAD_H__
+
+
+#include <ft2build.h>
+#include "cidobjs.h"
+
+
+FT_BEGIN_HEADER
+
+
+#if 0
+
+  /* Compute the maximum advance width of a font through quick parsing */
+  FT_LOCAL FT_Error
+  CID_Compute_Max_Advance( CID_Face  face,
+                           FT_Int*   max_advance );
+
+#endif /* 0 */
+
+  FT_LOCAL FT_Error
+  CID_Load_Glyph( CID_GlyphSlot  glyph,
+                  CID_Size       size,
+                  FT_Int         glyph_index,
+                  FT_Int         load_flags );
+
+
+FT_END_HEADER
+
+#endif /* __CIDGLOAD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cidload.h b/libraries/freetype-2.0.5/include/cidload.h
new file mode 100644 (file)
index 0000000..0b70657
--- /dev/null
@@ -0,0 +1,57 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidload.h                                                              */
+/*                                                                         */
+/*    CID-keyed Type1 font loader (specification).                         */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CIDLOAD_H__
+#define __CIDLOAD_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include "cidparse.h"
+
+
+FT_BEGIN_HEADER
+
+
+  typedef struct  CID_Loader_
+  {
+    CID_Parser  parser;          /* parser used to read the stream */
+    FT_Int      num_chars;       /* number of characters in encoding */
+
+  } CID_Loader;
+
+
+  FT_LOCAL FT_Long
+  cid_get_offset( FT_Byte**  start,
+                  FT_Byte    offsize );
+
+  FT_LOCAL void
+  cid_decrypt( FT_Byte*   buffer,
+               FT_Offset  length,
+               FT_UShort  seed );
+
+  FT_LOCAL FT_Error
+  CID_Open_Face( CID_Face  face );
+
+
+FT_END_HEADER
+
+#endif /* __CIDLOAD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cidobjs.h b/libraries/freetype-2.0.5/include/cidobjs.h
new file mode 100644 (file)
index 0000000..8330663
--- /dev/null
@@ -0,0 +1,137 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidobjs.h                                                              */
+/*                                                                         */
+/*    CID objects manager (specification).                                 */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CIDOBJS_H__
+#define __CIDOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  /* The following structures must be defined by the hinter */
+  typedef struct CID_Size_Hints_   CID_Size_Hints;
+  typedef struct CID_Glyph_Hints_  CID_Glyph_Hints;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CID_Driver                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 driver object.                                */
+  /*                                                                       */
+  typedef struct CID_DriverRec_*  CID_Driver;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CID_Size                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 size object.                                  */
+  /*                                                                       */
+  typedef struct CID_SizeRec_*  CID_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CID_GlyphSlot                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 glyph slot object.                            */
+  /*                                                                       */
+  typedef struct CID_GlyphSlotRec_*  CID_GlyphSlot;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    CID_CharMap                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 character mapping object.                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The Type 1 format doesn't use a charmap but an encoding table.     */
+  /*    The driver is responsible for making up charmap objects            */
+  /*    corresponding to these tables.                                     */
+  /*                                                                       */
+  typedef struct CID_CharMapRec_*  CID_CharMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* HERE BEGINS THE TYPE 1 SPECIFIC STUFF                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  typedef struct  CID_SizeRec_
+  {
+    FT_SizeRec  root;
+    FT_Bool     valid;
+
+  } CID_SizeRec;
+
+
+  typedef struct  CID_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+
+    FT_Bool          hint;
+    FT_Bool          scaled;
+
+    FT_Fixed         x_scale;
+    FT_Fixed         y_scale;
+
+  } CID_GlyphSlotRec;
+
+
+  FT_LOCAL FT_Error
+  CID_Init_Face( FT_Stream      stream,
+                 CID_Face       face,
+                 FT_Int         face_index,
+                 FT_Int         num_params,
+                 FT_Parameter*  params );
+
+  FT_LOCAL void
+  CID_Done_Face( CID_Face  face );
+
+
+  FT_LOCAL FT_Error
+  CID_Init_Driver( CID_Driver  driver );
+
+  FT_LOCAL void
+  CID_Done_Driver( CID_Driver  driver );
+
+
+FT_END_HEADER
+
+#endif /* __CIDOBJS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cidparse.h b/libraries/freetype-2.0.5/include/cidparse.h
new file mode 100644 (file)
index 0000000..a2bd1fa
--- /dev/null
@@ -0,0 +1,116 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidparse.h                                                             */
+/*                                                                         */
+/*    CID-keyed Type1 parser (specification).                              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CIDPARSE_H__
+#define __CIDPARSE_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_TYPE1_TYPES_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    CID_Parser                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A CID_Parser is an object used to parse a Type 1 fonts very        */
+  /*    quickly.                                                           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root           :: the root T1_Parser fields                        */
+  /*                                                                       */
+  /*    stream         :: The current input stream.                        */
+  /*                                                                       */
+  /*    postscript     :: A pointer to the data to be parsed.              */
+  /*                                                                       */
+  /*    postscript_len :: The length of the data to be parsed.             */
+  /*                                                                       */
+  /*    data_offset    :: The start position of the binary data (i.e., the */
+  /*                      end of the data to be parsed.                    */
+  /*                                                                       */
+  /*    cid            :: A structure which holds the information about    */
+  /*                      the current font.                                */
+  /*                                                                       */
+  /*    num_dict       :: The number of font dictionaries.                 */
+  /*                                                                       */
+  typedef struct  CID_Parser_
+  {
+    T1_Parser  root;
+    FT_Stream  stream;
+
+    FT_Byte*   postscript;
+    FT_Int     postscript_len;
+
+    FT_ULong   data_offset;
+
+    CID_Info*  cid;
+    FT_Int     num_dict;
+
+  } CID_Parser;
+
+
+  FT_LOCAL FT_Error
+  CID_New_Parser( CID_Parser*       parser,
+                  FT_Stream         stream,
+                  FT_Memory         memory,
+                  PSAux_Interface*  psaux );
+
+  FT_LOCAL void
+  CID_Done_Parser( CID_Parser*  parser );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                            PARSING ROUTINES                           */
+  /*                                                                       */
+  /*************************************************************************/
+
+#define CID_Skip_Spaces( p )  (p)->root.funcs.skip_spaces( &(p)->root )
+#define CID_Skip_Alpha( p )   (p)->root.funcs.skip_alpha ( &(p)->root )
+
+#define CID_ToInt( p )       (p)->root.funcs.to_int( &(p)->root )
+#define CID_ToFixed( p, t )  (p)->root.funcs.to_fixed( &(p)->root, t )
+
+#define CID_ToCoordArray( p, m, c )    \
+          (p)->root.funcs.to_coord_array( &(p)->root, m, c )
+#define CID_ToFixedArray( p, m, f, t ) \
+          (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
+#define CID_ToToken( p, t )            \
+          (p)->root.funcs.to_token( &(p)->root, t )
+#define CID_ToTokenArray( p, t, m, c ) \
+          (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
+
+#define CID_Load_Field( p, f, o )       \
+          (p)->root.funcs.load_field( &(p)->root, f, o, 0, 0 )
+#define CID_Load_Field_Table( p, f, o ) \
+          (p)->root.funcs.load_field_table( &(p)->root, f, o, 0, 0 )
+
+
+FT_END_HEADER
+
+#endif /* __CIDPARSE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cidriver.h b/libraries/freetype-2.0.5/include/cidriver.h
new file mode 100644 (file)
index 0000000..33e8481
--- /dev/null
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidriver.h                                                             */
+/*                                                                         */
+/*    High-level CID driver interface (specification).                     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CIDRIVER_H__
+#define __CIDRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_CALLBACK_TABLE
+  const  FT_Driver_Class  t1cid_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __CIDRIVER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/cidtoken.h b/libraries/freetype-2.0.5/include/cidtoken.h
new file mode 100644 (file)
index 0000000..487355d
--- /dev/null
@@ -0,0 +1,96 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cidtoken.h                                                             */
+/*                                                                         */
+/*    CID token definitions (specification only).                          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  CID_Info
+#undef  T1CODE
+#define T1CODE        t1_field_cid_info
+
+  T1_FIELD_STRING( "CIDFontName", cid_font_name )
+  T1_FIELD_NUM   ( "CIDFontVersion", cid_version )
+  T1_FIELD_NUM   ( "CIDFontType", cid_font_type )
+  T1_FIELD_STRING( "Registry", registry )
+  T1_FIELD_STRING( "Ordering", ordering )
+  T1_FIELD_NUM   ( "Supplement", supplement )
+  T1_FIELD_NUM   ( "UIDBase", uid_base )
+  T1_FIELD_NUM   ( "CIDMapOffset", cidmap_offset )
+  T1_FIELD_NUM   ( "FDBytes", fd_bytes )
+  T1_FIELD_NUM   ( "GDBytes", gd_bytes )
+  T1_FIELD_NUM   ( "CIDCount", cid_count )
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  T1_FontInfo
+#undef  T1CODE
+#define T1CODE        t1_field_font_info
+
+  T1_FIELD_STRING( "version", version )
+  T1_FIELD_STRING( "Notice", notice )
+  T1_FIELD_STRING( "FullName", full_name )
+  T1_FIELD_STRING( "FamilyName", family_name )
+  T1_FIELD_STRING( "Weight", weight )
+  T1_FIELD_FIXED ( "ItalicAngle", italic_angle )
+  T1_FIELD_BOOL  ( "isFixedPitch", is_fixed_pitch )
+  T1_FIELD_NUM   ( "UnderlinePosition", underline_position )
+  T1_FIELD_NUM   ( "UnderlineThickness", underline_thickness )
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  CID_FontDict
+#undef  T1CODE
+#define T1CODE        t1_field_font_dict
+
+  T1_FIELD_NUM  ( "PaintType", paint_type )
+  T1_FIELD_NUM  ( "FontType", font_type )
+  T1_FIELD_NUM  ( "SubrMapOffset", subrmap_offset )
+  T1_FIELD_NUM  ( "SDBytes", sd_bytes )
+  T1_FIELD_NUM  ( "SubrCount", num_subrs )
+  T1_FIELD_NUM  ( "lenBuildCharArray", len_buildchar )
+  T1_FIELD_FIXED( "ForceBoldThreshold", forcebold_threshold )
+  T1_FIELD_FIXED( "ExpansionFactor", expansion_factor )
+  T1_FIELD_NUM  ( "StrokeWidth", stroke_width )
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  T1_Private
+#undef  T1CODE
+#define T1CODE        t1_field_private
+
+  T1_FIELD_NUM       ( "UniqueID", unique_id )
+  T1_FIELD_NUM       ( "lenIV", lenIV )
+  T1_FIELD_NUM       ( "LanguageGroup", language_group )
+  T1_FIELD_NUM       ( "password", password )
+
+  T1_FIELD_FIXED     ( "BlueScale", blue_scale )
+  T1_FIELD_NUM       ( "BlueShift", blue_shift )
+  T1_FIELD_NUM       ( "BlueFuzz",  blue_fuzz )
+
+  T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 )
+  T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 )
+  T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 )
+  T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 )
+
+  T1_FIELD_NUM_TABLE2( "StdHW", standard_width,  1 )
+  T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 )
+  T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 )
+
+  T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 )
+  T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 )
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/fnterrs.h b/libraries/freetype-2.0.5/include/fnterrs.h
new file mode 100644 (file)
index 0000000..ea80909
--- /dev/null
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fnterrs.h                                                              */
+/*                                                                         */
+/*    Win FNT/FON error codes (specification only).                        */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the Windows FNT/FON error enumeration     */
+  /* constants.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __FNTERRS_H__
+#define __FNTERRS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  FNT_Err_
+#define FT_ERR_BASE    FT_Mod_Err_Winfonts
+
+#include FT_ERRORS_H
+
+#endif /* __FNTERRS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/Makefile.am b/libraries/freetype-2.0.5/include/freetype/Makefile.am
new file mode 100644 (file)
index 0000000..4e67f6a
--- /dev/null
@@ -0,0 +1,6 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_HEADERS = \
+ freetype.h    ftchapters.h  ftimage.h     ftmm.h        ftoutln.h     ftsnames.h    fttrigon.h    ttnameid.h    \
+ ftbbox.h      fterrors.h    ftlist.h      ftmoderr.h    ftrender.h    ftsynth.h     fttypes.h     tttables.h    \
+ ftcache.h     ftglyph.h     ftmac.h       ftmodule.h    ftsizes.h     ftsystem.h    t1tables.h    tttags.h      
diff --git a/libraries/freetype-2.0.5/include/freetype/cache/Makefile.am b/libraries/freetype-2.0.5/include/freetype/cache/Makefile.am
new file mode 100644 (file)
index 0000000..98cd2aa
--- /dev/null
@@ -0,0 +1,3 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_HEADERS = ftcchunk.h  ftcglyph.h  ftcimage.h  ftcmanag.h  ftcsbits.h  ftlru.h     
diff --git a/libraries/freetype-2.0.5/include/freetype/cache/ftcchunk.h b/libraries/freetype-2.0.5/include/freetype/cache/ftcchunk.h
new file mode 100644 (file)
index 0000000..47fed6e
--- /dev/null
@@ -0,0 +1,228 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcchunk.h                                                             */
+/*                                                                         */
+/*    FreeType chunk cache (specification).                                */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Important: The functions defined in this file are only used to        */
+  /*            implement an abstract chunk cache class.  You need to      */
+  /*            provide additional logic to implement a complete cache.    */
+  /*            For example, see `ftcmetrx.h' and `ftcmetrx.c' which       */
+  /*            implement a glyph metrics cache based on this code.        */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*********                                                       *********/
+  /*********             WARNING, THIS IS BETA CODE.               *********/
+  /*********                                                       *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#ifndef __FTCCHUNK_H__
+#define __FTCCHUNK_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_MANAGER_H
+
+
+FT_BEGIN_HEADER
+
+
+  /* maximum number of chunk sets in a given chunk cache */
+#define FTC_MAX_CHUNK_SETS  16
+
+
+  typedef struct FTC_ChunkNodeRec_*    FTC_ChunkNode;
+  typedef struct FTC_ChunkSetRec_*     FTC_ChunkSet;
+  typedef struct FTC_Chunk_CacheRec_*  FTC_Chunk_Cache;
+
+  typedef struct  FTC_ChunkNodeRec_
+  {
+    FTC_CacheNodeRec  root;
+    FTC_ChunkSet      cset;
+    FT_UShort         cset_index;
+    FT_UShort         num_elements;
+    FT_Byte*          elements;
+
+  } FTC_ChunkNodeRec;
+
+
+#define FTC_CHUNKNODE_TO_LRUNODE( x )  ((FT_ListNode)( x ))
+#define FTC_LRUNODE_TO_CHUNKNODE( x )  ((FTC_ChunkNode)( x ))
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  chunk set methods                                                    */
+  /*                                                                       */
+
+  /* used to set "element_max", "element_count" and "element_size" */
+  typedef FT_Error
+  (*FTC_ChunkSet_SizesFunc)( FTC_ChunkSet  cset,
+                             FT_Pointer    type );
+
+  typedef FT_Error
+  (*FTC_ChunkSet_InitFunc)( FTC_ChunkSet  cset,
+                            FT_Pointer    type );
+
+  typedef void
+  (*FTC_ChunkSet_DoneFunc)( FTC_ChunkSet  cset );
+
+  typedef FT_Bool
+  (*FTC_ChunkSet_CompareFunc)( FTC_ChunkSet  cset,
+                               FT_Pointer    type );
+
+
+  typedef FT_Error
+  (*FTC_ChunkSet_NewNodeFunc)( FTC_ChunkSet    cset,
+                               FT_UInt         index,
+                               FTC_ChunkNode*  anode );
+
+  typedef void
+  (*FTC_ChunkSet_DestroyNodeFunc)( FTC_ChunkNode   node );
+
+  typedef FT_ULong
+  (*FTC_ChunkSet_SizeNodeFunc)( FTC_ChunkNode   node );
+
+
+  typedef struct  FTC_ChunkSet_Class_
+  {
+    FT_UInt                       cset_byte_size;
+
+    FTC_ChunkSet_InitFunc         init;
+    FTC_ChunkSet_DoneFunc         done;
+    FTC_ChunkSet_CompareFunc      compare;
+    FTC_ChunkSet_SizesFunc        sizes;
+
+    FTC_ChunkSet_NewNodeFunc      new_node;
+    FTC_ChunkSet_SizeNodeFunc     size_node;
+    FTC_ChunkSet_DestroyNodeFunc  destroy_node;
+
+  } FTC_ChunkSet_Class;
+
+
+  typedef struct  FTC_ChunkSetRec_
+  {
+    FTC_Chunk_Cache      cache;
+    FTC_Manager          manager;
+    FT_Memory            memory;
+    FTC_ChunkSet_Class*  clazz;
+    FT_UInt              cset_index;     /* index in parent cache    */
+
+    FT_UInt              element_max;    /* maximum number of elements   */
+    FT_UInt              element_size;   /* element size in bytes        */
+    FT_UInt              element_count;  /* number of elements per chunk */
+
+    FT_UInt              num_chunks;
+    FTC_ChunkNode*       chunks;
+
+  } FTC_ChunkSetRec;
+
+
+  /* the abstract chunk cache class */
+  typedef struct  FTC_Chunk_Cache_Class_
+  {
+    FTC_Cache_Class      root;
+    FTC_ChunkSet_Class*  cset_class;
+
+  } FTC_Chunk_Cache_Class;
+
+
+  /* the abstract chunk cache object */
+  typedef struct  FTC_Chunk_CacheRec_
+  {
+    FTC_CacheRec              root;
+    FT_Lru                    csets_lru;   /* static chunk set lru list */
+    FTC_ChunkSet              last_cset;   /* small cache :-)           */
+    FTC_ChunkSet_CompareFunc  compare;     /* useful shortcut           */
+
+  } FTC_Chunk_CacheRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* These functions are exported so that they can be called from          */
+  /* user-provided cache classes; otherwise, they are really part of the   */
+  /* cache sub-system internals.                                           */
+  /*                                                                       */
+
+  FT_EXPORT( FT_Error )
+  FTC_ChunkNode_Init( FTC_ChunkNode  node,
+                      FTC_ChunkSet   cset,
+                      FT_UInt        index,
+                      FT_Bool        alloc );
+
+#define FTC_ChunkNode_Ref( n ) \
+          FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count++
+
+#define FTC_ChunkNode_Unref( n ) \
+          FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count--
+
+
+  /* chunk set objects */
+
+  FT_EXPORT( void )
+  FTC_ChunkNode_Destroy( FTC_ChunkNode    node );
+
+
+  FT_EXPORT( FT_Error )
+  FTC_ChunkSet_New( FTC_Chunk_Cache  cache,
+                    FT_Pointer       type,
+                    FTC_ChunkSet    *aset );
+
+
+  FT_EXPORT( FT_Error )
+  FTC_ChunkSet_Lookup_Node( FTC_ChunkSet    cset,
+                            FT_UInt         glyph_index,
+                            FTC_ChunkNode*  anode,
+                            FT_UInt        *anindex );
+
+
+  /* chunk cache objects */
+
+  FT_EXPORT( FT_Error )
+  FTC_Chunk_Cache_Init( FTC_Chunk_Cache  cache );
+
+  FT_EXPORT( void )
+  FTC_Chunk_Cache_Done( FTC_Chunk_Cache  cache );
+
+  FT_EXPORT( FT_Error )
+  FTC_Chunk_Cache_Lookup( FTC_Chunk_Cache  cache,
+                          FT_Pointer       type,
+                          FT_UInt          gindex,
+                          FTC_ChunkNode   *anode,
+                          FT_UInt         *aindex );
+
+
+FT_END_HEADER
+
+#endif /* __FTCCHUNK_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/cache/ftcglyph.h b/libraries/freetype-2.0.5/include/freetype/cache/ftcglyph.h
new file mode 100644 (file)
index 0000000..a8af44a
--- /dev/null
@@ -0,0 +1,222 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcglyph.h                                                             */
+/*                                                                         */
+/*    FreeType abstract glyph cache (specification).                       */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Important: The functions defined in this file are only used to        */
+  /*            implement an abstract glyph cache class.  You need to      */
+  /*            provide additional logic to implement a complete cache.    */
+  /*            For example, see `ftcimage.h' and `ftcimage.c' which       */
+  /*            implement a FT_Glyph cache based on this code.             */
+  /*                                                                       */
+  /*  NOTE: For now, each glyph set is implemented as a static hash table. */
+  /*        It would be interesting to experiment with dynamic hashes to   */
+  /*        see whether this improves performance or not (I don't know why */
+  /*        but something tells me it won't).                              */
+  /*                                                                       */
+  /*        In all cases, this change should not affect any derived glyph  */
+  /*        cache class.                                                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*********                                                       *********/
+  /*********             WARNING, THIS IS BETA CODE.               *********/
+  /*********                                                       *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#ifndef __FTCGLYPH_H__
+#define __FTCGLYPH_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_MANAGER_H
+
+#include <stddef.h>
+
+
+FT_BEGIN_HEADER
+
+
+  /* maximum number of glyph sets per glyph cache; must be < 256 */
+#define FTC_MAX_GLYPH_SETS          16
+#define FTC_GSET_HASH_SIZE_DEFAULT  64
+
+
+  typedef struct FTC_GlyphSetRec_*     FTC_GlyphSet;
+  typedef struct FTC_GlyphNodeRec_*    FTC_GlyphNode;
+  typedef struct FTC_Glyph_CacheRec_*  FTC_Glyph_Cache;
+
+  typedef struct  FTC_GlyphNodeRec_
+  {
+    FTC_CacheNodeRec  root;
+    FTC_GlyphNode     gset_next;   /* next in glyph set's bucket list */
+    FT_UShort         glyph_index;
+    FT_UShort         gset_index;
+
+  } FTC_GlyphNodeRec;
+
+
+#define FTC_GLYPHNODE( x )             ( (FTC_GlyphNode)( x ) )
+#define FTC_GLYPHNODE_TO_LRUNODE( n )  ( (FT_ListNode)( n ) )
+#define FTC_LRUNODE_TO_GLYPHNODE( n )  ( (FTC_GlyphNode)( n ) )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Glyph set methods.                                                    */
+  /*                                                                       */
+
+  typedef FT_Error
+  (*FTC_GlyphSet_InitFunc)( FTC_GlyphSet    gset,
+                            FT_Pointer      type );
+
+  typedef void
+  (*FTC_GlyphSet_DoneFunc)( FTC_GlyphSet    gset );
+
+  typedef FT_Bool
+  (*FTC_GlyphSet_CompareFunc)( FTC_GlyphSet    gset,
+                               FT_Pointer      type );
+
+
+  typedef FT_Error
+  (*FTC_GlyphSet_NewNodeFunc)( FTC_GlyphSet    gset,
+                               FT_UInt         gindex,
+                               FTC_GlyphNode*  anode );
+
+  typedef void
+  (*FTC_GlyphSet_DestroyNodeFunc)( FTC_GlyphNode   node,
+                                   FTC_GlyphSet    gset );
+
+  typedef FT_ULong
+  (*FTC_GlyphSet_SizeNodeFunc)( FTC_GlyphNode   node,
+                                FTC_GlyphSet    gset );
+
+
+  typedef struct  FTC_GlyphSet_Class_
+  {
+    FT_UInt                       gset_byte_size;
+
+    FTC_GlyphSet_InitFunc         init;
+    FTC_GlyphSet_DoneFunc         done;
+    FTC_GlyphSet_CompareFunc      compare;
+
+    FTC_GlyphSet_NewNodeFunc      new_node;
+    FTC_GlyphSet_SizeNodeFunc     size_node;
+    FTC_GlyphSet_DestroyNodeFunc  destroy_node;
+
+  } FTC_GlyphSet_Class;
+
+
+  typedef struct  FTC_GlyphSetRec_
+  {
+    FTC_Glyph_Cache      cache;
+    FTC_Manager          manager;
+    FT_Memory            memory;
+    FTC_GlyphSet_Class*  clazz;
+    FT_UInt              hash_size;
+    FTC_GlyphNode*       buckets;
+    FT_UInt              gset_index;  /* index in parent cache    */
+
+  } FTC_GlyphSetRec;
+
+
+  /* the abstract glyph cache class */
+  typedef struct  FTC_Glyph_Cache_Class_
+  {
+    FTC_Cache_Class      root;
+    FTC_GlyphSet_Class*  gset_class;
+
+  } FTC_Glyph_Cache_Class;
+
+
+  /* the abstract glyph cache object */
+  typedef struct  FTC_Glyph_CacheRec_
+  {
+    FTC_CacheRec              root;
+    FT_Lru                    gsets_lru;    /* static sets lru list */
+    FTC_GlyphSet              last_gset;    /* small cache :-)      */
+    FTC_GlyphSet_CompareFunc  compare;      /* useful shortcut      */
+
+  } FTC_Glyph_CacheRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* These functions are exported so that they can be called from          */
+  /* user-provided cache classes; otherwise, they are really part of the   */
+  /* cache sub-system internals.                                           */
+  /*                                                                       */
+
+  FT_EXPORT( void )
+  FTC_GlyphNode_Init( FTC_GlyphNode  node,
+                      FTC_GlyphSet   gset,
+                      FT_UInt        gindex );
+
+#define FTC_GlyphNode_Ref( n ) \
+          FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count++
+
+#define FTC_GlyphNode_Unref( n ) \
+          FTC_CACHENODE_TO_DATA_P( &(n)->root )->ref_count--
+
+
+  FT_EXPORT( void )
+  FTC_GlyphNode_Destroy( FTC_GlyphNode    node,
+                         FTC_Glyph_Cache  cache );
+
+  FT_EXPORT( FT_Error )
+  FTC_Glyph_Cache_Init(  FTC_Glyph_Cache  cache );
+
+  FT_EXPORT( void )
+  FTC_Glyph_Cache_Done(  FTC_Glyph_Cache  cache );
+
+
+  FT_EXPORT( FT_Error )
+  FTC_GlyphSet_New( FTC_Glyph_Cache  cache,
+                    FT_Pointer       type,
+                    FTC_GlyphSet    *aset );
+
+  FT_EXPORT( FT_Error )
+  FTC_GlyphSet_Lookup_Node( FTC_GlyphSet    gset,
+                            FT_UInt         glyph_index,
+                            FTC_GlyphNode  *anode );
+
+  FT_EXPORT( FT_Error )
+  FTC_Glyph_Cache_Lookup( FTC_Glyph_Cache  cache,
+                          FT_Pointer       type,
+                          FT_UInt          gindex,
+                          FTC_GlyphNode   *anode );
+
+
+FT_END_HEADER
+
+#endif /* __FTCGLYPH_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/cache/ftcimage.h b/libraries/freetype-2.0.5/include/freetype/cache/ftcimage.h
new file mode 100644 (file)
index 0000000..376aeab
--- /dev/null
@@ -0,0 +1,181 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcimage.h                                                             */
+/*                                                                         */
+/*    FreeType Image cache (body).                                         */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Each image cache really manages FT_Glyph objects.                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTCIMAGE_H__
+#define __FTCIMAGE_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_INTERNAL_GLYPH_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    cache_subsystem                                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                       IMAGE CACHE OBJECT                      *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define FTC_IMAGE_FORMAT( x )  ( (x) & 7 )
+
+
+#define ftc_image_format_bitmap      0
+#define ftc_image_format_outline     1
+
+#define ftc_image_flag_monochrome   16
+#define ftc_image_flag_unhinted     32
+#define ftc_image_flag_autohinted   64
+#define ftc_image_flag_unscaled    128
+#define ftc_image_flag_no_sbits    256
+
+  /* monochrome bitmap */
+#define ftc_image_mono             ftc_image_format_bitmap | \
+                                   ftc_image_flag_monochrome
+  /* anti-aliased bitmap */
+#define ftc_image_grays            ftc_image_format_bitmap
+  /* scaled outline */
+#define ftc_image_outline          ftc_image_format_outline
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FTC_Image_Desc                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to describe a given glyph image category.  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    size       :: An FTC_SizeRec used to describe the glyph's face &   */
+  /*                  size.                                                */
+  /*                                                                       */
+  /*    image_type :: The glyph image's type.                              */
+  /*                                                                       */
+  typedef struct  FTC_Image_Desc_
+  {
+    FTC_FontRec  font;
+    FT_UInt      image_type;
+
+  } FTC_Image_Desc;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FTC_Image_Cache                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to an glyph image cache object.  They are designed to     */
+  /*    hold many distinct glyph images, while not exceeding a certain     */
+  /*    memory threshold.                                                  */
+  /*                                                                       */
+  typedef struct FTC_Image_CacheRec_*  FTC_Image_Cache;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_Image_Cache_New                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new glyph image cache.                                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    manager :: The parent manager for the image cache.                 */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    acache  :: A handle to the new glyph image cache object.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FTC_Image_Cache_New( FTC_Manager       manager,
+                       FTC_Image_Cache  *acache );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_Image_Cache_Lookup                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves a given glyph image from a glyph image cache.            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    cache  :: A handle to the source glyph image cache.                */
+  /*                                                                       */
+  /*    desc   :: A pointer to a glyph image descriptor.                   */
+  /*                                                                       */
+  /*    gindex :: The glyph index to retrieve.                             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aglyph :: The corresponding FT_Glyph object.  0 in case of         */
+  /*              failure.                                                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The returned glyph is owned and managed by the glyph image cache.  */
+  /*    Never try to transform or discard it manually!  You can however    */
+  /*    create a copy with FT_Glyph_Copy() and modify the new one.         */
+  /*                                                                       */
+  /*    Because the glyph image cache limits the total amount of memory    */
+  /*    taken by the glyphs it holds, the returned glyph might disappear   */
+  /*    on a later invocation of this function!  It's a cache after all... */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FTC_Image_Cache_Lookup( FTC_Image_Cache  cache,
+                          FTC_Image_Desc*  desc,
+                          FT_UInt          gindex,
+                          FT_Glyph        *aglyph );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTCIMAGE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/cache/ftcmanag.h b/libraries/freetype-2.0.5/include/freetype/cache/ftcmanag.h
new file mode 100644 (file)
index 0000000..2d97fad
--- /dev/null
@@ -0,0 +1,385 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcmanag.h                                                             */
+/*                                                                         */
+/*    FreeType Cache Manager (specification).                              */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A cache manager is in charge of the following:                        */
+  /*                                                                       */
+  /*  - Maintain a mapping between generic FTC_FaceIDs and live FT_Face    */
+  /*    objects.  The mapping itself is performed through a user-provided  */
+  /*    callback.  However, the manager maintains a small cache of FT_Face */
+  /*    & FT_Size objects in order to speed up things considerably.        */
+  /*                                                                       */
+  /*  - Manage one or more cache objects.  Each cache is in charge of      */
+  /*    holding a varying number of `cache nodes'.  Each cache node        */
+  /*    represents a minimal amount of individually accessible cached      */
+  /*    data.  For example, a cache node can be an FT_Glyph image          */
+  /*    containing a vector outline, or some glyph metrics, or anything    */
+  /*    else.                                                              */
+  /*                                                                       */
+  /*    Each cache node has a certain size in bytes that is added to the   */
+  /*    total amount of `cache memory' within the manager.                 */
+  /*                                                                       */
+  /*    All cache nodes are located in a global LRU list, where the oldest */
+  /*    node is at the tail of the list.                                   */
+  /*                                                                       */
+  /*    Each node belongs to a single cache, and includes a reference      */
+  /*    count to avoid destroying it (due to caching).                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*********                                                       *********/
+  /*********             WARNING, THIS IS BETA CODE.               *********/
+  /*********                                                       *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#ifndef __FTCMANAG_H__
+#define __FTCMANAG_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_INTERNAL_LRU_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    cache_subsystem                                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define FTC_MAX_FACES_DEFAULT  2
+#define FTC_MAX_SIZES_DEFAULT  4
+#define FTC_MAX_BYTES_DEFAULT  200000L  /* 200kByte by default! */
+
+  /* maximum number of caches registered in a single manager */
+#define FTC_MAX_CACHES         16
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FTC_ManagerRec                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The cache manager structure.                                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    library      :: A handle to a FreeType library instance.           */
+  /*                                                                       */
+  /*    faces_lru    :: The lru list of FT_Face objects in the cache.      */
+  /*                                                                       */
+  /*    sizes_lru    :: The lru list of FT_Size objects in the cache.      */
+  /*                                                                       */
+  /*    max_bytes    :: The maximum number of bytes to be allocated in the */
+  /*                    cache.  This is only related to the byte size of   */
+  /*                    the nodes cached by the manager.                   */
+  /*                                                                       */
+  /*    num_bytes    :: The current number of bytes allocated in the       */
+  /*                    cache.  Only related to the byte size of cached    */
+  /*                    nodes.                                             */
+  /*                                                                       */
+  /*    num_nodes    :: The current number of nodes in the manager.        */
+  /*                                                                       */
+  /*    global_lru   :: The global lru list of all cache nodes.            */
+  /*                                                                       */
+  /*    caches       :: A table of installed/registered cache objects.     */
+  /*                                                                       */
+  /*    request_data :: User-provided data passed to the requester.        */
+  /*                                                                       */
+  /*    request_face :: User-provided function used to implement a mapping */
+  /*                    between abstract FTC_FaceIDs and real FT_Face      */
+  /*                    objects.                                           */
+  /*                                                                       */
+  typedef struct  FTC_ManagerRec_
+  {
+    FT_Library          library;
+    FT_Lru              faces_lru;
+    FT_Lru              sizes_lru;
+
+    FT_ULong            max_bytes;
+    FT_ULong            num_bytes;
+    FT_UInt             num_nodes;
+    FT_ListRec          global_lru;
+    FTC_Cache           caches[FTC_MAX_CACHES];
+
+    FT_Pointer          request_data;
+    FTC_Face_Requester  request_face;
+
+  } FTC_ManagerRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_Manager_Compress                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used to check the state of the cache manager if   */
+  /*    its `num_bytes' field is greater than its `max_bytes' field.  It   */
+  /*    will flush as many old cache nodes as possible (ignoring cache     */
+  /*    nodes with a non-zero reference count).                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    manager :: A handle to the cache manager.                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Client applications should not call this function directly.  It is */
+  /*    normally invoked by specific cache implementations.                */
+  /*                                                                       */
+  /*    The reason this function is exported is to allow client-specific   */
+  /*    cache classes.                                                     */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FTC_Manager_Compress( FTC_Manager  manager );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   CACHE NODE DEFINITIONS                      *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Each cache controls one or more cache nodes.  Each node is part of    */
+  /* the global_lru list of the manager.  Its `data' field however is used */
+  /* as a reference count for now.                                         */
+  /*                                                                       */
+  /* A node can be anything, depending on the type of information held by  */
+  /* the cache.  It can be an individual glyph image, a set of bitmaps     */
+  /* glyphs for a given size, some metrics, etc.                           */
+  /*                                                                       */
+
+  typedef FT_ListNodeRec     FTC_CacheNodeRec;
+  typedef FTC_CacheNodeRec*  FTC_CacheNode;
+
+
+  /* the field `cachenode.data' is typecast to this type */
+  typedef struct  FTC_CacheNode_Data_
+  {
+    FT_UShort  cache_index;
+    FT_Short   ref_count;
+
+  } FTC_CacheNode_Data;
+
+
+  /* return a pointer to FTC_CacheNode_Data contained in a */
+  /* CacheNode's `data' field                              */
+#define FTC_CACHENODE_TO_DATA_P( n ) \
+          ( (FTC_CacheNode_Data*)&(n)->data )
+
+#define FTC_LIST_TO_CACHENODE( n )  ( (FTC_CacheNode)(n) )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FTC_CacheNode_SizeFunc                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to compute the total size in bytes of a given      */
+  /*    cache node.  It is used by the cache manager to compute the number */
+  /*    of old nodes to flush when the cache is full.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    node       :: A handle to the target cache node.                   */
+  /*                                                                       */
+  /*    cache_data :: A generic pointer passed to the destructor.          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The size of a given cache node in bytes.                           */
+  /*                                                                       */
+  typedef FT_ULong
+  (*FTC_CacheNode_SizeFunc)( FTC_CacheNode  node,
+                             FT_Pointer     cache_data );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FTC_CacheNode_DestroyFunc                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to destroy a given cache node.  It is called by    */
+  /*    the manager when the cache is full and old nodes need to be        */
+  /*    flushed out.                                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    node       :: A handle to the target cache node.                   */
+  /*                                                                       */
+  /*    cache_data :: A generic pointer passed to the destructor.          */
+  /*                                                                       */
+  typedef void
+  (*FTC_CacheNode_DestroyFunc)( FTC_CacheNode  node,
+                                FT_Pointer     cache_data );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FTC_CacheNode_Class                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple structure used to describe a cache node's class to   */
+  /*    the cache manager.                                                 */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    size_node    :: A function used to size the node.                  */
+  /*                                                                       */
+  /*    destroy_node :: A function used to destroy the node.               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The cache node class doesn't include a `new_node' function because */
+  /*    the cache manager never allocates cache node directly; it          */
+  /*    delegates this task to its cache objects.                          */
+  /*                                                                       */
+  typedef struct  FTC_CacheNode_Class_
+  {
+    FTC_CacheNode_SizeFunc     size_node;
+    FTC_CacheNode_DestroyFunc  destroy_node;
+
+  } FTC_CacheNode_Class;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                       CACHE DEFINITIONS                       *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FTC_Cache_InitFunc                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to initialize a given cache object.                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    cache :: A handle to the new cache.                                */
+  /*                                                                       */
+  typedef FT_Error
+  (*FTC_Cache_InitFunc)( FTC_Cache  cache );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FTC_Cache_DoneFunc                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function to finalize a given cache object.                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    cache :: A handle to the target cache.                             */
+  /*                                                                       */
+  typedef void
+  (*FTC_Cache_DoneFunc)( FTC_Cache  cache );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FTC_Cache_Class                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe a given cache object class to the     */
+  /*    cache manager.                                                     */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    cache_byte_size :: The size of the cache object in bytes.          */
+  /*                                                                       */
+  /*    init_cache      :: The cache object initializer.                   */
+  /*                                                                       */
+  /*    done_cache      :: The cache object finalizer.                     */
+  /*                                                                       */
+  struct  FTC_Cache_Class_
+  {
+    FT_UInt             cache_byte_size;
+    FTC_Cache_InitFunc  init_cache;
+    FTC_Cache_DoneFunc  done_cache;
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FTC_CacheRec                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe an abstract cache object.             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    manager     :: A handle to the parent cache manager.               */
+  /*                                                                       */
+  /*    memory      :: A handle to the memory manager.                     */
+  /*                                                                       */
+  /*    clazz       :: A pointer to the cache class.                       */
+  /*                                                                       */
+  /*    node_clazz  :: A pointer to the cache's node class.                */
+  /*                                                                       */
+  /*    cache_index :: An index of the cache in the manager's table.       */
+  /*                                                                       */
+  /*    cache_data  :: Data passed to the cache node                       */
+  /*                   constructor/finalizer.                              */
+  /*                                                                       */
+  typedef struct  FTC_CacheRec_
+  {
+    FTC_Manager           manager;
+    FT_Memory             memory;
+    FTC_Cache_Class*      clazz;
+    FTC_CacheNode_Class*  node_clazz;
+
+    FT_UInt               cache_index;  /* in manager's table           */
+    FT_Pointer            cache_data;   /* passed to cache node methods */
+
+  } FTC_CacheRec;
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTCMANAG_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/cache/ftcsbits.h b/libraries/freetype-2.0.5/include/freetype/cache/ftcsbits.h
new file mode 100644 (file)
index 0000000..aba87c8
--- /dev/null
@@ -0,0 +1,181 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcsbits.h                                                             */
+/*                                                                         */
+/*    A small-bitmap cache (specification).                                */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTCSBITS_H__
+#define __FTCSBITS_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include FT_CACHE_INTERNAL_CHUNK_H
+#include FT_CACHE_IMAGE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    cache_subsystem                                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FTC_SBit                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a small bitmap descriptor.  See the FTC_SBitRec        */
+  /*    structure for details.                                             */
+  /*                                                                       */
+  typedef struct FTC_SBitRec_*  FTC_SBit;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FTC_SBit_Cache                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a small bitmap cache.  These are special cache objects */
+  /*    used to store small glyph bitmaps (and anti-aliased pixmaps) in a  */
+  /*    much more efficient way than the traditional glyph image cache     */
+  /*    implemented by FTC_Image_Cache.                                    */
+  /*                                                                       */
+  typedef struct FTC_SBit_CacheRec_*  FTC_SBit_Cache;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FTC_SBitRec                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very compact structure used to describe a small glyph bitmap.    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    width    :: The bitmap width in pixels.                            */
+  /*                                                                       */
+  /*    height   :: The bitmap height in pixels.                           */
+  /*                                                                       */
+  /*    left     :: The horizontal distance from the pen position to the   */
+  /*                left bitmap border (a.k.a. `left side bearing', or     */
+  /*                `lsb').                                                */
+  /*                                                                       */
+  /*    top      :: The vertical distance from the pen position (on the    */
+  /*                baseline) to the upper bitmap border (a.k.a. `top side */
+  /*                bearing').  The distance is positive for upwards       */
+  /*                Y coordinates.                                         */
+  /*                                                                       */
+  /*    format   :: The format of the glyph bitmap (monochrome or gray).   */
+  /*                                                                       */
+  /*    pitch    :: The number of bytes per bitmap line.  May be positive  */
+  /*                or negative.                                           */
+  /*                                                                       */
+  /*    xadvance :: The horizontal advance width in pixels.                */
+  /*                                                                       */
+  /*    yadvance :: The vertical advance height in pixels.                 */
+  /*                                                                       */
+  /*    buffer   :: A pointer to the bitmap pixels.                        */
+  /*                                                                       */
+  typedef struct  FTC_SBitRec_
+  {
+    FT_Byte   width;
+    FT_Byte   height;
+    FT_Char   left;
+    FT_Char   top;
+
+    FT_Byte   format;
+    FT_Char   pitch;
+    FT_Char   xadvance;
+    FT_Char   yadvance;
+
+    FT_Byte*  buffer;
+
+  } FTC_SBitRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_SBit_Cache_New                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new cache to store small glyph bitmaps.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    manager :: A handle to the source cache manager.                   */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    acache  :: A handle to the new sbit cache.  NULL in case of error. */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FTC_SBit_Cache_New( FTC_Manager      manager,
+                      FTC_SBit_Cache  *acache );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_SBit_Cache_Lookup                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Looks up a given small glyph bitmap in a given sbit cache.         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    cache  :: A handle to the source sbit cache.                       */
+  /*    desc   :: A pointer to the glyph image descriptor.                 */
+  /*    gindex :: The glyph index.                                         */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    sbit   :: A handle to a small bitmap descriptor.                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The small bitmap descriptor and its bit buffer are owned by the    */
+  /*    cache and should never be freed by the application.  They might    */
+  /*    as well disappear from memory on the next cache lookup, so don't   */
+  /*    treat them as persistent data.                                     */
+  /*                                                                       */
+  /*    The descriptor's `buffer' field is set to 0 to indicate a missing  */
+  /*    glyph bitmap.                                                      */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FTC_SBit_Cache_Lookup( FTC_SBit_Cache   cache,
+                         FTC_Image_Desc*  desc,
+                         FT_UInt          gindex,
+                         FTC_SBit        *sbit );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTCSBITS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/cache/ftlru.h b/libraries/freetype-2.0.5/include/freetype/cache/ftlru.h
new file mode 100644 (file)
index 0000000..7874438
--- /dev/null
@@ -0,0 +1,185 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftlru.h                                                                */
+/*                                                                         */
+/*    Simple LRU list-cache (specification).                               */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* An LRU is a list that cannot hold more than a certain number of       */
+  /* elements (`max_elements').  All elements on the list are sorted in    */
+  /* least-recently-used order, i.e., the `oldest' element is at the tail  */
+  /* of the list.                                                          */
+  /*                                                                       */
+  /* When doing a lookup (either through `Lookup()' or `Lookup_Node()'),   */
+  /* the list is searched for an element with the corresponding key.  If   */
+  /* it is found, the element is moved to the head of the list and is      */
+  /* returned.                                                             */
+  /*                                                                       */
+  /* If no corresponding element is found, the lookup routine will try to  */
+  /* obtain a new element with the relevant key.  If the list is already   */
+  /* full, the oldest element from the list is discarded and replaced by a */
+  /* new one; a new element is added to the list otherwise.                */
+  /*                                                                       */
+  /* Note that it is possible to pre-allocate the element list nodes.      */
+  /* This is handy if `max_elements' is sufficiently small, as it saves    */
+  /* allocations/releases during the lookup process.                       */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*********                                                       *********/
+  /*********             WARNING, THIS IS BETA CODE.               *********/
+  /*********                                                       *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#ifndef __FTLRU_H__
+#define __FTLRU_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /* generic key type */
+  typedef FT_Pointer  FT_LruKey;
+
+
+  /* an lru node -- root.data points to the element */
+  typedef struct  FT_LruNodeRec_
+  {
+    FT_ListNodeRec  root;
+    FT_LruKey       key;
+
+  } FT_LruNodeRec, *FT_LruNode;
+
+
+  /* forward declaration */
+  typedef struct FT_LruRec_*  FT_Lru;
+
+
+  /* LRU class */
+  typedef struct  FT_Lru_Class_
+  {
+    FT_UInt  lru_size;      /* object size in bytes */
+
+    /* this method is used to initialize a new list element node */
+    FT_Error
+    (*init_element)( FT_Lru      lru,
+                     FT_LruNode  node );
+
+    /* this method is used to finalize a given list element node */
+    void
+    (*done_element)( FT_Lru      lru,
+                     FT_LruNode  node );
+
+    /* If defined, this method is called when the list if full        */
+    /* during the lookup process -- it is used to change the contents */
+    /* of a list element node, instead of calling `done_element()',   */
+    /* then `init_element'.  Set it to 0 for default behaviour.       */
+    FT_Error
+    (*flush_element)( FT_Lru      lru,
+                      FT_LruNode  node,
+                      FT_LruKey   new_key );
+
+    /* If defined, this method is used to compare a list element node */
+    /* with a given key during a lookup.  If set to 0, the `key'      */
+    /* fields will be directly compared instead.                      */
+    FT_Bool
+    (*compare_element)( FT_LruNode  node,
+                        FT_LruKey   key );
+
+  } FT_Lru_Class;
+
+
+  /* A selector is used to indicate whether a given list element node    */
+  /* is part of a selection for FT_Lru_Remove_Selection().  The function */
+  /* must return true (i.e., non-null) to indicate that the node is part */
+  /* of it.                                                              */
+  typedef FT_Bool
+  (*FT_Lru_Selector)( FT_Lru      lru,
+                      FT_LruNode  node,
+                      FT_Pointer  data );
+
+
+  typedef struct  FT_LruRec_
+  {
+    FT_Lru_Class*  clazz;
+    FT_UInt        max_elements;
+    FT_UInt        num_elements;
+    FT_ListRec     elements;
+    FT_Memory      memory;
+    FT_Pointer     user_data;
+
+    /* the following fields are only meaningful for static lru containers */
+    FT_ListRec     free_nodes;
+    FT_LruNode     nodes;
+
+  } FT_LruRec;
+
+
+  FT_EXPORT( FT_Error )
+  FT_Lru_New( const FT_Lru_Class*  clazz,
+              FT_UInt              max_elements,
+              FT_Pointer           user_data,
+              FT_Memory            memory,
+              FT_Bool              pre_alloc,
+              FT_Lru              *anlru );
+
+  FT_EXPORT( void )
+  FT_Lru_Reset( FT_Lru  lru );
+
+  FT_EXPORT( void )
+  FT_Lru_Done ( FT_Lru  lru );
+
+  FT_EXPORT( FT_Error )
+  FT_Lru_Lookup_Node( FT_Lru        lru,
+                      FT_LruKey     key,
+                      FT_LruNode   *anode );
+
+  FT_EXPORT( FT_Error )
+  FT_Lru_Lookup( FT_Lru       lru,
+                 FT_LruKey    key,
+                 FT_Pointer  *anobject );
+
+  FT_EXPORT( void )
+  FT_Lru_Remove_Node( FT_Lru      lru,
+                      FT_LruNode  node );
+
+  FT_EXPORT( void )
+  FT_Lru_Remove_Selection( FT_Lru           lru,
+                           FT_Lru_Selector  selector,
+                           FT_Pointer       data );
+
+
+FT_END_HEADER
+
+#endif /* __FTLRU_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/config/Makefile.am b/libraries/freetype-2.0.5/include/freetype/config/Makefile.am
new file mode 100644 (file)
index 0000000..a523052
--- /dev/null
@@ -0,0 +1,3 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_HEADERS = ftconfig.h  ftheader.h  ftmodule.h  ftoption.h  
diff --git a/libraries/freetype-2.0.5/include/freetype/config/ftconfig.h b/libraries/freetype-2.0.5/include/freetype/config/ftconfig.h
new file mode 100644 (file)
index 0000000..f990c90
--- /dev/null
@@ -0,0 +1,326 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftconfig.h                                                             */
+/*                                                                         */
+/*    ANSI-specific configuration file (specification only).               */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This header file contains a number of macro definitions that are used */
+  /* by the rest of the engine.  Most of the macros here are automatically */
+  /* determined at compile time, and you should not need to change it to   */
+  /* port FreeType, except to compile the library with a non-ANSI          */
+  /* compiler.                                                             */
+  /*                                                                       */
+  /* Note however that if some specific modifications are needed, we       */
+  /* advise you to place a modified copy in your build directory.          */
+  /*                                                                       */
+  /* The build directory is usually `freetype/builds/<system>', and        */
+  /* contains system-specific files that are always included first when    */
+  /* building the library.                                                 */
+  /*                                                                       */
+  /* This ANSI version should stay in `include/freetype/config'.           */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTCONFIG_H__
+#define __FTCONFIG_H__
+
+#include <ft2build.h>
+#include FT_CONFIG_OPTIONS_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*               PLATFORM-SPECIFIC CONFIGURATION MACROS                  */
+  /*                                                                       */
+  /* These macros can be toggled to suit a specific system.  The current   */
+  /* ones are defaults used to compile FreeType in an ANSI C environment   */
+  /* (16bit compilers are also supported).  Copy this file to your own     */
+  /* `freetype/builds/<system>' directory, and edit it to port the engine. */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* We use <limits.h> values to know the sizes of the types.  */
+#include <limits.h>
+
+  /* The number of bytes in an `int' type.  */
+#if   UINT_MAX == 0xFFFFFFFFUL
+#define FT_SIZEOF_INT  4
+#elif UINT_MAX == 0xFFFFU
+#define FT_SIZEOF_INT  2
+#elif UINT_MAX > 0xFFFFFFFFU && UINT_MAX == 0xFFFFFFFFFFFFFFFFU
+#define FT_SIZEOF_INT  8
+#else
+#error "Unsupported number of bytes in `int' type!"
+#endif
+
+  /* The number of bytes in a `long' type.  */
+#if   ULONG_MAX == 0xFFFFFFFFUL
+#define FT_SIZEOF_LONG  4
+#elif ULONG_MAX > 0xFFFFFFFFU && ULONG_MAX == 0xFFFFFFFFFFFFFFFFU
+#define FT_SIZEOF_LONG  8
+#else
+#error "Unsupported number of bytes in `long' type!"
+#endif
+
+
+  /* Preferred alignment of data */
+#define FT_ALIGNMENT  8
+
+
+  /* UNUSED is a macro used to indicate that a given parameter is not used */
+  /* -- this is only used to get rid of unpleasant compiler warnings       */
+#ifndef FT_UNUSED
+#define FT_UNUSED( arg )  ( (arg) = (arg) )
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                     AUTOMATIC CONFIGURATION MACROS                    */
+  /*                                                                       */
+  /* These macros are computed from the ones defined above.  Don't touch   */
+  /* their definition, unless you know precisely what you are doing.  No   */
+  /* porter should need to mess with them.                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IntN types                                                            */
+  /*                                                                       */
+  /*   Used to guarantee the size of some specific integers.               */
+  /*                                                                       */
+  typedef signed short    FT_Int16;
+  typedef unsigned short  FT_UInt16;
+
+#if FT_SIZEOF_INT == 4
+
+  typedef signed int      FT_Int32;
+  typedef unsigned int    FT_UInt32;
+
+#elif FT_SIZEOF_LONG == 4
+
+  typedef signed long     FT_Int32;
+  typedef unsigned long   FT_UInt32;
+
+#else
+#error "no 32bit type found -- please check your configuration files"
+#endif
+
+  /* now, lookup for an integer type that is at least 32 bits */
+#if FT_SIZEOF_INT >= 4
+
+  typedef int           FT_Fast;
+  typedef unsigned int  FT_UFast;
+
+#elif FT_SIZEOF_LONG >= 4
+
+  typedef long          FT_Fast;
+  typedef unsigned long FT_UFast;
+
+#endif
+
+
+
+  /* determine whether we have a 64-bit int type for platforms without */
+  /* Autoconf                                                          */
+#if FT_SIZEOF_LONG == 8
+
+  /* FT_LONG64 must be defined if a 64-bit type is available */
+#define FT_LONG64
+#define FT_INT64  long
+
+#elif defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
+
+  /* this compiler provides the __int64 type */
+#define FT_LONG64
+#define FT_INT64  __int64
+
+#elif defined( __BORLANDC__ )  /* Borland C++ */
+
+  /* XXXX: We should probably check the value of __BORLANDC__ in order */
+  /*       to test the compiler version.                               */
+
+  /* this compiler provides the __int64 type */
+#define FT_LONG64
+#define FT_INT64  __int64
+
+#elif defined( __WATCOMC__ )   /* Watcom C++ */
+
+  /* Watcom doesn't provide 64-bit data types */
+
+#elif defined( __MWKS__ )      /* Metrowerks CodeWarrior */
+
+  /* I don't know if it provides 64-bit data types, any suggestion */
+  /* is welcome.                                                   */
+
+#elif defined( __GNUC__ )
+
+  /* GCC provides the "long long" type */
+#define FT_LONG64
+#define FT_INT64  long long int
+
+#endif /* !FT_LONG64 */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A 64-bit data type will create compilation problems if you compile    */
+  /* in strict ANSI mode.  To avoid them, we disable their use if          */
+  /* __STDC__ is defined.  You can however ignore this rule by             */
+  /* defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro.        */
+  /*                                                                       */
+#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 )
+
+#ifdef __STDC__
+
+  /* undefine the 64-bit macros in strict ANSI compilation mode */
+#undef FT_LONG64
+#undef FT_INT64
+
+#endif /* __STDC__ */
+
+#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */
+
+
+#ifdef FT_MAKE_OPTION_SINGLE_OBJECT
+
+#define FT_LOCAL      static
+#define FT_LOCAL_DEF  static
+
+#else
+
+#ifdef __cplusplus
+#define FT_LOCAL      extern "C"
+#define FT_LOCAL_DEF  extern "C"
+#else
+#define FT_LOCAL      extern
+#define FT_LOCAL_DEF  extern
+#endif
+
+#endif /* FT_MAKE_OPTION_SINGLE_OBJECT */
+
+
+#ifndef FT_BASE
+
+#ifdef __cplusplus
+#define FT_BASE( x )  extern "C"  x
+#else
+#define FT_BASE( x )  extern  x
+#endif
+
+#endif /* !FT_BASE */
+
+
+#ifndef FT_BASE_DEF
+
+#ifdef __cplusplus
+#define FT_BASE_DEF( x )  extern "C"  x
+#else
+#define FT_BASE_DEF( x )  extern  x
+#endif
+
+#endif /* !FT_BASE_DEF */
+
+
+#ifndef FT_EXPORT
+
+#ifdef __cplusplus
+#define FT_EXPORT( x )  extern "C"  x
+#else
+#define FT_EXPORT( x )  extern  x
+#endif
+
+#endif /* !FT_EXPORT */
+
+
+#ifndef FT_EXPORT_DEF
+
+#ifdef __cplusplus
+#define FT_EXPORT_DEF( x )  extern "C"  x
+#else
+#define FT_EXPORT_DEF( x )  extern  x
+#endif
+
+#endif /* !FT_EXPORT_DEF */
+
+
+#ifndef FT_EXPORT_VAR
+
+#ifdef __cplusplus
+#define FT_EXPORT_VAR( x )  extern "C"  x
+#else
+#define FT_EXPORT_VAR( x )  extern  x
+#endif
+
+#endif /* !FT_EXPORT_VAR */
+
+  /* The following macros are needed to compile the library with a   */
+  /* C++ compiler and with 16bit compilers.                          */
+  /*                                                                 */
+
+  /* This is special.  Within C++, you must specify `extern "C"' for */
+  /* functions which are used via function pointers, and you also    */
+  /* must do that for structures which contain function pointers to  */
+  /* assure C linkage -- it's not possible to have (local) anonymous */
+  /* functions which are accessed by (global) function pointers.     */
+  /*                                                                 */
+  /*                                                                 */
+  /* FT_CALLBACK_DEF is used to _define_ a callback function.        */
+  /*                                                                 */
+  /* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */
+  /* contains pointers to callback functions.                        */
+  /*                                                                 */
+  /* FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable   */
+  /* that contains pointers to callback functions.                   */
+  /*                                                                 */
+  /*                                                                 */
+  /* Some 16bit compilers have to redefine these macros to insert    */
+  /* the infamous `_cdecl' or `__fastcall' declarations.             */
+  /*                                                                 */
+#ifndef FT_CALLBACK_DEF
+#ifdef __cplusplus
+#define FT_CALLBACK_DEF( x )  extern "C" x
+#else
+#define FT_CALLBACK_DEF( x )  static x
+#endif
+#endif /* FT_CALLBACK_DEF */
+
+#ifndef FT_CALLBACK_TABLE
+#ifdef __cplusplus
+#define FT_CALLBACK_TABLE      extern "C"
+#define FT_CALLBACK_TABLE_DEF  extern "C"
+#else
+#define FT_CALLBACK_TABLE      extern
+#define FT_CALLBACK_TABLE_DEF  /* nothing */
+#endif
+#endif /* FT_CALLBACK_TABLE */
+
+
+FT_END_HEADER
+
+
+#endif /* __FTCONFIG_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/config/ftheader.h b/libraries/freetype-2.0.5/include/freetype/config/ftheader.h
new file mode 100644 (file)
index 0000000..b4ec98b
--- /dev/null
@@ -0,0 +1,481 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftheader.h                                                             */
+/*                                                                         */
+/*    Build macros of the FreeType 2 library.                              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+#ifndef __FT_HEADER_H__
+#define __FT_HEADER_H__
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Macro>                                                               */
+  /*    FT_BEGIN_HEADER                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This macro is used in association with @FT_END_HEADER in header    */
+  /*    files to ensure that the declarations within are properly          */
+  /*    encapsulated in an `extern "C" { .. }' block when included from a  */
+  /*    C++ compiler.                                                      */
+  /*                                                                       */
+#ifdef __cplusplus
+#define FT_BEGIN_HEADER  extern "C" {
+#else
+#define FT_BEGIN_HEADER  /* nothing */
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Macro>                                                               */
+  /*    FT_END_HEADER                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This macro is used in association with @FT_BEGIN_HEADER in header  */
+  /*    files to ensure that the declarations within are properly          */
+  /*    encapsulated in an `extern "C" { .. }' block when included from a  */
+  /*    C++ compiler.                                                      */
+  /*                                                                       */
+#ifdef __cplusplus
+#define FT_END_HEADER  }
+#else
+#define FT_END_HEADER  /* nothing */
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Aliases for the FreeType 2 public and configuration files.            */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    header_file_macros                                                 */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Header File Macros                                                 */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    Macro definitions used to #include specific header files.          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The following macros are defined to the name of specific           */
+  /*    FreeType 2 header files.  They can be used directly in #include    */
+  /*    statements as in:                                                  */
+  /*                                                                       */
+  /*    {                                                                  */
+  /*      #include FT_FREETYPE_H                                           */
+  /*      #include FT_MULTIPLE_MASTERS_H                                   */
+  /*      #include FT_GLYPH_H                                              */
+  /*    }                                                                  */
+  /*                                                                       */
+  /*    There are several reasons why we are now using macros to name      */
+  /*    public header files.  The first one is that such macros are not    */
+  /*    limited to the infamous 8.3 naming rule required by DOS (and       */
+  /*    `FT_MULTIPLE_MASTERS_H' is a lot more meaningful than `ftmm.h').   */
+  /*                                                                       */
+  /*    The second reason is that is allows for more flexibility in the    */
+  /*    way FreeType 2 is installed on a given system.                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /* configuration files */
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_CONFIG_CONFIG_H                                                 */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    FreeType 2 configuration data.                                     */
+  /*                                                                       */
+#ifndef FT_CONFIG_CONFIG_H
+#define FT_CONFIG_CONFIG_H  <freetype/config/ftconfig.h>
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_CONFIG_OPTIONS_H                                                */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    FreeType 2 project-specific configuration options.                 */
+  /*                                                                       */
+#ifndef FT_CONFIG_OPTIONS_H
+#define FT_CONFIG_OPTIONS_H  <freetype/config/ftoption.h>
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_CONFIG_MODULES_H                                                */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the list of FreeType 2 modules that are statically linked to new   */
+  /*    library instances in @FT_Init_FreeType.                            */
+  /*                                                                       */
+#ifndef FT_CONFIG_MODULES_H
+#define FT_CONFIG_MODULES_H  <freetype/config/ftmodule.h>
+#endif
+
+  /* public headers */
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_FREETYPE_H                                                      */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the base FreeType 2 API.                                           */
+  /*                                                                       */
+#define FT_FREETYPE_H  <freetype/freetype.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_ERRORS_H                                                        */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the list of FreeType 2 error codes (and messages).                 */
+  /*                                                                       */
+  /*    It is included by @FT_FREETYPE_H.                                  */
+  /*                                                                       */
+#define FT_ERRORS_H  <freetype/fterrors.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_MODULE_ERRORS_H                                                 */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the list of FreeType 2 module error offsets (and messages).        */
+  /*                                                                       */
+#define FT_MODULE_ERRORS_H  <freetype/ftmoderr.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_SYSTEM_H                                                        */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the FreeType 2 interface to low-level operations (i.e. memory      */
+  /*    management and stream i/o).                                        */
+  /*                                                                       */
+  /*    It is included by @FT_FREETYPE_H.                                  */
+  /*                                                                       */
+#define FT_SYSTEM_H  <freetype/ftsystem.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_IMAGE_H                                                         */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    types definitions related to glyph images (i.e. bitmaps, outlines, */
+  /*    scan-converter parameters).                                        */
+  /*                                                                       */
+  /*    It is included by @FT_FREETYPE_H.                                  */
+  /*                                                                       */
+#define FT_IMAGE_H  <freetype/ftimage.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_TYPES_H                                                         */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the basic data types defined by FreeType 2.                        */
+  /*                                                                       */
+  /*    It is included by @FT_FREETYPE_H.                                  */
+  /*                                                                       */
+#define FT_TYPES_H  <freetype/fttypes.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_LIST_H                                                          */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the list management API of FreeType 2.                             */
+  /*                                                                       */
+  /*    (Most applications will never need to include this file.)          */
+  /*                                                                       */
+#define FT_LIST_H  <freetype/ftlist.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_OUTLINE_H                                                       */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the scalable outline management API of FreeType 2.                 */
+  /*                                                                       */
+#define FT_OUTLINE_H  <freetype/ftoutln.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_SIZES_H                                                         */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the API used to manage multiple @FT_Size objects per face.         */
+  /*                                                                       */
+#define FT_SIZES_H  <freetype/ftsizes.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_MODULE_H                                                        */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the module management API of FreeType 2.                           */
+  /*                                                                       */
+#define FT_MODULE_H  <freetype/ftmodule.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_RENDER_H                                                        */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the renderer module management API of FreeType 2.                  */
+  /*                                                                       */
+#define FT_RENDER_H  <freetype/ftrender.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_TYPE1_TABLES_H                                                  */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the types and API specific to the Type 1 format.                   */
+  /*                                                                       */
+#define FT_TYPE1_TABLES_H  <freetype/t1tables.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_TRUETYPE_IDS_H                                                  */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the enumeration values used to identify name strings, languages,   */
+  /*    encodings, etc.  This file really contains a _large_ set of        */
+  /*    constant macro definitions, taken from the TrueType and OpenType   */
+  /*    specifications.                                                    */
+  /*                                                                       */
+#define FT_TRUETYPE_IDS_H  <freetype/ttnameid.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_TRUETYPE_TABLES_H                                               */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the types and API specific to the TrueType (as well as OpenType)   */
+  /*    format.                                                            */
+  /*                                                                       */
+#define FT_TRUETYPE_TABLES_H  <freetype/tttables.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_TRUETYPE_TAGS_H                                                 */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the definitions of TrueType 4-byte `tags' used to identify blocks  */
+  /*    in SFNT-based font formats (i.e. TrueType and OpenType).           */
+  /*                                                                       */
+#define FT_TRUETYPE_TAGS_H  <freetype/tttags.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_GLYPH_H                                                         */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the API of the optional glyph management component.                */
+  /*                                                                       */
+#define FT_GLYPH_H  <freetype/ftglyph.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_BBOX_H                                                          */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the API of the optional exact bounding box computation routines.   */
+  /*                                                                       */
+#define FT_BBOX_H  <freetype/ftbbox.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_BEZIER_H                                                        */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    a small useful API to handle bezier arcs.  Note that you _must_    */
+  /*    include FT_FREETYPE_H or FT_IMAGE_H before this header.            */
+  /*                                                                       */
+#define FT_BEZIER_H  <freetype/ftbezier.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_CACHE_H                                                         */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the API of the optional FreeType 2 cache sub-system.               */
+  /*                                                                       */
+#define FT_CACHE_H  <freetype/ftcache.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_CACHE_IMAGE_H                                                   */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the `glyph image' API of the FreeType 2 cache sub-system.          */
+  /*                                                                       */
+  /*    It is used to define a cache for @FT_Glyph elements.  You can also */
+  /*    see the API defined in @FT_CACHE_SMALL_BITMAPS_H if you only need  */
+  /*    to store small glyph bitmaps, as it will use less memory.          */
+  /*                                                                       */
+#define FT_CACHE_IMAGE_H  <freetype/cache/ftcimage.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_CACHE_SMALL_BITMAPS_H                                           */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the `small bitmaps' API of the FreeType 2 cache sub-system.        */
+  /*                                                                       */
+  /*    It is used to define a cache for small glyph bitmaps in a          */
+  /*    relatively memory-efficient way.  You can also use the API defined */
+  /*    in @FT_CACHE_IMAGE_H if you want to cache arbitrary glyph images,  */
+  /*    including scalable outlines.                                       */
+  /*                                                                       */
+#define FT_CACHE_SMALL_BITMAPS_H  <freetype/cache/ftcsbits.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_MAC_H                                                           */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the Macintosh-specific FreeType 2 API. The latter is used to       */
+  /*    access fonts embedded in resource forks.                           */
+  /*                                                                       */
+  /*    This header file must be explicitly included by client             */
+  /*    applications compiled on the Mac (note that the base API still     */
+  /*    works though).                                                     */
+  /*                                                                       */
+#define FT_MAC_H  <freetype/ftmac.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_MULTIPLE_MASTERS_H                                              */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the optional multiple-masters management API of FreeType 2.        */
+  /*                                                                       */
+#define FT_MULTIPLE_MASTERS_H  <freetype/ftmm.h>
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_SFNT_NAMES_H                                                    */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A macro used in #include statements to name the file containing    */
+  /*    the optional FreeType 2 API used to access embedded `name' strings */
+  /*    in SFNT-based font formats (i.e. TrueType and OpenType).           */
+  /*                                                                       */
+#define FT_SFNT_NAMES_H  <freetype/ftsnames.h>
+
+  /* */
+
+#define FT_TRIGONOMETRY_H          <freetype/fttrigon.h>
+#define FT_SYNTHESIS_H             <freetype/ftsynth.h>
+
+#define FT_CACHE_MANAGER_H         <freetype/cache/ftcmanag.h>
+
+#define FT_CACHE_INTERNAL_LRU_H    <freetype/cache/ftlru.h>
+#define FT_CACHE_INTERNAL_GLYPH_H  <freetype/cache/ftcglyph.h>
+#define FT_CACHE_INTERNAL_CHUNK_H  <freetype/cache/ftcchunk.h>
+
+  /* now include internal headers definitions from <freetype/internal/...> */
+
+#define  FT_INTERNAL_INTERNAL_H    <freetype/internal/internal.h>
+#include FT_INTERNAL_INTERNAL_H
+
+
+#endif /* __FT2_BUILD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/config/ftmodule.h b/libraries/freetype-2.0.5/include/freetype/config/ftmodule.h
new file mode 100644 (file)
index 0000000..eb35a32
--- /dev/null
@@ -0,0 +1,12 @@
+FT_USE_MODULE(autohint_module_class)
+FT_USE_MODULE(cff_driver_class)
+FT_USE_MODULE(t1cid_driver_class)
+FT_USE_MODULE(pcf_driver_class)
+FT_USE_MODULE(psaux_module_class)
+FT_USE_MODULE(psnames_module_class)
+FT_USE_MODULE(ft_raster1_renderer_class)
+FT_USE_MODULE(sfnt_module_class)
+FT_USE_MODULE(ft_smooth_renderer_class)
+FT_USE_MODULE(tt_driver_class)
+FT_USE_MODULE(t1_driver_class)
+FT_USE_MODULE(winfnt_driver_class)
diff --git a/libraries/freetype-2.0.5/include/freetype/config/ftoption.h b/libraries/freetype-2.0.5/include/freetype/config/ftoption.h
new file mode 100644 (file)
index 0000000..b163312
--- /dev/null
@@ -0,0 +1,426 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftoption.h                                                             */
+/*                                                                         */
+/*    User-selectable configuration macros (specification only).           */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTOPTION_H__
+#define __FTOPTION_H__
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                 USER-SELECTABLE CONFIGURATION MACROS                  */
+  /*                                                                       */
+  /* These macros can be toggled by developers to enable or disable        */
+  /* certain aspects of FreeType.  This is a default file, where all major */
+  /* options are enabled.                                                  */
+  /*                                                                       */
+  /* Note that if some modifications are required for your build, we       */
+  /* advise you to put a modified copy of this file in your build          */
+  /* directory, rather than modifying it in-place.                         */
+  /*                                                                       */
+  /* The build directory is normally `freetype/builds/<system>' and        */
+  /* contains build or system-specific files that are included in          */
+  /* priority when building the library.                                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /**** G E N E R A L   F R E E T Y P E   2   C O N F I G U R A T I O N ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Convenience functions support                                         */
+  /*                                                                       */
+  /*   Some functions of the FreeType 2 API are provided as a convenience  */
+  /*   for client applications and developers. However,  they are not      */
+  /*   required to build and run the library itself.                       */
+  /*                                                                       */
+  /*   By defining this configuration macro, you'll disable the            */
+  /*   compilation of these functions at build time.  This can be useful   */
+  /*   to reduce the library's code size when you don't need any of        */
+  /*   these functions.                                                    */
+  /*                                                                       */
+  /*   All convenience functions are declared as such in their             */
+  /*   documentation.                                                      */
+  /*                                                                       */
+#undef FT_CONFIG_OPTION_NO_CONVENIENCE_FUNCS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Module errors                                                         */
+  /*                                                                       */
+  /*   If this macro is set (which is _not_ the default), the higher byte  */
+  /*   of an error code gives the module in which the error has occurred,  */
+  /*   while the lower byte is the real error code.                        */
+  /*                                                                       */
+  /*   Setting this macro makes sense for debugging purposes only, since   */
+  /*   it would break source compatibility of certain programs that use    */
+  /*   FreeType 2.                                                         */
+  /*                                                                       */
+  /*   More details can be found in the files ftmoderr.h and fterrors.h.   */
+  /*                                                                       */
+#undef  FT_CONFIG_OPTION_USE_MODULE_ERRORS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Alternate Glyph Image Format support                                  */
+  /*                                                                       */
+  /*   By default, the glyph images returned by the FreeType glyph loader  */
+  /*   can either be a pixmap or a vectorial outline defined through       */
+  /*   Bezier control points.  When defining the following configuration   */
+  /*   macro, some font drivers will be able to register alternate         */
+  /*   glyph image formats.                                                */
+  /*                                                                       */
+  /*   Unset this macro if you are sure that you will never use a font     */
+  /*   driver with an alternate glyph format; this will reduce the size of */
+  /*   the base layer code.                                                */
+  /*                                                                       */
+  /*   Note that a few Type 1 fonts, as well as Windows `vector' fonts     */
+  /*   use a vector `plotter' format that isn't supported when this        */
+  /*   macro is undefined.                                                 */
+  /*                                                                       */
+#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Glyph Postscript Names handling                                       */
+  /*                                                                       */
+  /*   By default, FreeType 2 is compiled with the `PSNames' module.  This */
+  /*   This module is in charge of converting a glyph name string into a   */
+  /*   Unicode value, or return a Macintosh standard glyph name for the    */
+  /*   use with the TrueType `post' table.                                 */
+  /*                                                                       */
+  /*   Undefine this macro if you do not want `PSNames' compiled in your   */
+  /*   build of FreeType.  This has the following effects:                 */
+  /*                                                                       */
+  /*   - The TrueType driver will provide its own set of glyph names,      */
+  /*     if you build it to support postscript names in the TrueType       */
+  /*     `post' table.                                                     */
+  /*                                                                       */
+  /*   - The Type 1 driver will not be able to synthetize a Unicode        */
+  /*     charmap out of the glyphs found in the fonts.                     */
+  /*                                                                       */
+  /*   You would normally undefine this configuration macro when building  */
+  /*   a version of FreeType that doesn't contain a Type 1 or CFF driver.  */
+  /*                                                                       */
+#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Postscript Names to Unicode Values support                            */
+  /*                                                                       */
+  /*   By default, FreeType 2 is built with the `PSNames' module compiled  */
+  /*   in.  Among other things, the module is used to convert a glyph name */
+  /*   into a Unicode value.  This is especially useful in order to        */
+  /*   synthetize on the fly a Unicode charmap from the CFF/Type 1 driver  */
+  /*   through a big table named the `Adobe Glyph List' (AGL).             */
+  /*                                                                       */
+  /*   Undefine this macro if you do not want the Adobe Glyph List         */
+  /*   compiled in your `PSNames' module.  The Type 1 driver will not be   */
+  /*   able to synthetize a Unicode charmap out of the glyphs found in the */
+  /*   fonts.                                                              */
+  /*                                                                       */
+#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Many compilers provide a non-ANSI 64-bit data type that can be used   */
+  /* by FreeType to speed up some computations.  However, this will create */
+  /* some problems when compiling the library in strict ANSI mode.         */
+  /*                                                                       */
+  /* For this reason, the use of 64-bit ints is normally disabled when     */
+  /* the __STDC__ macro is defined.  You can however disable this by       */
+  /* defining here the macro FT_CONFIG_OPTION_FORCE_INT64.                 */
+  /*                                                                       */
+  /* For most compilers, this will only create compilation warnings        */
+  /* when building the library.                                            */
+  /*                                                                       */
+  /* ObNote: The compiler-specific 64-bit integers are detected in the     */
+  /*         file "ftconfig.h" either statically, or through Autoconf      */
+  /*         on platforms that support it.                                 */
+  /*                                                                       */
+#define  FT_CONFIG_OPTION_FORCE_INT64
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DLL export compilation                                                */
+  /*                                                                       */
+  /*   When compiling FreeType as a DLL, some systems/compilers need a     */
+  /*   special keyword in front OR after the return type of function       */
+  /*   declarations.                                                       */
+  /*                                                                       */
+  /*   Two macros are used within the FreeType source code to define       */
+  /*   exported library functions: FT_EXPORT and FT_EXPORT_DEF.            */
+  /*                                                                       */
+  /*     FT_EXPORT( return_type )                                          */
+  /*                                                                       */
+  /*       is used in a function declaration, as in                        */
+  /*                                                                       */
+  /*         FT_EXPORT( FT_Error )                                         */
+  /*         FT_Init_FreeType( FT_Library*  alibrary );                    */
+  /*                                                                       */
+  /*                                                                       */
+  /*     FT_EXPORT_DEF( return_type )                                      */
+  /*                                                                       */
+  /*       is used in a function definition, as in                         */
+  /*                                                                       */
+  /*         FT_EXPORT_DEF( FT_Error )                                     */
+  /*         FT_Init_FreeType( FT_Library*  alibrary )                     */
+  /*         {                                                             */
+  /*           ... some code ...                                           */
+  /*           return FT_Err_Ok;                                           */
+  /*         }                                                             */
+  /*                                                                       */
+  /*   You can provide your own implementation of FT_EXPORT and            */
+  /*   FT_EXPORT_DEF here if you want.  If you leave them undefined, they  */
+  /*   will be later automatically defined as `extern return_type' to      */
+  /*   allow normal compilation.                                           */
+  /*                                                                       */
+#undef FT_EXPORT
+#undef FT_EXPORT_DEF
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Debug level                                                           */
+  /*                                                                       */
+  /*   FreeType can be compiled in debug or trace mode.  In debug mode,    */
+  /*   errors are reported through the `ftdebug' component.  In trace      */
+  /*   mode, additional messages are sent to the standard output during    */
+  /*   execution.                                                          */
+  /*                                                                       */
+  /*   Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode.     */
+  /*   Define FT_DEBUG_LEVEL_TRACE to build it in trace mode.              */
+  /*                                                                       */
+  /*   Don't define any of these macros to compile in `release' mode!      */
+  /*                                                                       */
+/* #define  FT_DEBUG_LEVEL_ERROR */
+/* #define  FT_DEBUG_LEVEL_TRACE */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Computation Algorithms                                                */
+  /*                                                                       */
+  /*   Used for debugging, this configuration macro should disappear       */
+  /*   soon.                                                               */
+  /*                                                                       */
+#undef  FT_CONFIG_OPTION_OLD_CALCS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The size in bytes of the render pool used by the scan-line converter  */
+  /* to do all of its work.                                                */
+  /*                                                                       */
+  /* This must be greater than 4kByte.                                     */
+  /*                                                                       */
+#define FT_RENDER_POOL_SIZE  32768L
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FT_MAX_MODULES                                                        */
+  /*                                                                       */
+  /*   The maximum number of modules that can be registered in a single    */
+  /*   FreeType library object.  16 is the default.                        */
+  /*                                                                       */
+#define FT_MAX_MODULES  16
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FT_MAX_EXTENSIONS                                                     */
+  /*                                                                       */
+  /*   The maximum number of extensions that can be registered in a single */
+  /*   font driver.  8 is the default.                                     */
+  /*                                                                       */
+  /*   If you don't know what this means, you certainly do not need to     */
+  /*   change this value.                                                  */
+  /*                                                                       */
+#define FT_MAX_EXTENSIONS  8
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****        S F N T   D R I V E R    C O N F I G U R A T I O N       ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support       */
+  /* embedded bitmaps in all formats using the SFNT module (namely         */
+  /* TrueType & OpenType).                                                 */
+  /*                                                                       */
+#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to    */
+  /* load and enumerate the glyph Postscript names in a TrueType or        */
+  /* OpenType file.                                                        */
+  /*                                                                       */
+  /* Note that when you do not compile the `PSNames' module by undefining  */
+  /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will   */
+  /* contain additional code used to read the PS Names table from a font.  */
+  /*                                                                       */
+  /* (By default, the module uses `PSNames' to extract glyph names.)       */
+  /*                                                                       */
+#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to       */
+  /* access the internal name table in a SFNT-based format like TrueType   */
+  /* or OpenType.  The name table contains various strings used to         */
+  /* describe the font, like family name, copyright, version, etc.  It     */
+  /* does not contain any glyph name though.                               */
+  /*                                                                       */
+  /* Accessing SFNT names is done through the functions declared in        */
+  /* `freetype/ftnames.h'.                                                 */
+  /*                                                                       */
+#define TT_CONFIG_OPTION_SFNT_NAMES
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****    T R U E T Y P E   D R I V E R    C O N F I G U R A T I O N   ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile   */
+  /* a bytecode interpreter in the TrueType driver.  Note that there are   */
+  /* important patent issues related to the use of the interpreter.        */
+  /*                                                                       */
+  /* By undefining this, you will only compile the code necessary to load  */
+  /* TrueType glyphs without hinting.                                      */
+  /*                                                                       */
+#undef  TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType    */
+  /* bytecode interpreter with a huge switch statement, rather than a call */
+  /* table.  This results in smaller and faster code for a number of       */
+  /* architectures.                                                        */
+  /*                                                                       */
+  /* Note however that on some compiler/processor combinations, undefining */
+  /* this macro will generate faster, though larger, code.                 */
+  /*                                                                       */
+#define TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****      T Y P E 1   D R I V E R    C O N F I G U R A T I O N       ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and       */
+  /* arrays in the Type 1 stream (see t1load.c).  A minimum of 4 is        */
+  /* required.                                                             */
+  /*                                                                       */
+#define T1_MAX_DICT_DEPTH  5
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine   */
+  /* calls during glyph loading.                                           */
+  /*                                                                       */
+#define T1_MAX_SUBRS_CALLS  16
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity.  A     */
+  /* minimum of 16 is required.                                            */
+  /*                                                                       */
+  /* The Chinese font MingTiEG-Medium (CNS 11643 character set) needs 256. */
+  /*                                                                       */
+#define T1_MAX_CHARSTRINGS_OPERANDS  256
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define T1_CONFIG_OPTION_DISABLE_HINTER if you want to generate a      */
+  /* driver with no hinter.  This can be useful to debug the parser.       */
+  /*                                                                       */
+#undef T1_CONFIG_OPTION_DISABLE_HINTER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define this configuration macro if you want to prevent the            */
+  /* compilation of `t1afm', which is in charge of reading Type 1 AFM      */
+  /* files into an existing face.  Note that if set, the T1 driver will be */
+  /* unable to produce kerning distances.                                  */
+  /*                                                                       */
+#undef T1_CONFIG_OPTION_NO_AFM
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define this configuration macro if you want to prevent the            */
+  /* compilation of the Multiple Masters font support in the Type 1        */
+  /* driver.                                                               */
+  /*                                                                       */
+#undef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+FT_END_HEADER
+
+
+#endif /* __FTOPTION_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/freetype.h b/libraries/freetype-2.0.5/include/freetype/freetype.h
new file mode 100644 (file)
index 0000000..41d6f60
--- /dev/null
@@ -0,0 +1,2619 @@
+/***************************************************************************/
+/*                                                                         */
+/*  freetype.h                                                             */
+/*                                                                         */
+/*    FreeType high-level API and common types (specification only).       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FREETYPE_H__
+#define __FREETYPE_H__
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The `raster' component duplicates some of the declarations in         */
+  /* freetype.h for stand-alone use if _FREETYPE_ isn't defined.           */
+  /*                                                                       */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The FREETYPE_MAJOR and FREETYPE_MINOR macros are used to version the  */
+  /* new FreeType design, which is able to host several kinds of font      */
+  /* drivers.  It starts at 2.0.                                           */
+  /*                                                                       */
+#define FREETYPE_MAJOR 2
+#define FREETYPE_MINOR 0
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_ERRORS_H
+#include FT_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /*                        B A S I C   T Y P E S                          */
+  /*                                                                       */
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    base_interface                                                     */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Base Interface                                                     */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    The FreeType 2 base font interface.                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This section describes the public high-level API of FreeType 2.    */
+  /*                                                                       */
+  /* <Order>                                                               */
+  /*    FT_Library                                                         */
+  /*    FT_Face                                                            */
+  /*    FT_Size                                                            */
+  /*    FT_GlyphSlot                                                       */
+  /*    FT_CharMap                                                         */
+  /*    FT_Encoding                                                        */
+  /*                                                                       */
+  /*    FT_FaceRec                                                         */
+  /*                                                                       */
+  /*    FT_FACE_FLAG_SCALABLE                                              */
+  /*    FT_FACE_FLAG_FIXED_SIZES                                           */
+  /*    FT_FACE_FLAG_FIXED_WIDTH                                           */
+  /*    FT_FACE_FLAG_HORIZONTAL                                            */
+  /*    FT_FACE_FLAG_VERTICAL                                              */
+  /*    FT_FACE_FLAG_SFNT                                                  */
+  /*    FT_FACE_FLAG_KERNING                                               */
+  /*    FT_FACE_FLAG_MULTIPLE_MASTERS                                      */
+  /*    FT_FACE_FLAG_GLYPH_NAMES                                           */
+  /*    FT_FACE_FLAG_EXTERNAL_STREAM                                       */
+  /*    FT_FACE_FLAG_FAST_GLYPHS                                           */
+  /*                                                                       */
+  /*    FT_STYLE_FLAG_BOLD                                                 */
+  /*    FT_STYLE_FLAG_ITALIC                                               */
+  /*                                                                       */
+  /*    FT_SizeRec                                                         */
+  /*    FT_Size_Metrics                                                    */
+  /*                                                                       */
+  /*    FT_GlyphSlotRec                                                    */
+  /*    FT_Glyph_Metrics                                                   */
+  /*    FT_SubGlyph                                                        */
+  /*                                                                       */
+  /*    FT_Bitmap_Size                                                     */
+  /*                                                                       */
+  /*    FT_Init_FreeType                                                   */
+  /*    FT_Done_FreeType                                                   */
+  /*                                                                       */
+  /*    FT_New_Face                                                        */
+  /*    FT_Done_Face                                                       */
+  /*    FT_New_Memory_Face                                                 */
+  /*    FT_Open_Face                                                       */
+  /*    FT_Open_Args                                                       */
+  /*    FT_Open_Flags                                                      */
+  /*    FT_Parameter                                                       */
+  /*    FT_Attach_File                                                     */
+  /*    FT_Attach_Stream                                                   */
+  /*                                                                       */
+  /*    FT_Set_Char_Size                                                   */
+  /*    FT_Set_Pixel_Sizes                                                 */
+  /*    FT_Set_Transform                                                   */
+  /*    FT_Load_Glyph                                                      */
+  /*    FT_Get_Char_Index                                                  */
+  /*    FT_Get_Name_Index                                                  */
+  /*    FT_Load_Char                                                       */
+  /*                                                                       */
+  /*    FT_LOAD_DEFAULT                                                    */
+  /*    FT_LOAD_RENDER                                                     */
+  /*    FT_LOAD_MONOCHROME                                                 */
+  /*    FT_LOAD_LINEAR_DESIGN                                              */
+  /*    FT_LOAD_NO_SCALE                                                   */
+  /*    FT_LOAD_NO_HINTING                                                 */
+  /*    FT_LOAD_NO_BITMAP                                                  */
+  /*    FT_LOAD_CROP_BITMAP                                                */
+  /*                                                                       */
+  /*    FT_LOAD_VERTICAL_LAYOUT                                            */
+  /*    FT_LOAD_IGNORE_TRANSFORM                                           */
+  /*    FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH                                */
+  /*    FT_LOAD_FORCE_AUTOHINT                                             */
+  /*    FT_LOAD_NO_RECURSE                                                 */
+  /*    FT_LOAD_PEDANTIC                                                   */
+  /*                                                                       */
+  /*    FT_Render_Glyph                                                    */
+  /*    FT_Render_Mode                                                     */
+  /*    FT_Get_Kerning                                                     */
+  /*    FT_Kerning_Mode                                                    */
+  /*    FT_Get_Glyph_Name                                                  */
+  /*                                                                       */
+  /*    FT_CharMapRec                                                      */
+  /*    FT_Select_Charmap                                                  */
+  /*    FT_Set_Charmap                                                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Glyph_Metrics                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model the metrics of a single glyph.  Note     */
+  /*    that values are expressed in 26.6 fractional pixel format or in    */
+  /*    font units, depending on context.                                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    width        :: The glyph's width.                                 */
+  /*                                                                       */
+  /*    height       :: The glyph's height.                                */
+  /*                                                                       */
+  /*    horiBearingX :: Horizontal left side bearing.                      */
+  /*                                                                       */
+  /*    horiBearingY :: Horizontal top side bearing.                       */
+  /*                                                                       */
+  /*    horiAdvance  :: Horizontal advance width.                          */
+  /*                                                                       */
+  /*    vertBearingX :: Vertical left side bearing.                        */
+  /*                                                                       */
+  /*    vertBearingY :: Vertical top side bearing.                         */
+  /*                                                                       */
+  /*    vertAdvance  :: Vertical advance height.                           */
+  /*                                                                       */
+  typedef struct  FT_Glyph_Metrics_
+  {
+    FT_Pos  width;         /* glyph width  */
+    FT_Pos  height;        /* glyph height */
+
+    FT_Pos  horiBearingX;  /* left side bearing in horizontal layouts */
+    FT_Pos  horiBearingY;  /* top side bearing in horizontal layouts  */
+    FT_Pos  horiAdvance;   /* advance width for horizontal layout     */
+
+    FT_Pos  vertBearingX;  /* left side bearing in vertical layouts */
+    FT_Pos  vertBearingY;  /* top side bearing in vertical layouts  */
+    FT_Pos  vertAdvance;   /* advance height for vertical layout    */
+
+  } FT_Glyph_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Bitmap_Size                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An extremely simple structure used to model the size of a bitmap   */
+  /*    strike (i.e., a bitmap instance of the font for a given            */
+  /*    resolution) in a fixed-size font face.  This is used for the       */
+  /*    `available_sizes' field of the FT_Face_Properties structure.       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    height :: The character height in pixels.                          */
+  /*                                                                       */
+  /*    width  :: The character width in pixels.                           */
+  /*                                                                       */
+  typedef struct  FT_Bitmap_Size_
+  {
+    FT_Short  height;
+    FT_Short  width;
+
+  } FT_Bitmap_Size;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /*                     O B J E C T   C L A S S E S                       */
+  /*                                                                       */
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Library                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a FreeType library instance.  Each `library' is        */
+  /*    completely independent from the others; it is the `root' of a set  */
+  /*    of objects like fonts, faces, sizes, etc.                          */
+  /*                                                                       */
+  /*    It also embeds a system object (see FT_System), as well as a       */
+  /*    scan-line converter object (see FT_Raster).                        */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Library objects are created through FT_Init_FreeType().            */
+  /*                                                                       */
+  typedef struct FT_LibraryRec_  *FT_Library;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Module                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given FreeType module object.  Each module can be a  */
+  /*    font driver, a renderer, or anything else that provides services   */
+  /*    to the formers.                                                    */
+  /*                                                                       */
+  typedef struct FT_ModuleRec_*  FT_Module;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Driver                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given FreeType font driver object.  Each font driver */
+  /*    is able to create faces, sizes, glyph slots, and charmaps from the */
+  /*    resources whose format it supports.                                */
+  /*                                                                       */
+  /*    A driver can support either bitmap, graymap, or scalable font      */
+  /*    formats.                                                           */
+  /*                                                                       */
+  typedef struct FT_DriverRec_*  FT_Driver;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Renderer                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given FreeType renderer.  A renderer is in charge of */
+  /*    converting a glyph image to a bitmap, when necessary.  Each        */
+  /*    supports a given glyph image format, and one or more target        */
+  /*    surface depths.                                                    */
+  /*                                                                       */
+  typedef struct FT_RendererRec_*  FT_Renderer;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Face                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given driver face object.  A face object contains    */
+  /*    all the instance and glyph independent data of a font file         */
+  /*    typeface.                                                          */
+  /*                                                                       */
+  /*    A face object is created from a resource object through the        */
+  /*    new_face() method of a given driver.                               */
+  /*                                                                       */
+  typedef struct FT_FaceRec_*  FT_Face;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Size                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given driver size object.  Such an object models the */
+  /*    _resolution_ AND _size_ dependent state of a given driver face     */
+  /*    size.                                                              */
+  /*                                                                       */
+  /*    A size object is always created from a given face object.  It is   */
+  /*    discarded automatically by its parent face.                        */
+  /*                                                                       */
+  typedef struct FT_SizeRec_*  FT_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_GlyphSlot                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given `glyph slot'.  A slot is a container where it  */
+  /*    is possible to load any of the glyphs contained within its parent  */
+  /*    face.                                                              */
+  /*                                                                       */
+  /*    A glyph slot is created from a given face object.  It is discarded */
+  /*    automatically by its parent face.                                  */
+  /*                                                                       */
+  typedef struct FT_GlyphSlotRec_*  FT_GlyphSlot;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_CharMap                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a given character map.  A charmap is used to translate */
+  /*    character codes in a given encoding into glyph indexes for its     */
+  /*    parent's face.  Some font formats may provide several charmaps per */
+  /*    font.                                                              */
+  /*                                                                       */
+  /*    A charmap is created from a given face object.  It is discarded    */
+  /*    automatically by its parent face.                                  */
+  /*                                                                       */
+  typedef struct FT_CharMapRec_*  FT_CharMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Macro>                                                               */
+  /*    FT_ENC_TAG                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This macro converts four letter tags into an unsigned long.        */
+  /*                                                                       */
+#ifndef FT_ENC_TAG
+#define FT_ENC_TAG( value, _x1, _x2, _x3, _x4 ) \
+        value = ( ( (unsigned long)_x1 << 24 ) | \
+                  ( (unsigned long)_x2 << 16 ) | \
+                  ( (unsigned long)_x3 << 8  ) | \
+                    (unsigned long)_x4         )
+#endif /* FT_ENC_TAG */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Encoding                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration used to specify encodings supported by charmaps.    */
+  /*    Used in the FT_Select_Charmap() API function.                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Because of 32-bit charcodes defined in Unicode (i.e., surrogates), */
+  /*    all character codes must be expressed as FT_Longs.                 */
+  /*                                                                       */
+  /*    Other encodings might be defined in the future.                    */
+  /*                                                                       */
+  typedef enum  FT_Encoding_
+  {
+    FT_ENC_TAG( ft_encoding_none, 0, 0, 0, 0 ),
+
+    FT_ENC_TAG( ft_encoding_symbol,  's', 'y', 'm', 'b' ),
+    FT_ENC_TAG( ft_encoding_unicode, 'u', 'n', 'i', 'c' ),
+    FT_ENC_TAG( ft_encoding_latin_2, 'l', 'a', 't', '2' ),
+    FT_ENC_TAG( ft_encoding_sjis,    's', 'j', 'i', 's' ),
+    FT_ENC_TAG( ft_encoding_gb2312,  'g', 'b', ' ', ' ' ),
+    FT_ENC_TAG( ft_encoding_big5,    'b', 'i', 'g', '5' ),
+    FT_ENC_TAG( ft_encoding_wansung, 'w', 'a', 'n', 's' ),
+    FT_ENC_TAG( ft_encoding_johab,   'j', 'o', 'h', 'a' ),
+
+    FT_ENC_TAG( ft_encoding_adobe_standard, 'A', 'D', 'O', 'B' ),
+    FT_ENC_TAG( ft_encoding_adobe_expert,   'A', 'D', 'B', 'E' ),
+    FT_ENC_TAG( ft_encoding_adobe_custom,   'A', 'D', 'B', 'C' ),
+
+    FT_ENC_TAG( ft_encoding_apple_roman, 'a', 'r', 'm', 'n' )
+
+  } FT_Encoding;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_CharMapRec                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The base charmap class.                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    face        :: A handle to the parent face object.                 */
+  /*                                                                       */
+  /*    encoding    :: A tag which identifies the charmap.  Use this with  */
+  /*                   FT_Select_Charmap().                                */
+  /*                                                                       */
+  /*    platform_id :: An ID number describing the platform for the        */
+  /*                   following encoding ID.  This comes directly from    */
+  /*                   the TrueType specification and should be emulated   */
+  /*                   for other formats.                                  */
+  /*                                                                       */
+  /*    encoding_id :: A platform specific encoding number.  This also     */
+  /*                   comes from the TrueType specification and should be */
+  /*                   emulated similarly.                                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    We STRONGLY recommmend emulating a Unicode charmap for drivers     */
+  /*    that do not support TrueType or OpenType.                          */
+  /*                                                                       */
+  typedef struct  FT_CharMapRec_
+  {
+    FT_Face      face;
+    FT_Encoding  encoding;
+    FT_UShort    platform_id;
+    FT_UShort    encoding_id;
+
+  } FT_CharMapRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /*                 B A S E   O B J E C T   C L A S S E S                 */
+  /*                                                                       */
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Face_Internal                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An opaque handle to an FT_Face_InternalRec structure, used to      */
+  /*    model private data of a given FT_Face object.                      */
+  /*                                                                       */
+  /*    This field might change between releases of FreeType 2 and are     */
+  /*    not generally available to client applications.                    */
+  /*                                                                       */
+  typedef struct FT_Face_InternalRec_*  FT_Face_Internal;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       FreeType base face class                        */
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_FaceRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    FreeType root face class structure.  A face object models the      */
+  /*    resolution and point-size independent data found in a font file.   */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_faces           :: In the case where the face is located in a  */
+  /*                           collection (i.e., a resource which embeds   */
+  /*                           several faces), this is the total number of */
+  /*                           faces found in the resource.  1 by default. */
+  /*                                                                       */
+  /*    face_index          :: The index of the face in its resource.      */
+  /*                           Usually, this is 0 for all normal font      */
+  /*                           formats.  It can be more in the case of     */
+  /*                           collections (which embed several fonts in a */
+  /*                           single resource/file).                      */
+  /*                                                                       */
+  /*    face_flags          :: A set of bit flags that give important      */
+  /*                           information about the face; see the         */
+  /*                           FT_FACE_FLAG_XXX macros for details.        */
+  /*                                                                       */
+  /*    style_flags         :: A set of bit flags indicating the style of  */
+  /*                           the face (i.e., italic, bold, underline,    */
+  /*                           etc).                                       */
+  /*                                                                       */
+  /*    num_glyphs          :: The total number of glyphs in the face.     */
+  /*                                                                       */
+  /*    family_name         :: The face's family name.  This is an ASCII   */
+  /*                           string, usually in English, which describes */
+  /*                           the typeface's family (like `Times New      */
+  /*                           Roman', `Bodoni', `Garamond', etc).  This   */
+  /*                           is a least common denominator used to list  */
+  /*                           fonts.  Some formats (TrueType & OpenType)  */
+  /*                           provide localized and Unicode versions of   */
+  /*                           this string.  Applications should use the   */
+  /*                           format specific interface to access them.   */
+  /*                                                                       */
+  /*    style_name          :: The face's style name.  This is an ASCII    */
+  /*                           string, usually in English, which describes */
+  /*                           the typeface's style (like `Italic',        */
+  /*                           `Bold', `Condensed', etc).  Not all font    */
+  /*                           formats provide a style name, so this field */
+  /*                           is optional, and can be set to NULL.  As    */
+  /*                           for `family_name', some formats provide     */
+  /*                           localized/Unicode versions of this string.  */
+  /*                           Applications should use the format specific */
+  /*                           interface to access them.                   */
+  /*                                                                       */
+  /*    num_fixed_sizes     :: The number of fixed sizes available in this */
+  /*                           face.  This should be set to 0 for scalable */
+  /*                           fonts, unless its resource includes a       */
+  /*                           complete set of glyphs (called a `strike')  */
+  /*                           for the specified size.                     */
+  /*                                                                       */
+  /*    available_sizes     :: An array of sizes specifying the available  */
+  /*                           bitmap/graymap sizes that are contained in  */
+  /*                           in the font resource.  Should be set to     */
+  /*                           NULL if the field `num_fixed_sizes' is set  */
+  /*                           to 0.                                       */
+  /*                                                                       */
+  /*    num_charmaps        :: The total number of character maps in the   */
+  /*                           face.                                       */
+  /*                                                                       */
+  /*    charmaps            :: A table of pointers to the face's charmaps. */
+  /*                           Used to scan the list of available charmaps */
+  /*                           -- this table might change after a call to  */
+  /*                           FT_Attach_File/Stream (e.g. when used to    */
+  /*                           hook an additional encoding/CMap to the     */
+  /*                           face object).                               */
+  /*                                                                       */
+  /*    generic             :: A field reserved for client uses.  See the  */
+  /*                           FT_Generic type description.                */
+  /*                                                                       */
+  /*    bbox                :: The font bounding box.  Coordinates are     */
+  /*                           expressed in font units (see units_per_EM). */
+  /*                           The box is large enough to contain any      */
+  /*                           glyph from the font.  Thus, bbox.yMax can   */
+  /*                           be seen as the `maximal ascender',          */
+  /*                           bbox.yMin as the `minimal descender', and   */
+  /*                           the maximal glyph width is given by         */
+  /*                           `bbox.xMax-bbox.xMin' (not to be confused   */
+  /*                           with the maximal _advance_width_).  Only    */
+  /*                           relevant for scalable formats.              */
+  /*                                                                       */
+  /*    units_per_EM        :: The number of font units per EM square for  */
+  /*                           this face.  This is typically 2048 for      */
+  /*                           TrueType fonts, 1000 for Type1 fonts, and   */
+  /*                           should be set to the (unrealistic) value 1  */
+  /*                           for fixed-sizes fonts.  Only relevant for   */
+  /*                           scalable formats.                           */
+  /*                                                                       */
+  /*    ascender            :: The face's ascender is the vertical         */
+  /*                           distance from the baseline to the topmost   */
+  /*                           point of any glyph in the face.  This       */
+  /*                           field's value is positive, expressed in     */
+  /*                           font units.  Some font designs use a value  */
+  /*                           different from `bbox.yMax'.  Only relevant  */
+  /*                           for scalable formats.                       */
+  /*                                                                       */
+  /*    descender           :: The face's descender is the vertical        */
+  /*                           distance from the baseline to the           */
+  /*                           bottommost point of any glyph in the face.  */
+  /*                           This field's value is positive, expressed   */
+  /*                           in font units.  Some font designs use a     */
+  /*                           value different from `-bbox.yMin'.  Only    */
+  /*                           relevant for scalable formats.              */
+  /*                                                                       */
+  /*    height              :: The face's height is the vertical distance  */
+  /*                           from one baseline to the next when writing  */
+  /*                           several lines of text.  Its value is always */
+  /*                           positive, expressed in font units.  The     */
+  /*                           value can be computed as                    */
+  /*                           `ascender+descender+line_gap' where the     */
+  /*                           value of `line_gap' is also called          */
+  /*                           `external leading'.  Only relevant for      */
+  /*                           scalable formats.                           */
+  /*                                                                       */
+  /*    max_advance_width   :: The maximal advance width, in font units,   */
+  /*                           for all glyphs in this face.  This can be   */
+  /*                           used to make word wrapping computations     */
+  /*                           faster.  Only relevant for scalable         */
+  /*                           formats.                                    */
+  /*                                                                       */
+  /*    max_advance_height  :: The maximal advance height, in font units,  */
+  /*                           for all glyphs in this face.  This is only  */
+  /*                           relevant for vertical layouts, and should   */
+  /*                           be set to the `height' for fonts that do    */
+  /*                           not provide vertical metrics.  Only         */
+  /*                           relevant for scalable formats.              */
+  /*                                                                       */
+  /*    underline_position  :: The position, in font units, of the         */
+  /*                           underline line for this face.  It's the     */
+  /*                           center of the underlining stem.  Only       */
+  /*                           relevant for scalable formats.              */
+  /*                                                                       */
+  /*    underline_thickness :: The thickness, in font units, of the        */
+  /*                           underline for this face.  Only relevant for */
+  /*                           scalable formats.                           */
+  /*                                                                       */
+  /*    driver              :: A handle to the face's parent driver        */
+  /*                           object.                                     */
+  /*                                                                       */
+  /*    memory              :: A handle to the face's parent memory        */
+  /*                           object.  Used for the allocation of         */
+  /*                           subsequent objects.                         */
+  /*                                                                       */
+  /*    stream              :: A handle to the face's stream.              */
+  /*                                                                       */
+  /*    glyph               :: The face's associated glyph slot(s).  This  */
+  /*                           object is created automatically with a new  */
+  /*                           face object.  However, certain kinds of     */
+  /*                           applications (mainly tools like converters) */
+  /*                           can need more than one slot to ease their   */
+  /*                           task.                                       */
+  /*                                                                       */
+  /*    sizes_list          :: The list of child sizes for this face.      */
+  /*                                                                       */
+  /*    internal            :: A pointer to internal fields of the face    */
+  /*                           object.  These fields can change freely     */
+  /*                           between releases of FreeType and are not    */
+  /*                           publicly available.                         */
+  /*                                                                       */
+  typedef struct  FT_FaceRec_
+  {
+    FT_Long           num_faces;
+    FT_Long           face_index;
+
+    FT_Long           face_flags;
+    FT_Long           style_flags;
+
+    FT_Long           num_glyphs;
+
+    FT_String*        family_name;
+    FT_String*        style_name;
+
+    FT_Int            num_fixed_sizes;
+    FT_Bitmap_Size*   available_sizes;
+
+    FT_Int            num_charmaps;
+    FT_CharMap*       charmaps;
+
+    FT_Generic        generic;
+
+    /*# the following are only relevant to scalable outlines */
+    FT_BBox           bbox;
+
+    FT_UShort         units_per_EM;
+    FT_Short          ascender;
+    FT_Short          descender;
+    FT_Short          height;
+
+    FT_Short          max_advance_width;
+    FT_Short          max_advance_height;
+
+    FT_Short          underline_position;
+    FT_Short          underline_thickness;
+
+    FT_GlyphSlot      glyph;
+    FT_Size           size;
+    FT_CharMap        charmap;
+
+    /*@private begin */
+
+    FT_Driver         driver;
+    FT_Memory         memory;
+    FT_Stream         stream;
+
+    FT_ListRec        sizes_list;
+
+    FT_Generic        autohint;
+    void*             extensions;
+
+    FT_Face_Internal  internal;
+
+    /*@private end */
+
+  } FT_FaceRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_SCALABLE                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face provides  */
+  /*    vectorial outlines (i.e., TrueType or Type1).  This doesn't        */
+  /*    prevent embedding of bitmap strikes though, i.e., a given face can */
+  /*    have both this bit set, and a `num_fixed_sizes' property > 0.      */
+  /*                                                                       */
+#define FT_FACE_FLAG_SCALABLE  1
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_FIXED_SIZES                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face contains  */
+  /*    `fixed sizes', i.e., bitmap strikes for some given pixel sizes.    */
+  /*    See the `num_fixed_sizes' and `available_sizes' face properties    */
+  /*    for more information.                                              */
+  /*                                                                       */
+#define FT_FACE_FLAG_FIXED_SIZES  2
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_FIXED_WIDTH                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face contains  */
+  /*    fixed-width characters (like Courier, Lucida, MonoType, etc.).     */
+  /*                                                                       */
+#define FT_FACE_FLAG_FIXED_WIDTH  4
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_SFNT                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face uses the  */
+  /*    `sfnt' storage fomat.  For now, this means TrueType or OpenType.   */
+  /*                                                                       */
+#define FT_FACE_FLAG_SFNT  8
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_HORIZONTAL                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face contains  */
+  /*    horizontal glyph metrics.  This should be set for all common       */
+  /*    formats, but who knows.                                            */
+  /*                                                                       */
+#define FT_FACE_FLAG_HORIZONTAL  0x10
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_VERTICAL                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face contains  */
+  /*    vertical glyph metrics.  If not set, the glyph loader will         */
+  /*    synthetize vertical metrics itself to help display vertical text   */
+  /*    correctly.                                                         */
+  /*                                                                       */
+#define FT_FACE_FLAG_VERTICAL  0x20
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_KERNING                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face contains  */
+  /*    kerning information.  When set, this information can be retrieved  */
+  /*    through the function FT_Get_Kerning().  Note that when unset, this */
+  /*    function will always return the kerning vector (0,0).              */
+  /*                                                                       */
+#define FT_FACE_FLAG_KERNING  0x40
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_FAST_GLYPHS                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that the glyphs in a given  */
+  /*    font can be retrieved very quickly, and that a glyph cache is thus */
+  /*    not necessary for any of its child size objects.                   */
+  /*                                                                       */
+  /*    This flag should really be set for fixed-size formats like FNT,    */
+  /*    where each glyph bitmap is available directly in binary form       */
+  /*    without any kind of compression.                                   */
+  /*                                                                       */
+#define FT_FACE_FLAG_FAST_GLYPHS  0x80
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_MULTIPLE_MASTERS                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that the font contains      */
+  /*    multiple masters and is capable of interpolating between them.     */
+  /*                                                                       */
+#define FT_FACE_FLAG_MULTIPLE_MASTERS  0x100
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_GLYPH_NAMES                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that the font contains      */
+  /*    glyph names that can be retrieved through FT_Get_Glyph_Name().     */
+  /*                                                                       */
+#define FT_FACE_FLAG_GLYPH_NAMES  0x200
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_FACE_FLAG_EXTERNAL_STREAM                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This bit field is used internally by FreeType to indicate that     */
+  /*    a face's stream was provided by the client application and should  */
+  /*    not be destroyed by FT_Done_Face().                                */
+  /*                                                                       */
+#define FT_FACE_FLAG_EXTERNAL_STREAM  0x4000
+
+
+  /* */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro: FT_HAS_HORIZONTAL (face)                                      */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   A macro that returns true whenever a face object contains           */
+  /*   horizontal metrics (this is true for all font formats though).      */
+  /*                                                                       */
+  /* @also:                                                                */
+  /*   @FT_HAS_VERTICAL can be used to check for vertical metrics.         */
+  /*                                                                       */
+#define FT_HAS_HORIZONTAL( face ) \
+          ( face->face_flags & FT_FACE_FLAG_HORIZONTAL )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro: FT_HAS_VERTICAL (face)                                        */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   A macro that returns true whenever a face object contains vertical  */
+  /*   metrics.                                                            */
+  /*                                                                       */
+#define FT_HAS_VERTICAL( face ) \
+          ( face->face_flags & FT_FACE_FLAG_VERTICAL )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro: FT_HAS_KERNING (face)                                         */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   A macro that returns true whenever a face object contains kerning   */
+  /*   data that can be accessed with @FT_Get_Kerning.                     */
+  /*                                                                       */
+#define FT_HAS_KERNING( face ) \
+          ( face->face_flags & FT_FACE_FLAG_KERNING )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro: FT_IS_SCALABLE (face)                                         */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   A macro that returns true whenever a face object contains a         */
+  /*   scalable font face (true for TrueType, Type 1, CID, and             */
+  /*   OpenType/CFF font formats.                                          */
+  /*                                                                       */
+#define FT_IS_SCALABLE( face ) \
+          ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro: FT_IS_SFNT (face)                                             */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   A macro that returns true whenever a face object contains a font    */
+  /*   whose format is based on the SFNT storage scheme.  This usually     */
+  /*   means: TrueType fonts, OpenType fonts, as well as SFNT-based        */
+  /*   embedded bitmap fonts.                                              */
+  /*                                                                       */
+  /*   If this macro is true, all functions defined in @FT_SFNT_NAMES_H    */
+  /*   and @FT_TRUETYPE_TABLES_H are available.                            */
+  /*                                                                       */
+#define FT_IS_SFNT( face ) \
+          ( face->face_flags & FT_FACE_FLAG_SFNT )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro: FT_IS_FIXED_WIDTH (face)                                      */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   A macro that returns true whenever a face object contains a font    */
+  /*   face that contains fixed-width (or "monospace", "fixed-pitch",      */
+  /*   etc.) glyphs.                                                       */
+  /*                                                                       */
+#define FT_IS_FIXED_WIDTH( face ) \
+          ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro: FT_IS_FIXED_SIZES (face)                                      */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   A macro that returns true whenever a face object contains some      */
+  /*   embedded bitmaps.  See the `fixed_sizes' field of the @FT_FaceRec   */
+  /*   structure.                                                          */
+  /*                                                                       */
+#define FT_HAS_FIXED_SIZES( face ) \
+          ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
+
+
+   /* */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro: FT_HAS_FAST_GLYPHS (face)                                     */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   XXX                                                                 */
+  /*                                                                       */
+#define FT_HAS_FAST_GLYPHS( face ) \
+          ( face->face_flags & FT_FACE_FLAG_FAST_GLYPHS )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro: FT_HAS_GLYPH_NAMES (face)                                     */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   A macro that returns true whenever a face object contains some      */
+  /*   glyph names that can be accessed through @FT_Get_Glyph_Names.       */
+  /*                                                                       */
+#define FT_HAS_GLYPH_NAMES( face ) \
+          ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro: FT_HAS_MULTIPLE_MASTERS (face)                                */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   A macro that returns true whenever a face object contains some      */
+  /*   multiple masters.  The functions provided by                        */
+  /*   @FT_MULTIPLE_MASTERS_H are then available to choose the exact       */
+  /*   design you want.                                                    */
+  /*                                                                       */
+#define FT_HAS_MULTIPLE_MASTERS( face ) \
+          ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_STYLE_FLAG_ITALIC                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face is        */
+  /*    italicized.                                                        */
+  /*                                                                       */
+#define FT_STYLE_FLAG_ITALIC  1
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_STYLE_FLAG_BOLD                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used to indicate that a given face is        */
+  /*    emboldened.                                                        */
+  /*                                                                       */
+#define FT_STYLE_FLAG_BOLD  2
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Size_Internal                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An opaque handle to an FT_Size_InternalRec structure, used to      */
+  /*    model private data of a given FT_Size object.                      */
+  /*                                                                       */
+  typedef struct FT_Size_InternalRec_*  FT_Size_Internal;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                    FreeType base size metrics                         */
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Size_Metrics                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The size metrics structure returned scaled important distances for */
+  /*    a given size object.                                               */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    x_ppem       :: The character width, expressed in integer pixels.  */
+  /*                    This is the width of the EM square expressed in    */
+  /*                    pixels, hence the term `ppem' (pixels per EM).     */
+  /*                                                                       */
+  /*    y_ppem       :: The character height, expressed in integer pixels. */
+  /*                    This is the height of the EM square expressed in   */
+  /*                    pixels, hence the term `ppem' (pixels per EM).     */
+  /*                                                                       */
+  /*    x_scale      :: A simple 16.16 fixed point format coefficient used */
+  /*                    to scale horizontal distances expressed in font    */
+  /*                    units to fractional (26.6) pixel coordinates.      */
+  /*                                                                       */
+  /*    y_scale      :: A simple 16.16 fixed point format coefficient used */
+  /*                    to scale vertical distances expressed in font      */
+  /*                    units to fractional (26.6) pixel coordinates.      */
+  /*                                                                       */
+  /*    ascender     :: The ascender, expressed in 26.6 fixed point        */
+  /*                    pixels.  Always positive.                          */
+  /*                                                                       */
+  /*    descender    :: The descender, expressed in 26.6 fixed point       */
+  /*                    pixels.  Always positive.                          */
+  /*                                                                       */
+  /*    height       :: The text height, expressed in 26.6 fixed point     */
+  /*                    pixels.  Always positive.                          */
+  /*                                                                       */
+  /*    max_advance  :: Maximum horizontal advance, expressed in 26.6      */
+  /*                    fixed point pixels.  Always positive.              */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The values of `ascender', `descender', and `height' are only the   */
+  /*    scaled versions of `face->ascender', `face->descender', and        */
+  /*    `face->height'.                                                    */
+  /*                                                                       */
+  /*    Unfortunately, due to glyph hinting, these values might not be     */
+  /*    exact for certain fonts, they thus must be treated as unreliable   */
+  /*    with an error margin of at least one pixel!                        */
+  /*                                                                       */
+  /*    Indeed, the only way to get the exact pixel ascender and descender */
+  /*    is to render _all_ glyphs.  As this would be a definite            */
+  /*    performance hit, it is up to client applications to perform such   */
+  /*    computations.                                                      */
+  /*                                                                       */
+  typedef struct  FT_Size_Metrics_
+  {
+    FT_UShort  x_ppem;      /* horizontal pixels per EM               */
+    FT_UShort  y_ppem;      /* vertical pixels per EM                 */
+
+    FT_Fixed   x_scale;     /* two scales used to convert font units  */
+    FT_Fixed   y_scale;     /* to 26.6 frac. pixel coordinates..      */
+
+    FT_Pos     ascender;    /* ascender in 26.6 frac. pixels          */
+    FT_Pos     descender;   /* descender in 26.6 frac. pixels         */
+    FT_Pos     height;      /* text height in 26.6 frac. pixels       */
+    FT_Pos     max_advance; /* max horizontal advance, in 26.6 pixels */
+
+  } FT_Size_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       FreeType base size class                        */
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_SizeRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    FreeType root size class structure.  A size object models the      */
+  /*    resolution and pointsize dependent data of a given face.           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    face    :: Handle to the parent face object.                       */
+  /*                                                                       */
+  /*    generic :: A typeless pointer, which is unused by the FreeType     */
+  /*               library or any of its drivers.  It can be used by       */
+  /*               client applications to link their own data to each size */
+  /*               object.                                                 */
+  /*                                                                       */
+  /*    metrics :: Metrics for this size object.  This field is read-only. */
+  /*                                                                       */
+  typedef struct  FT_SizeRec_
+  {
+    FT_Face           face;      /* parent face object              */
+    FT_Generic        generic;   /* generic pointer for client uses */
+    FT_Size_Metrics   metrics;   /* size metrics                    */
+    FT_Size_Internal  internal;
+
+  } FT_SizeRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_SubGlyph                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The subglyph structure is an internal object used to describe      */
+  /*    subglyphs (for example, in the case of composites).                */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The subglyph implementation is not part of the high-level API,     */
+  /*    hence the forward structure declaration.                           */
+  /*                                                                       */
+  typedef struct FT_SubGlyph_  FT_SubGlyph;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Slot_Internal                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An opaque handle to an FT_Slot_InternalRec structure, used to      */
+  /*    model private data of a given FT_GlyphSlot object.                 */
+  /*                                                                       */
+  typedef struct FT_Slot_InternalRec_*  FT_Slot_Internal;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                  FreeType Glyph Slot base class                       */
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_GlyphSlotRec                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    FreeType root glyph slot class structure.  A glyph slot is a       */
+  /*    container where individual glyphs can be loaded, be they           */
+  /*    vectorial or bitmap/graymaps.                                      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    library           :: A handle to the FreeType library instance     */
+  /*                         this slot belongs to.                         */
+  /*                                                                       */
+  /*    face              :: A handle to the parent face object.           */
+  /*                                                                       */
+  /*    next              :: In some cases (like some font tools), several */
+  /*                         glyph slots per face object can be a good     */
+  /*                         thing.  As this is rare, the glyph slots are  */
+  /*                         listed through a direct, single-linked list   */
+  /*                         using its `next' field.                       */
+  /*                                                                       */
+  /*    generic           :: A typeless pointer which is unused by the     */
+  /*                         FreeType library or any of its drivers.  It   */
+  /*                         can be used by client applications to link    */
+  /*                         their own data to each glyph slot object.     */
+  /*                                                                       */
+  /*    metrics           :: The metrics of the last loaded glyph in the   */
+  /*                         slot.  The returned values depend on the last */
+  /*                         load flags (see the FT_Load_Glyph() API       */
+  /*                         function) and can be expressed either in 26.6 */
+  /*                         fractional pixels or font units.              */
+  /*                                                                       */
+  /*                         Note that even when the glyph image is        */
+  /*                         transformed, the metrics are not.             */
+  /*                                                                       */
+  /*    linearHoriAdvance :: For scalable formats only, this field holds   */
+  /*                         the linearly scaled horizontal advance width  */
+  /*                         for the glyph (i.e. the scaled and unhinted   */
+  /*                         value of the hori advance).  This can be      */
+  /*                         important to perform correct WYSIWYG layout.  */
+  /*                                                                       */
+  /*                         Note that this value is expressed by default  */
+  /*                         in 16.16 pixels. However, when the glyph is   */
+  /*                         loaded with the FT_LOAD_LINEAR_DESIGN flag,   */
+  /*                         this field contains simply the value of the   */
+  /*                         advance in original font units.               */
+  /*                                                                       */
+  /*    linearVertAdvance :: For scalable formats only, this field holds   */
+  /*                         the linearly scaled vertical advance height   */
+  /*                         for the glyph.  See linearHoriAdvance for     */
+  /*                         comments.                                     */
+  /*                                                                       */
+  /*    advance           :: This is the transformed advance width for the */
+  /*                         glyph.                                        */
+  /*                                                                       */
+  /*    format            :: This field indicates the format of the image  */
+  /*                         contained in the glyph slot.  Typically       */
+  /*                         ft_glyph_format_bitmap,                       */
+  /*                         ft_glyph_format_outline, and                  */
+  /*                         ft_glyph_format_composite, but others are     */
+  /*                         possible.                                     */
+  /*                                                                       */
+  /*    bitmap            :: This field is used as a bitmap descriptor     */
+  /*                         when the slot format is                       */
+  /*                         ft_glyph_format_bitmap.  Note that the        */
+  /*                         address and content of the bitmap buffer can  */
+  /*                         change between calls of FT_Load_Glyph() and a */
+  /*                         few other functions.                          */
+  /*                                                                       */
+  /*    bitmap_left       :: This is the bitmap's left bearing expressed   */
+  /*                         in integer pixels.  Of course, this is only   */
+  /*                         valid if the format is                        */
+  /*                         ft_glyph_format_bitmap.                       */
+  /*                                                                       */
+  /*    bitmap_top        :: This is the bitmap's top bearing expressed in */
+  /*                         integer pixels.  Remember that this is the    */
+  /*                         distance from the baseline to the top-most    */
+  /*                         glyph scanline, upwards y-coordinates being   */
+  /*                         *positive*.                                   */
+  /*                                                                       */
+  /*    outline           :: The outline descriptor for the current glyph  */
+  /*                         image if its format is                        */
+  /*                         ft_glyph_bitmap_outline.                      */
+  /*                                                                       */
+  /*    num_subglyphs     :: The number of subglyphs in a composite glyph. */
+  /*                         This format is only valid for the composite   */
+  /*                         glyph format, that should normally only be    */
+  /*                         loaded with the FT_LOAD_NO_RECURSE flag.      */
+  /*                                                                       */
+  /*    subglyphs         :: An array of subglyph descriptors for          */
+  /*                         composite glyphs.  There are `num_subglyphs'  */
+  /*                         elements in there.                            */
+  /*                                                                       */
+  /*    control_data      :: Certain font drivers can also return the      */
+  /*                         control data for a given glyph image (e.g.    */
+  /*                         TrueType bytecode, Type 1 charstrings, etc.). */
+  /*                         This field is a pointer to such data.         */
+  /*                                                                       */
+  /*    control_len       :: This is the length in bytes of the control    */
+  /*                         data.                                         */
+  /*                                                                       */
+  /*    other             :: Really wicked formats can use this pointer to */
+  /*                         present their own glyph image to client apps. */
+  /*                         Note that the app will need to know about the */
+  /*                         image format.                                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If @FT_Load_Glyph() is called with default flags (see              */
+  /*    @FT_LOAD_DEFAULT ) the glyph image is loaded in the glyph slot in  */
+  /*    its native format (e.g. a vectorial outline for TrueType and       */
+  /*    Type 1 formats).                                                   */
+  /*                                                                       */
+  /*    This image can later be converted into a bitmap by calling         */
+  /*    FT_Render_Glyph().  This function finds the current renderer for   */
+  /*    the native image's format then invokes it.                         */
+  /*                                                                       */
+  /*    The renderer is in charge of transforming the native image through */
+  /*    the slot's face transformation fields, then convert it into a      */
+  /*    bitmap that is returned in `slot->bitmap'.                         */
+  /*                                                                       */
+  /*    Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */
+  /*    to specify the position of the bitmap relative to the current pen  */
+  /*    position (e.g. coordinates [0,0] on the baseline).  Of course,     */
+  /*    `slot->format' is also changed to `ft_glyph_format_bitmap' .       */
+  /*                                                                       */
+  typedef struct  FT_GlyphSlotRec_
+  {
+    FT_Library        library;
+    FT_Face           face;
+    FT_GlyphSlot      next;
+    FT_UInt           flags;
+    FT_Generic        generic;
+
+    FT_Glyph_Metrics  metrics;
+    FT_Fixed          linearHoriAdvance;
+    FT_Fixed          linearVertAdvance;
+    FT_Vector         advance;
+
+    FT_Glyph_Format   format;
+
+    FT_Bitmap         bitmap;
+    FT_Int            bitmap_left;
+    FT_Int            bitmap_top;
+
+    FT_Outline        outline;
+
+    FT_UInt           num_subglyphs;
+    FT_SubGlyph*      subglyphs;
+
+    void*             control_data;
+    long              control_len;
+
+    void*             other;
+
+    FT_Slot_Internal  internal;
+
+  } FT_GlyphSlotRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /*                         F U N C T I O N S                             */
+  /*                                                                       */
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Init_FreeType                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a new FreeType library object.  The set of drivers     */
+  /*    that are registered by this function is determined at build time.  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    alibrary :: A handle to a new library object.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Init_FreeType( FT_Library  *alibrary );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_FreeType                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given FreeType library object and all of its childs,    */
+  /*    including resources, drivers, faces, sizes, etc.                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the target library object.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Done_FreeType( FT_Library  library );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Open_Flags                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration used to list the bit flags used within the          */
+  /*    `flags' field of the @FT_Open_Args structure.                      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_open_memory   :: This is a memory-based stream.                 */
+  /*                                                                       */
+  /*    ft_open_stream   :: Copy the stream from the `stream' field.       */
+  /*                                                                       */
+  /*    ft_open_pathname :: Create a new input stream from a C pathname.   */
+  /*                                                                       */
+  /*    ft_open_driver   :: Use the `driver' field.                        */
+  /*                                                                       */
+  /*    ft_open_params   :: Use the `num_params' & `params' field.         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The `ft_open_memory', `ft_open_stream', and `ft_open_pathname'     */
+  /*    flags are mutually exclusive.                                      */
+  /*                                                                       */
+  typedef enum
+  {
+    ft_open_memory   = 1,
+    ft_open_stream   = 2,
+    ft_open_pathname = 4,
+    ft_open_driver   = 8,
+    ft_open_params   = 16
+
+  } FT_Open_Flags;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Parameter                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to pass more or less generic parameters    */
+  /*    to FT_Open_Face().                                                 */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    tag  :: A 4-byte identification tag.                               */
+  /*                                                                       */
+  /*    data :: A pointer to the parameter data.                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The id and function of parameters are driver-specific.             */
+  /*                                                                       */
+  typedef struct  FT_Parameter_
+  {
+    FT_ULong    tag;
+    FT_Pointer  data;
+
+  } FT_Parameter;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Open_Args                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to indicate how to open a new font file/stream.   */
+  /*    A pointer to such a structure can be used as a parameter for the   */
+  /*    functions @FT_Open_Face() & @FT_Attach_Stream().                   */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    flags       :: A set of bit flags indicating how to use the        */
+  /*                   structure.                                          */
+  /*                                                                       */
+  /*    memory_base :: The first byte of the file in memory.               */
+  /*                                                                       */
+  /*    memory_size :: The size in bytes of the file in memory.            */
+  /*                                                                       */
+  /*    pathname    :: A pointer to an 8-bit file pathname.                */
+  /*                                                                       */
+  /*    stream      :: A handle to a source stream object.                 */
+  /*                                                                       */
+  /*    driver      :: This field is exclusively used by FT_Open_Face();   */
+  /*                   it simply specifies the font driver to use to open  */
+  /*                   the face.  If set to 0, FreeType will try to load   */
+  /*                   the face with each one of the drivers in its list.  */
+  /*                                                                       */
+  /*    num_params  :: The number of extra parameters.                     */
+  /*                                                                       */
+  /*    params      :: Extra parameters passed to the font driver when     */
+  /*                   opening a new face.                                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream type is determined by the contents of `flags' which     */
+  /*    are tested in the following order by @FT_Open_Face:                */
+  /*                                                                       */
+  /*    If the `ft_open_memory' bit is set, assume that this is a          */
+  /*    memory file of `memory_size' bytes,located at `memory_address'.    */
+  /*                                                                       */
+  /*    Otherwise, if the `ft_open_stream' bit is set, assume that a       */
+  /*    custom input stream `stream' is used.                              */
+  /*                                                                       */
+  /*    Otherwise, if the `ft_open_pathname' bit is set, assume that this  */
+  /*    is a normal file and use `pathname' to open it.                    */
+  /*                                                                       */
+  /*    If the `ft_open_driver' bit is set, @FT_Open_Face() will only      */
+  /*    try to open the file with the driver whose handler is in `driver'. */
+  /*                                                                       */
+  /*    If the `ft_open_params' bit is set, the parameters given by        */
+  /*    `num_params' and `params' will be used.  They are ignored          */
+  /*    otherwise.                                                         */
+  /*                                                                       */
+  typedef struct  FT_Open_Args_
+  {
+    FT_Open_Flags   flags;
+    const FT_Byte*  memory_base;
+    FT_Long         memory_size;
+    FT_String*      pathname;
+    FT_Stream       stream;
+    FT_Module       driver;
+    FT_Int          num_params;
+    FT_Parameter*   params;
+
+  } FT_Open_Args;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Face                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new face object from a given resource and typeface index */
+  /*    using a pathname to the font file.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library resource.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    pathname   :: A path to the font file.                             */
+  /*                                                                       */
+  /*    face_index :: The index of the face within the resource.  The      */
+  /*                  first face has index 0.                              */
+  /* <Output>                                                              */
+  /*    aface      :: A handle to a new face object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Unlike FreeType 1.x, this function automatically creates a glyph   */
+  /*    slot for the face object which can be accessed directly through    */
+  /*    `face->glyph'.                                                     */
+  /*                                                                       */
+  /*    FT_New_Face() can be used to determine and/or check the font       */
+  /*    format of a given font resource.  If the `face_index' field is     */
+  /*    negative, the function will _not_ return any face handle in        */
+  /*    `aface'.  Its return value should be 0 if the font format is       */
+  /*    recognized, or non-zero otherwise.                                 */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_New_Face( FT_Library   library,
+               const char*  filepathname,
+               FT_Long      face_index,
+               FT_Face     *aface );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Memory_Face                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new face object from a given resource and typeface index */
+  /*    using a font file already loaded into memory.                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library resource.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    file_base  :: A pointer to the beginning of the font data.         */
+  /*                                                                       */
+  /*    file_size  :: The size of the memory chunk used by the font data.  */
+  /*                                                                       */
+  /*    face_index :: The index of the face within the resource.  The      */
+  /*                  first face has index 0.                              */
+  /* <Output>                                                              */
+  /*    aface      :: A handle to a new face object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The font data bytes are used _directly_ by the @FT_Face object.    */
+  /*    This means that they are not copied, and that the client is        */
+  /*    responsible for releasing/destroying them _after_ the              */
+  /*    corresponding call to @FT_Done_Face .                              */
+  /*                                                                       */
+  /*    Unlike FreeType 1.x, this function automatically creates a glyph   */
+  /*    slot for the face object which can be accessed directly through    */
+  /*    `face->glyph'.                                                     */
+  /*                                                                       */
+  /*    FT_New_Memory_Face() can be used to determine and/or check the     */
+  /*    font format of a given font resource.  If the `face_index' field   */
+  /*    is negative, the function will _not_ return any face handle in     */
+  /*    `aface'.  Its return value should be 0 if the font format is       */
+  /*    recognized, or non-zero otherwise.                                 */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_New_Memory_Face( FT_Library      library,
+                      const FT_Byte*  file_base,
+                      FT_Long         file_size,
+                      FT_Long         face_index,
+                      FT_Face        *aface );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Open_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Opens a face object from a given resource and typeface index using */
+  /*    an `FT_Open_Args' structure.  If the face object doesn't exist, it */
+  /*    will be created.                                                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library resource.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    args       :: A pointer to an `FT_Open_Args' structure which must  */
+  /*                  be filled by the caller.                             */
+  /*                                                                       */
+  /*    face_index :: The index of the face within the resource.  The      */
+  /*                  first face has index 0.                              */
+  /* <Output>                                                              */
+  /*    aface      :: A handle to a new face object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Unlike FreeType 1.x, this function automatically creates a glyph   */
+  /*    slot for the face object which can be accessed directly through    */
+  /*    `face->glyph'.                                                     */
+  /*                                                                       */
+  /*    FT_Open_Face() can be used to determine and/or check the font      */
+  /*    format of a given font resource.  If the `face_index' field is     */
+  /*    negative, the function will _not_ return any face handle in        */
+  /*    `*face'.  Its return value should be 0 if the font format is       */
+  /*    recognized, or non-zero otherwise.                                 */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Open_Face( FT_Library     library,
+                FT_Open_Args*  args,
+                FT_Long        face_index,
+                FT_Face       *aface );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Attach_File                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    `Attaches' a given font file to an existing face.  This is usually */
+  /*    to read additional information for a single face object.  For      */
+  /*    example, it is used to read the AFM files that come with Type 1    */
+  /*    fonts in order to add kerning data and other metrics.              */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face         :: The target face object.                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    filepathname :: An 8-bit pathname naming the `metrics' file.       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If your font file is in memory, or if you want to provide your     */
+  /*    own input stream object, use FT_Attach_Stream().                   */
+  /*                                                                       */
+  /*    The meaning of the `attach' action (i.e., what really happens when */
+  /*    the new file is read) is not fixed by FreeType itself.  It really  */
+  /*    depends on the font format (and thus the font driver).             */
+  /*                                                                       */
+  /*    Client applications are expected to know what they are doing       */
+  /*    when invoking this function.  Most drivers simply do not implement */
+  /*    file attachments.                                                  */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Attach_File( FT_Face      face,
+                  const char*  filepathname );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Attach_Stream                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is similar to FT_Attach_File() with the exception    */
+  /*    that it reads the attachment from an arbitrary stream.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The target face object.                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    parameters :: A pointer to an FT_Open_Args structure used to       */
+  /*                  describe the input stream to FreeType.               */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The meaning of the `attach' (i.e. what really happens when the     */
+  /*    new file is read) is not fixed by FreeType itself.  It really      */
+  /*    depends on the font format (and thus the font driver).             */
+  /*                                                                       */
+  /*    Client applications are expected to know what they are doing       */
+  /*    when invoking this function.  Most drivers simply do not implement */
+  /*    file attachments.                                                  */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Attach_Stream( FT_Face        face,
+                    FT_Open_Args*  parameters );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards a given face object, as well as all of its child slots    */
+  /*    and sizes.                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to a target face object.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Done_Face( FT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Char_Size                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the character dimensions of a given face object.  The         */
+  /*    `char_width' and `char_height' values are used for the width and   */
+  /*    height, respectively, expressed in 26.6 fractional points.         */
+  /*                                                                       */
+  /*    If the horizontal or vertical resolution values are zero, a        */
+  /*    default value of 72dpi is used.  Similarly, if one of the          */
+  /*    character dimensions is zero, its value is set equal to the other. */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size            :: A handle to a target size object.               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    char_width      :: The character width, in 26.6 fractional points. */
+  /*                                                                       */
+  /*    char_height     :: The character height, in 26.6 fractional        */
+  /*                       points.                                         */
+  /*                                                                       */
+  /*    horz_resolution :: The horizontal resolution.                      */
+  /*                                                                       */
+  /*    vert_resolution :: The vertical resolution.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    When dealing with fixed-size faces (i.e., non-scalable formats),   */
+  /*    use the function FT_Set_Pixel_Sizes().                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Set_Char_Size( FT_Face     face,
+                    FT_F26Dot6  char_width,
+                    FT_F26Dot6  char_height,
+                    FT_UInt     horz_resolution,
+                    FT_UInt     vert_resolution );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Pixel_Sizes                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the character dimensions of a given face object.  The width   */
+  /*    and height are expressed in integer pixels.                        */
+  /*                                                                       */
+  /*    If one of the character dimensions is zero, its value is set equal */
+  /*    to the other.                                                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face         :: A handle to the target face object.                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    pixel_width  :: The character width, in integer pixels.            */
+  /*                                                                       */
+  /*    pixel_height :: The character height, in integer pixels.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The values of `pixel_width' and `pixel_height' correspond to the   */
+  /*    pixel values of the _typographic_ character size, which are NOT    */
+  /*    necessarily the same as the dimensions of the glyph `bitmap        */
+  /*    cells'.                                                            */
+  /*                                                                       */
+  /*    The `character size' is really the size of an abstract square      */
+  /*    called the `EM', used to design the font.  However, depending      */
+  /*    on the font design, glyphs will be smaller or greater than the     */
+  /*    EM.                                                                */
+  /*                                                                       */
+  /*    This means that setting the pixel size to, say, 8x8 doesn't        */
+  /*    guarantee in any way that you will get glyph bitmaps that all fit  */
+  /*    within an 8x8 cell (sometimes even far from it).                   */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Set_Pixel_Sizes( FT_Face  face,
+                      FT_UInt  pixel_width,
+                      FT_UInt  pixel_height );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Load_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to load a single glyph within a given glyph slot,  */
+  /*    for a given size.                                                  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face        :: A handle to the target face object where the glyph  */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FT_LOAD_XXX constants can be used to control the    */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If the glyph image is not a bitmap, and if the bit flag            */
+  /*    FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be         */
+  /*    transformed with the information passed to a previous call to      */
+  /*    FT_Set_Transform().                                                */
+  /*                                                                       */
+  /*    Note that this also transforms the `face.glyph.advance' field, but */
+  /*    *not* the values in `face.glyph.metrics'.                          */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Load_Glyph( FT_Face  face,
+                 FT_UInt  glyph_index,
+                 FT_Int   load_flags );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Load_Char                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to load a single glyph within a given glyph slot,  */
+  /*    for a given size, according to its character code.                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face        :: A handle to a target face object where the glyph    */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    char_code   :: The glyph's character code, according to the        */
+  /*                   current charmap used in the face.                   */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FT_LOAD_XXX constants can be used to control the    */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If the face has no current charmap, or if the character code       */
+  /*    is not defined in the charmap, this function will return an        */
+  /*    error.                                                             */
+  /*                                                                       */
+  /*    If the glyph image is not a bitmap, and if the bit flag            */
+  /*    FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be         */
+  /*    transformed with the information passed to a previous call to      */
+  /*    FT_Set_Transform().                                                */
+  /*                                                                       */
+  /*    Note that this also transforms the `face.glyph.advance' field, but */
+  /*    *not* the values in `face.glyph.metrics'.                          */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Load_Char( FT_Face   face,
+                FT_ULong  char_code,
+                FT_Int    load_flags );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_NO_SCALE                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the vector outline being loaded should not be scaled to 26.6       */
+  /*    fractional pixels, but kept in notional units.                     */
+  /*                                                                       */
+#define FT_LOAD_NO_SCALE  1
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_NO_HINTING                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the vector outline being loaded should not be fitted to the pixel  */
+  /*    grid but simply scaled to 26.6 fractional pixels.                  */
+  /*                                                                       */
+  /*    This flag is ignored if FT_LOAD_NO_SCALE is set.                   */
+  /*                                                                       */
+#define FT_LOAD_NO_HINTING  2
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_RENDER                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the function should load the glyph and immediately convert it into */
+  /*    a bitmap, if necessary, by calling FT_Render_Glyph().              */
+  /*                                                                       */
+  /*    Note that by default, FT_Load_Glyph() loads the glyph image in its */
+  /*    native format.                                                     */
+  /*                                                                       */
+#define FT_LOAD_RENDER  4
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_NO_BITMAP                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the function should not load the bitmap or pixmap of a given       */
+  /*    glyph.  This is useful when you do not want to load the embedded   */
+  /*    bitmaps of scalable formats, as the native glyph image will be     */
+  /*    loaded, and can then be rendered through FT_Render_Glyph().        */
+  /*                                                                       */
+#define FT_LOAD_NO_BITMAP  8
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_VERTICAL_LAYOUT                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the glyph image should be prepared for vertical layout.  This      */
+  /*    basically means that `face.glyph.advance' will correspond to the   */
+  /*    vertical advance height (instead of the default horizontal         */
+  /*    advance width), and that the glyph image will translated to match  */
+  /*    the vertical bearings positions.                                   */
+  /*                                                                       */
+#define FT_LOAD_VERTICAL_LAYOUT  16
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_FORCE_AUTOHINT                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the function should try to auto-hint the glyphs, even if a driver  */
+  /*    specific hinter is available.                                      */
+  /*                                                                       */
+#define FT_LOAD_FORCE_AUTOHINT  32
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_CROP_BITMAP                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the font driver should try to crop the bitmap (i.e. remove all     */
+  /*    space around its black bits) when loading it.  For now, this       */
+  /*    really only works with embedded bitmaps in TrueType fonts.         */
+  /*                                                                       */
+#define FT_LOAD_CROP_BITMAP  64
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_PEDANTIC                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the glyph loader should perform a pedantic bytecode                */
+  /*    interpretation.  Many popular fonts come with broken glyph         */
+  /*    programs.  When this flag is set, loading them will return an      */
+  /*    error.  Otherwise, errors are ignored by the loader, sometimes     */
+  /*    resulting in ugly glyphs.                                          */
+  /*                                                                       */
+#define FT_LOAD_PEDANTIC  128
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the glyph loader should ignore the global advance width defined    */
+  /*    in the font.  As far as we know, this is only used by the          */
+  /*    X-TrueType font server, in order to deal correctly with the        */
+  /*    incorrect metrics contained in DynaLab's TrueType CJK fonts.       */
+  /*                                                                       */
+#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH  512
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_NO_RECURSE                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the glyph loader should not load composite glyph recursively.      */
+  /*    Rather, when a composite glyph is encountered, it should set       */
+  /*    the values of `num_subglyphs' and `subglyphs', as well as set      */
+  /*    `face->glyph.format' to ft_glyph_format_composite.                 */
+  /*                                                                       */
+  /*    This is for use by the auto-hinter and possibly other tools.       */
+  /*    For nearly all applications, this flags should be left unset       */
+  /*    when invoking FT_Load_Glyph().                                     */
+  /*                                                                       */
+  /*    Note that the flag forces the load of unscaled glyphs.             */
+  /*                                                                       */
+#define FT_LOAD_NO_RECURSE  1024
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_IGNORE_TRANSFORM                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the glyph loader should not try to transform the loaded glyph      */
+  /*    image.                                                             */
+  /*                                                                       */
+#define FT_LOAD_IGNORE_TRANSFORM  2048
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_MONOCHROME                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Only used with FT_LOAD_RENDER set, it indicates that the returned  */
+  /*    glyph image should be 1-bit monochrome.  This really tells the     */
+  /*    glyph loader to use `ft_render_mode_mono' when calling             */
+  /*    FT_Render_Glyph().                                                 */
+  /*                                                                       */
+#define FT_LOAD_MONOCHROME  4096
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_LINEAR_DESIGN                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the function should return the linearly scaled metrics expressed   */
+  /*    in original font units, instead of the default 16.16 pixel values. */
+  /*                                                                       */
+#define FT_LOAD_LINEAR_DESIGN  8192
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Constant>                                                            */
+  /*    FT_LOAD_DEFAULT                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A bit-field constant, used with FT_Load_Glyph() to indicate that   */
+  /*    the function should try to load the glyph normally, i.e.,          */
+  /*    embedded bitmaps are favored over outlines, vectors are always     */
+  /*    scaled and grid-fitted.                                            */
+  /*                                                                       */
+#define FT_LOAD_DEFAULT  0
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Transform                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to set the transformation that is applied to glyph */
+  /*    images just before they are converted to bitmaps in a glyph slot   */
+  /*    when FT_Render_Glyph() is called.                                  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the source face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    matrix :: A pointer to the transformation's 2x2 matrix.  Use 0 for */
+  /*              the identity matrix.                                     */
+  /*    delta  :: A pointer to the translation vector.  Use 0 for the null */
+  /*              vector.                                                  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The transformation is only applied to scalable image formats after */
+  /*    the glyph has been loaded.  It means that hinting is unaltered by  */
+  /*    the transformation and is performed on the character size given in */
+  /*    the last call to FT_Set_Char_Sizes() or FT_Set_Pixel_Sizes().      */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Set_Transform( FT_Face     face,
+                    FT_Matrix*  matrix,
+                    FT_Vector*  delta );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Render_Mode                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration type that lists the render modes supported by the   */
+  /*    FreeType 2 renderer(s).  A renderer is in charge of converting a   */
+  /*    glyph image into a bitmap.                                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_render_mode_normal :: This is the default render mode; it       */
+  /*                             corresponds to 8-bit anti-aliased         */
+  /*                             bitmaps, using 256 levels of gray.        */
+  /*                                                                       */
+  /*    ft_render_mode_mono   :: This render mode is used to produce 1-bit */
+  /*                             monochrome bitmaps.                       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    There is no render mode to produce 8-bit `monochrome' bitmaps --   */
+  /*    you have to make the conversion yourself if you need such things   */
+  /*    (besides, FreeType is not a graphics library).                     */
+  /*                                                                       */
+  /*    More modes might appear later for specific display modes (e.g. TV, */
+  /*    LCDs, etc.).  They will be supported through the simple addition   */
+  /*    of a renderer module, with no changes to the rest of the engine.   */
+  /*                                                                       */
+  typedef enum  FT_Render_Mode_
+  {
+    ft_render_mode_normal = 0,
+    ft_render_mode_mono   = 1
+
+  } FT_Render_Mode;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Render_Glyph                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts a given glyph image to a bitmap.  It does so by           */
+  /*    inspecting the glyph image format, find the relevant renderer, and */
+  /*    invoke it.                                                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    slot        :: A handle to the glyph slot containing the image to  */
+  /*                   convert.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    render_mode :: This is the render mode used to render the glyph    */
+  /*                   image into a bitmap.  See FT_Render_Mode for a list */
+  /*                   of possible values.                                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Render_Glyph( FT_GlyphSlot  slot,
+                   FT_UInt       render_mode );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Kerning_Mode                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration used to specify which kerning values to return in   */
+  /*    FT_Get_Kerning().                                                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_kerning_default  :: Return scaled and grid-fitted kerning       */
+  /*                           distances (value is 0).                     */
+  /*                                                                       */
+  /*    ft_kerning_unfitted :: Return scaled but un-grid-fitted kerning    */
+  /*                           distances.                                  */
+  /*                                                                       */
+  /*    ft_kerning_unscaled :: Return the kerning vector in original font  */
+  /*                           units.                                      */
+  /*                                                                       */
+  typedef enum  FT_Kerning_Mode_
+  {
+    ft_kerning_default  = 0,
+    ft_kerning_unfitted,
+    ft_kerning_unscaled
+
+  } FT_Kerning_Mode;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Kerning                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the kerning vector between two glyphs of a same face.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to a source face object.                   */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /*    kern_mode   :: See FT_Kerning_Mode() for more information.         */
+  /*                   Determines the scale/dimension of the returned      */
+  /*                   kerning vector.                                     */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    akerning    :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this method.  Other layouts, or more sophisticated    */
+  /*    kernings, are out of the scope of this API function -- they can be */
+  /*    implemented through format-specific interfaces.                    */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Get_Kerning( FT_Face     face,
+                  FT_UInt     left_glyph,
+                  FT_UInt     right_glyph,
+                  FT_UInt     kern_mode,
+                  FT_Vector  *akerning );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Glyph_Name                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the ASCII name of a given glyph in a face.  This only    */
+  /*    works for those faces where FT_HAS_GLYPH_NAME(face) returns true.  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to a source face object.                   */
+  /*                                                                       */
+  /*    glyph_index :: The glyph index.                                    */
+  /*                                                                       */
+  /*    buffer_max  :: The maximal number of bytes available in the        */
+  /*                   buffer.                                             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    buffer      :: A pointer to a target buffer where the name will be */
+  /*                   copied to.                                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An error is returned if the face doesn't provide glyph names or if */
+  /*    the glyph index is invalid.  In all cases of failure, the first    */
+  /*    byte of `buffer' will be set to 0 to indicate an empty name.       */
+  /*                                                                       */
+  /*    The glyph name is truncated to fit within the buffer if it is too  */
+  /*    long.  The returned string is always zero-terminated.              */
+  /*                                                                       */
+  /*    This function is not compiled within the library if the config     */
+  /*    macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is defined in                */
+  /*    `include/freetype/config/ftoptions.h'                              */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Get_Glyph_Name( FT_Face     face,
+                     FT_UInt     glyph_index,
+                     FT_Pointer  buffer,
+                     FT_UInt     buffer_max );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Postscript_Name                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the ASCII Postscript name of a given face, when          */
+  /*    available. This should only work with Postscript and TrueType      */
+  /*    fonts..                                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: handle to source face object.                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    pointer to face's Postscript name. NULL when un-available          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The returned pointer is owned by the face and will be destroyed    */
+  /*    with it.                                                           */
+  /*                                                                       */
+  FT_EXPORT( const char* )
+  FT_Get_Postscript_Name( FT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Select_Charmap                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Selects a given charmap by its encoding tag (as listed in          */
+  /*    `freetype.h').                                                     */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face     :: A handle to the source face object.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    encoding :: A handle to the selected charmap.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will return an error if no charmap in the face       */
+  /*    corresponds to the encoding queried here.                          */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Select_Charmap( FT_Face      face,
+                     FT_Encoding  encoding );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Charmap                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Selects a given charmap for character code to glyph index          */
+  /*    decoding.                                                          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face    :: A handle to the source face object.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap :: A handle to the selected charmap.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will return an error if the charmap is not part of   */
+  /*    the face (i.e., if it is not listed in the face->charmaps[]        */
+  /*    table).                                                            */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Set_Charmap( FT_Face     face,
+                  FT_CharMap  charmap );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Char_Index                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the glyph index of a given character code.  This function  */
+  /*    uses a charmap object to do the translation.                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the source face object.                    */
+  /*                                                                       */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The glyph index.  0 means `undefined character code'.              */
+  /*                                                                       */
+  FT_EXPORT( FT_UInt )
+  FT_Get_Char_Index( FT_Face   face,
+                     FT_ULong  charcode );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Name_Index                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the glyph index of a given glyph name.  This function uses */
+  /*    driver specific objects to do the translation.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the source face object.                  */
+  /*                                                                       */
+  /*    glyph_name :: The glyph name.                                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The glyph index.  0 means `undefined character code'.              */
+  /*                                                                       */
+  FT_EXPORT( FT_UInt )
+  FT_Get_Name_Index( FT_Face     face,
+                     FT_String*  glyph_name );
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    computations                                                       */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Computations                                                       */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    Crunching fixed numbers and vectors                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This section contains various functions used to perform            */
+  /*    computations on 16.16 fixed-float numbers or 2d vectors.           */
+  /*                                                                       */
+  /* <Order>                                                               */
+  /*    FT_MulDiv                                                          */
+  /*    FT_MulFix                                                          */
+  /*    FT_DivFix                                                          */
+  /*    FT_RoundFix                                                        */
+  /*    FT_CeilFix                                                         */
+  /*    FT_FloorFix                                                        */
+  /*    FT_Vector_Transform                                                */
+  /*    FT_Matrix_Multiply                                                 */
+  /*    FT_Matrix_Invert                                                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulDiv                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation `(a*b)/c'   */
+  /*    with maximal accuracy (it uses a 64-bit intermediate integer       */
+  /*    whenever necessary).                                               */
+  /*                                                                       */
+  /*    This function isn't necessarily as fast as some processor specific */
+  /*    operations, but is at least completely portable.                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.                                        */
+  /*    c :: The divisor.                                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*b)/c'.  This function never traps when trying to */
+  /*    divide by zero; it simply returns `MaxInt' or `MinInt' depending   */
+  /*    on the signs of `a' and `b'.                                       */
+  /*                                                                       */
+  FT_EXPORT( FT_Long )
+  FT_MulDiv( FT_Long  a,
+             FT_Long  b,
+             FT_Long  c );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulFix                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation             */
+  /*    `(a*b)/0x10000' with maximal accuracy.  Most of the time this is   */
+  /*    used to multiply a given value by a 16.16 fixed float factor.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.  Use a 16.16 factor here whenever      */
+  /*         possible (see note below).                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*b)/0x10000'.                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function has been optimized for the case where the absolute   */
+  /*    value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
+  /*    As this happens mainly when scaling from notional units to         */
+  /*    fractional pixels in FreeType, it resulted in noticeable speed     */
+  /*    improvements between versions 2.x and 1.x.                         */
+  /*                                                                       */
+  /*    As a conclusion, always try to place a 16.16 factor as the         */
+  /*    _second_ argument of this function; this can make a great          */
+  /*    difference.                                                        */
+  /*                                                                       */
+  FT_EXPORT( FT_Long )
+  FT_MulFix( FT_Long  a,
+             FT_Long  b );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_DivFix                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to perform the computation             */
+  /*    `(a*0x10000)/b' with maximal accuracy.  Most of the time, this is  */
+  /*    used to divide a given value by a 16.16 fixed float factor.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The first multiplier.                                         */
+  /*    b :: The second multiplier.  Use a 16.16 factor here whenever      */
+  /*         possible (see note below).                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a*0x10000)/b'.                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The optimization for FT_DivFix() is simple: If (a << 16) fits in   */
+  /*    32 bits, then the division is computed directly.  Otherwise, we    */
+  /*    use a specialized version of the old FT_MulDiv64().                */
+  /*                                                                       */
+  FT_EXPORT( FT_Long )
+  FT_DivFix( FT_Long  a,
+             FT_Long  b );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_RoundFix                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to round a 16.16 fixed number.         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The number to be rounded.                                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a + 0x8000) & -0x10000'.                           */
+  /*                                                                       */
+  FT_EXPORT( FT_Fixed )
+  FT_RoundFix( FT_Fixed  a );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_CeilFix                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to compute the ceiling function of a   */
+  /*    16.16 fixed number.                                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The number for which the ceiling function is to be computed.  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `(a + 0x10000 - 1) & -0x10000'.                      */
+  /*                                                                       */
+  FT_EXPORT( FT_Fixed )
+  FT_CeilFix( FT_Fixed  a );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_FloorFix                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A very simple function used to compute the floor function of a     */
+  /*    16.16 fixed number.                                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: The number for which the floor function is to be computed.    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `a & -0x10000'.                                      */
+  /*                                                                       */
+  FT_EXPORT( FT_Fixed )
+  FT_FloorFix( FT_Fixed  a );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Vector_Transform                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Transforms a single vector through a 2x2 matrix.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    vector :: The target vector to transform.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    matrix :: A pointer to the source 2x2 matrix.                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The result is undefined if either `vector' or `matrix' is invalid. */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Vector_Transform( FT_Vector*  vec,
+                       FT_Matrix*  matrix );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FREETYPE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftbbox.h b/libraries/freetype-2.0.5/include/freetype/ftbbox.h
new file mode 100644 (file)
index 0000000..e661613
--- /dev/null
@@ -0,0 +1,83 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftbbox.h                                                               */
+/*                                                                         */
+/*    FreeType exact bbox computation (specification).                     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This component has a _single_ role: to compute exact outline bounding */
+  /* boxes.                                                                */
+  /*                                                                       */
+  /* It is separated from the rest of the engine for various technical     */
+  /* reasons.  It may well be integrated in `ftoutln' later.               */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTBBOX_H__
+#define __FTBBOX_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    outline_processing                                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Get_BBox                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the exact bounding box of an outline.  This is slower     */
+  /*    than computing the control box.  However, it uses an advanced      */
+  /*    algorithm which returns _very_ quickly when the two boxes          */
+  /*    coincide.  Otherwise, the outline Bezier arcs are walked over to   */
+  /*    extract their extrema.                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the source outline.                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    abbox   :: The outline's exact bounding box.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Outline_Get_BBox( FT_Outline*  outline,
+                       FT_BBox     *abbox );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTBBOX_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftcache.h b/libraries/freetype-2.0.5/include/freetype/ftcache.h
new file mode 100644 (file)
index 0000000..fc15956
--- /dev/null
@@ -0,0 +1,358 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcache.h                                                              */
+/*                                                                         */
+/*    FreeType Cache subsystem.                                            */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*********                                                       *********/
+  /*********             WARNING, THIS IS BETA CODE.               *********/
+  /*********                                                       *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#ifndef __FTCACHE_H__
+#define __FTCACHE_H__
+
+
+#include <ft2build.h>
+#include FT_GLYPH_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    cache_subsystem                                                    */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Cache Sub-System                                                   */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    How to cache face, size, and glyph data with FreeType 2.           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   This section describes the FreeType 2 cache sub-system which is     */
+  /*   stile in beta.                                                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    BASIC TYPE DEFINITIONS                     *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FTC_FaceID                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A generic pointer type that is used to identity face objects.  The */
+  /*    contents of such objects is application-dependent.                 */
+  /*                                                                       */
+  typedef FT_Pointer  FTC_FaceID;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FTC_Face_Requester                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A callback function provided by client applications.  It is used   */
+  /*    to translate a given FTC_FaceID into a new valid FT_Face object.   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face_id :: The face ID to resolve.                                 */
+  /*                                                                       */
+  /*    library :: A handle to a FreeType library object.                  */
+  /*                                                                       */
+  /*    data    :: Application-provided request data.                      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aface   :: A new FT_Face handle.                                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The face requester should not perform funny things on the returned */
+  /*    face object, like creating a new FT_Size for it, or setting a      */
+  /*    transformation through FT_Set_Transform()!                         */
+  /*                                                                       */
+  typedef FT_Error
+  (*FTC_Face_Requester)( FTC_FaceID  face_id,
+                         FT_Library  library,
+                         FT_Pointer  request_data,
+                         FT_Face*    aface );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FTC_FontRec                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to describe a given `font' to the cache    */
+  /*    manager.  Note that a `font' is the combination of a given face    */
+  /*    with a given character size.                                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    face_id    :: The ID of the face to use.                           */
+  /*                                                                       */
+  /*    pix_width  :: The character width in integer pixels.               */
+  /*                                                                       */
+  /*    pix_height :: The character height in integer pixels.              */
+  /*                                                                       */
+  typedef struct  FTC_FontRec_
+  {
+    FTC_FaceID  face_id;
+    FT_UShort   pix_width;
+    FT_UShort   pix_height;
+
+  } FTC_FontRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FTC_Font                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple handle to a FTC_FontRec structure.                        */
+  /*                                                                       */
+  typedef FTC_FontRec*  FTC_Font;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      CACHE MANAGER OBJECT                     *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FTC_Manager                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This object is used to cache one or more FT_Face objects, along    */
+  /*    with corresponding FT_Size objects.                                */
+  /*                                                                       */
+  typedef struct FTC_ManagerRec_*  FTC_Manager;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_Manager_New                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new cache manager.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library   :: The parent FreeType library handle to use.            */
+  /*                                                                       */
+  /*    max_faces :: Maximum number of faces to keep alive in manager.     */
+  /*                 Use 0 for defaults.                                   */
+  /*                                                                       */
+  /*    max_sizes :: Maximum number of sizes to keep alive in manager.     */
+  /*                 Use 0 for defaults.                                   */
+  /*                                                                       */
+  /*    max_bytes :: Maximum number of bytes to use for cached data.       */
+  /*                 Use 0 for defaults.                                   */
+  /*                                                                       */
+  /*    requester :: An application-provided callback used to translate    */
+  /*                 face IDs into real FT_Face objects.                   */
+  /*                                                                       */
+  /*    req_data  :: A generic pointer that is passed to the requester     */
+  /*                 each time it is called (see FTC_Face_Requester)       */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    amanager  :: A handle to a new manager object.  0 in case of       */
+  /*                 failure.                                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FTC_Manager_New( FT_Library          library,
+                   FT_UInt             max_faces,
+                   FT_UInt             max_sizes,
+                   FT_ULong            max_bytes,
+                   FTC_Face_Requester  requester,
+                   FT_Pointer          req_data,
+                   FTC_Manager        *amanager );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_Manager_Reset                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Empties a given cache manager.  This simply gets rid of all the    */
+  /*    currently cached FT_Face & FT_Size objects within the manager.     */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    manager :: A handle to the manager.                                */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FTC_Manager_Reset( FTC_Manager  manager );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_Manager_Done                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given manager after emptying it.                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    manager :: A handle to the target cache manager object.            */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FTC_Manager_Done( FTC_Manager  manager );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_Manager_Lookup_Face                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the FT_Face object that corresponds to a given face ID   */
+  /*    through a cache manager.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    manager :: A handle to the cache manager.                          */
+  /*                                                                       */
+  /*    face_id :: The ID of the face object.                              */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aface   :: A handle to the face object.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The returned FT_Face object is always owned by the manager.  You   */
+  /*    should never try to discard it yourself.                           */
+  /*                                                                       */
+  /*    The FT_Face object doesn't necessarily have a current size object  */
+  /*    (i.e., face->size can be 0).  If you need a specific `font size',  */
+  /*    use FTC_Manager_Lookup_Size() instead.                             */
+  /*                                                                       */
+  /*    Never change the face's transformation matrix (i.e., never call    */
+  /*    the FT_Set_Transform() function) on a returned face!  If you need  */
+  /*    to transform glyphs, do it yourself after glyph loading.           */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FTC_Manager_Lookup_Face( FTC_Manager  manager,
+                           FTC_FaceID   face_id,
+                           FT_Face     *aface );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_Manager_Lookup_Size                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the FT_Face & FT_Size objects that correspond to a given */
+  /*    FTC_SizeID.                                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    manager :: A handle to the cache manager.                          */
+  /*                                                                       */
+  /*    size_id :: The ID of the `font size' to use.                       */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aface   :: A pointer to the handle of the face object.  Set it to  */
+  /*               zero if you don't need it.                              */
+  /*                                                                       */
+  /*    asize   :: A pointer to the handle of the size object.  Set it to  */
+  /*               zero if you don't need it.                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The returned FT_Face object is always owned by the manager.  You   */
+  /*    should never try to discard it yourself.                           */
+  /*                                                                       */
+  /*    Never change the face's transformation matrix (i.e., never call    */
+  /*    the FT_Set_Transform() function) on a returned face!  If you need  */
+  /*    to transform glyphs, do it yourself after glyph loading.           */
+  /*                                                                       */
+  /*    Similarly, the returned FT_Size object is always owned by the      */
+  /*    manager.  You should never try to discard it, and never change its */
+  /*    settings with FT_Set_Pixel_Sizes() or FT_Set_Char_Size()!          */
+  /*                                                                       */
+  /*    The returned size object is the face's current size, which means   */
+  /*    that you can call FT_Load_Glyph() with the face if you need to.    */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FTC_Manager_Lookup_Size( FTC_Manager  manager,
+                           FTC_Font     font,
+                           FT_Face     *aface,
+                           FT_Size     *asize );
+
+
+  /* a cache class is used to describe a unique cache type to the manager */
+  typedef struct FTC_Cache_Class_  FTC_Cache_Class;
+  typedef struct FTC_CacheRec_*    FTC_Cache;
+
+
+  /* this must be used internally for the moment */
+  FT_EXPORT( FT_Error )
+  FTC_Manager_Register_Cache( FTC_Manager       manager,
+                              FTC_Cache_Class*  clazz,
+                              FTC_Cache        *acache );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTCACHE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftchapters.h b/libraries/freetype-2.0.5/include/freetype/ftchapters.h
new file mode 100644 (file)
index 0000000..3c107d8
--- /dev/null
@@ -0,0 +1,55 @@
+/***************************************************************************/
+/*                                                                         */
+/* <Chapter>                                                               */
+/*    core_api                                                             */
+/*                                                                         */
+/* <Title>                                                                 */
+/*    Core API                                                             */
+/*                                                                         */
+/* <Sections>                                                              */
+/*    basic_types                                                          */
+/*    base_interface                                                       */
+/*    glyph_management                                                     */
+/*    mac_specific                                                         */
+/*    multiple_masters                                                     */
+/*    truetype_tables                                                      */
+/*    type1_tables                                                         */
+/*    sfnt_names                                                           */
+/*    sizes_management                                                     */
+/*    module_management                                                    */
+/*    system_interface                                                     */
+/*    header_file_macros                                                   */
+/*                                                                         */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/*                                                                         */
+/* <Chapter>                                                               */
+/*    cache_subsystem                                                      */
+/*                                                                         */
+/* <Title>                                                                 */
+/*    Cache Sub-System                                                     */
+/*                                                                         */
+/* <Sections>                                                              */
+/*    cache_subsystem                                                      */
+/*                                                                         */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/*                                                                         */
+/* <Chapter>                                                               */
+/*    support_api                                                          */
+/*                                                                         */
+/* <Title>                                                                 */
+/*    Support API                                                          */
+/*                                                                         */
+/* <Sections>                                                              */
+/*    computations                                                         */
+/*    list_processing                                                      */
+/*    outline_processing                                                   */
+/*    raster                                                               */
+/*                                                                         */
+/***************************************************************************/
+
diff --git a/libraries/freetype-2.0.5/include/freetype/fterrors.h b/libraries/freetype-2.0.5/include/freetype/fterrors.h
new file mode 100644 (file)
index 0000000..89e0cf3
--- /dev/null
@@ -0,0 +1,383 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fterrors.h                                                             */
+/*                                                                         */
+/*    FreeType error codes (specification).                                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This special header file is used to define the FT2 enumeration        */
+  /* constants.  It can also be used to generate error message strings     */
+  /* with a small macro trick explained below.                             */
+  /*                                                                       */
+  /* I - Error Formats                                                     */
+  /* -----------------                                                     */
+  /*                                                                       */
+  /*   Since release 2.1, the error constants have changed.  The lower     */
+  /*   byte of the error value gives the "generic" error code, while the   */
+  /*   higher byte indicates in which module the error occured.            */
+  /*                                                                       */
+  /*   You can use the macro FT_ERROR_BASE(x) macro to extract the generic */
+  /*   error code from an FT_Error value.                                  */
+  /*                                                                       */
+  /*   The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be   */
+  /*   undefined in ftoption.h in order to make the higher byte always     */
+  /*   zero, in case you need to be compatible with previous versions of   */
+  /*   FreeType 2.                                                         */
+  /*                                                                       */
+  /*                                                                       */
+  /* II - Error Message strings                                            */
+  /* --------------------------                                            */
+  /*                                                                       */
+  /*   The error definitions below are made through special macros that    */
+  /*   allow client applications to build a table of error message strings */
+  /*   if they need it.  The strings are not included in a normal build of */
+  /*   FreeType 2 to save space (most client applications do not use       */
+  /*   them).                                                              */
+  /*                                                                       */
+  /*   To do so, you have to define the following macros before including  */
+  /*   this file:                                                          */
+  /*                                                                       */
+  /*   FT_ERROR_START_LIST ::                                              */
+  /*     This macro is called before anything else to define the start of  */
+  /*     the error list.  It is followed by several FT_ERROR_DEF calls     */
+  /*     (see below).                                                      */
+  /*                                                                       */
+  /*   FT_ERROR_DEF( e, v, s ) ::                                          */
+  /*     This macro is called to define one single error.                  */
+  /*     `e' is the error code identifier (e.g. FT_Err_Invalid_Argument).  */
+  /*     `v' is the error numerical value.                                 */
+  /*     `s' is the corresponding error string.                            */
+  /*                                                                       */
+  /*   FT_ERROR_END_LIST ::                                                */
+  /*     This macro ends the list.                                         */
+  /*                                                                       */
+  /*   Additionally, you have to undefine __FTERRORS_H__ before #including */
+  /*   this file.                                                          */
+  /*                                                                       */
+  /*   Here is a simple example:                                           */
+  /*                                                                       */
+  /*     {                                                                 */
+  /*       #undef __FTERRORS_H__                                           */
+  /*       #define FT_ERRORDEF( e, v, s )   { e, s },                      */
+  /*       #define FT_ERROR_START_LIST      {                              */
+  /*       #define FT_ERROR_END_LIST        { 0, 0 } };                    */
+  /*                                                                       */
+  /*       const struct                                                    */
+  /*       {                                                               */
+  /*         int          err_code;                                        */
+  /*         const char*  err_msg                                          */
+  /*       } ft_errors[] =                                                 */
+  /*                                                                       */
+  /*       #include FT_ERRORS_H                                            */
+  /*     }                                                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTERRORS_H__
+#define __FTERRORS_H__
+
+
+  /* include module base error codes */
+#include FT_MODULE_ERRORS_H
+
+
+  /*******************************************************************/
+  /*******************************************************************/
+  /*****                                                         *****/
+  /*****                       SETUP MACROS                      *****/
+  /*****                                                         *****/
+  /*******************************************************************/
+  /*******************************************************************/
+
+
+#undef  FT_NEED_EXTERN_C
+#define FT_ERR_XCAT( x, y )  x ## y
+#define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
+
+
+  /* FT_ERR_PREFIX is used as a prefix for error identifiers. */
+  /* By default, we use `FT_Err_'.                            */
+  /*                                                          */
+#ifndef FT_ERR_PREFIX
+#define FT_ERR_PREFIX  FT_Err_
+#endif
+
+
+  /* FT_ERR_BASE is used as the base for module-specific errors. */
+  /*                                                             */
+#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS
+
+#ifndef FT_ERR_BASE
+#define FT_ERR_BASE  FT_Mod_Err_Base
+#endif
+
+#else
+
+#undef FT_ERR_BASE
+#define FT_ERR_BASE  0
+
+#endif /* FT_CONFIG_OPTION_USE_MODULE_ERRORS */
+
+
+  /* If FT_ERRORDEF is not defined, we need to define a simple */
+  /* enumeration type.                                         */
+  /*                                                           */
+#ifndef FT_ERRORDEF
+
+#define FT_ERRORDEF( e, v, s )  e = v,
+#define FT_ERROR_START_LIST     enum {
+#define FT_ERROR_END_LIST       FT_ERR_CAT( FT_ERR_PREFIX, Max ) };
+
+#ifdef __cplusplus
+#define FT_NEED_EXTERN_C
+  extern "C" {
+#endif
+
+#endif /* !FT_ERRORDEF */
+
+
+  /* this macro is used to define an error */
+#define FT_ERRORDEF_( e, v, s )   \
+          FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s )
+
+  /* this is only used for FT_Err_Ok, which must be 0! */
+#define FT_NOERRORDEF_( e, v, s ) \
+          FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s )
+
+
+  /*******************************************************************/
+  /*******************************************************************/
+  /*****                                                         *****/
+  /*****                LIST OF ERROR CODES/MESSAGES             *****/
+  /*****                                                         *****/
+  /*******************************************************************/
+  /*******************************************************************/
+
+
+#ifdef FT_ERROR_START_LIST
+  FT_ERROR_START_LIST
+#endif
+
+
+  /* generic errors */
+
+  FT_NOERRORDEF_( Ok,                                        0x00, \
+                  "no error" )
+
+  FT_ERRORDEF_( Cannot_Open_Resource,                        0x01, \
+               "cannot open resource" )
+  FT_ERRORDEF_( Unknown_File_Format,                         0x02, \
+               "unknown file format" )
+  FT_ERRORDEF_( Invalid_File_Format,                         0x03, \
+               "broken file" )
+  FT_ERRORDEF_( Invalid_Version,                             0x04, \
+               "invalid FreeType version" )
+  FT_ERRORDEF_( Lower_Module_Version,                        0x05, \
+               "module version is too low" )
+  FT_ERRORDEF_( Invalid_Argument,                            0x06, \
+               "invalid argument" )
+  FT_ERRORDEF_( Unimplemented_Feature,                       0x07, \
+               "unimplemented feature" )
+
+  /* glyph/character errors */
+
+  FT_ERRORDEF_( Invalid_Glyph_Index,                         0x10, \
+               "invalid glyph index" )
+  FT_ERRORDEF_( Invalid_Character_Code,                      0x11, \
+               "invalid character code" )
+  FT_ERRORDEF_( Invalid_Glyph_Format,                        0x12, \
+               "unsupported glyph image format" )
+  FT_ERRORDEF_( Cannot_Render_Glyph,                         0x13, \
+               "cannot render this glyph format" )
+  FT_ERRORDEF_( Invalid_Outline,                             0x14, \
+               "invalid outline" )
+  FT_ERRORDEF_( Invalid_Composite,                           0x15, \
+               "invalid composite glyph" )
+  FT_ERRORDEF_( Too_Many_Hints,                              0x16, \
+               "too many hints" )
+  FT_ERRORDEF_( Invalid_Pixel_Size,                          0x17, \
+               "invalid pixel size" )
+
+  /* handle errors */
+
+  FT_ERRORDEF_( Invalid_Handle,                              0x20, \
+               "invalid object handle" )
+  FT_ERRORDEF_( Invalid_Library_Handle,                      0x21, \
+               "invalid library handle" )
+  FT_ERRORDEF_( Invalid_Driver_Handle,                       0x22, \
+               "invalid module handle" )
+  FT_ERRORDEF_( Invalid_Face_Handle,                         0x23, \
+               "invalid face handle" )
+  FT_ERRORDEF_( Invalid_Size_Handle,                         0x24, \
+               "invalid size handle" )
+  FT_ERRORDEF_( Invalid_Slot_Handle,                         0x25, \
+               "invalid glyph slot handle" )
+  FT_ERRORDEF_( Invalid_CharMap_Handle,                      0x26, \
+               "invalid charmap handle" )
+  FT_ERRORDEF_( Invalid_Cache_Handle,                        0x27, \
+               "invalid cache manager handle" )
+  FT_ERRORDEF_( Invalid_Stream_Handle,                       0x28, \
+               "invalid stream handle" )
+
+  /* driver errors */
+
+  FT_ERRORDEF_( Too_Many_Drivers,                            0x30, \
+               "too many modules" )
+  FT_ERRORDEF_( Too_Many_Extensions,                         0x31, \
+               "too many extensions" )
+
+  /* memory errors */
+
+  FT_ERRORDEF_( Out_Of_Memory,                               0x40, \
+               "out of memory" )
+  FT_ERRORDEF_( Unlisted_Object,                             0x41, \
+               "unlisted object" )
+
+  /* stream errors */
+
+  FT_ERRORDEF_( Cannot_Open_Stream,                          0x51, \
+               "cannot open stream" )
+  FT_ERRORDEF_( Invalid_Stream_Seek,                         0x52, \
+               "invalid stream seek" )
+  FT_ERRORDEF_( Invalid_Stream_Skip,                         0x53, \
+               "invalid stream skip" )
+  FT_ERRORDEF_( Invalid_Stream_Read,                         0x54, \
+               "invalid stream read" )
+  FT_ERRORDEF_( Invalid_Stream_Operation,                    0x55, \
+               "invalid stream operation" )
+  FT_ERRORDEF_( Invalid_Frame_Operation,                     0x56, \
+               "invalid frame operation" )
+  FT_ERRORDEF_( Nested_Frame_Access,                         0x57, \
+               "nested frame access" )
+  FT_ERRORDEF_( Invalid_Frame_Read,                          0x58, \
+               "invalid frame read" )
+
+  /* raster errors */
+
+  FT_ERRORDEF_( Raster_Uninitialized,                        0x60, \
+               "raster uninitialized" )
+  FT_ERRORDEF_( Raster_Corrupted,                            0x61, \
+               "raster corrupted" )
+  FT_ERRORDEF_( Raster_Overflow,                             0x62, \
+               "raster overflow" )
+  FT_ERRORDEF_( Raster_Negative_Height,                      0x63, \
+               "negative height while rastering" )
+
+  /* cache errors */
+
+  FT_ERRORDEF_( Too_Many_Caches,                             0x70, \
+               "too many registered caches" )
+
+  /* TrueType and SFNT errors */
+
+  FT_ERRORDEF_( Invalid_Opcode,                              0x80, \
+               "invalid opcode" )
+  FT_ERRORDEF_( Too_Few_Arguments,                           0x81, \
+               "too few arguments" )
+  FT_ERRORDEF_( Stack_Overflow,                              0x82, \
+               "stack overflow" )
+  FT_ERRORDEF_( Code_Overflow,                               0x83, \
+               "code overflow" )
+  FT_ERRORDEF_( Bad_Argument,                                0x84, \
+               "bad argument" )
+  FT_ERRORDEF_( Divide_By_Zero,                              0x85, \
+               "division by zero" )
+  FT_ERRORDEF_( Invalid_Reference,                           0x86, \
+               "invalid reference" )
+  FT_ERRORDEF_( Debug_OpCode,                                0x87, \
+               "found debug opcode" )
+  FT_ERRORDEF_( ENDF_In_Exec_Stream,                         0x88, \
+               "found ENDF opcode in execution stream" )
+  FT_ERRORDEF_( Nested_DEFS,                                 0x89, \
+               "nested DEFS" )
+  FT_ERRORDEF_( Invalid_CodeRange,                           0x8A, \
+               "invalid code range" )
+  FT_ERRORDEF_( Execution_Too_Long,                          0x8B, \
+               "execution context too long" )
+  FT_ERRORDEF_( Too_Many_Function_Defs,                      0x8C, \
+               "too many function definitions" )
+  FT_ERRORDEF_( Too_Many_Instruction_Defs,                   0x8D, \
+               "too many instruction definitions" )
+  FT_ERRORDEF_( Table_Missing,                               0x8E, \
+               "SFNT font table missing" )
+  FT_ERRORDEF_( Horiz_Header_Missing,                        0x8F, \
+               "horizontal header (hhea) table missing" )
+  FT_ERRORDEF_( Locations_Missing,                           0x90, \
+               "locations (loca) table missing" )
+  FT_ERRORDEF_( Name_Table_Missing,                          0x91, \
+               "name table missing" )
+  FT_ERRORDEF_( CMap_Table_Missing,                          0x92, \
+               "character map (cmap) table missing" )
+  FT_ERRORDEF_( Hmtx_Table_Missing,                          0x93, \
+               "horizontal metrics (hmtx) table missing" )
+  FT_ERRORDEF_( Post_Table_Missing,                          0x94, \
+               "PostScript (post) table missing" )
+  FT_ERRORDEF_( Invalid_Horiz_Metrics,                       0x95, \
+               "invalid horizontal metrics" )
+  FT_ERRORDEF_( Invalid_CharMap_Format,                      0x96, \
+               "invalid character map (cmap) format" )
+  FT_ERRORDEF_( Invalid_PPem,                                0x97, \
+               "invalid ppem value" )
+  FT_ERRORDEF_( Invalid_Vert_Metrics,                        0x98, \
+               "invalid vertical metrics" )
+  FT_ERRORDEF_( Could_Not_Find_Context,                      0x99, \
+               "could not find context" )
+  FT_ERRORDEF_( Invalid_Post_Table_Format,                   0x9A, \
+               "invalid PostScript (post) table format" )
+  FT_ERRORDEF_( Invalid_Post_Table,                          0x9B, \
+               "invalid PostScript (post) table" )
+
+  /* CFF, CID, and Type 1 errors */
+
+  FT_ERRORDEF_( Syntax_Error,                                0xA0, \
+               "opcode syntax error" )
+  FT_ERRORDEF_( Stack_Underflow,                             0xA1, \
+               "argument stack underflow" )
+
+
+#ifdef FT_ERROR_END_LIST
+  FT_ERROR_END_LIST
+#endif
+
+
+  /*******************************************************************/
+  /*******************************************************************/
+  /*****                                                         *****/
+  /*****                      SIMPLE CLEANUP                     *****/
+  /*****                                                         *****/
+  /*******************************************************************/
+  /*******************************************************************/
+
+#ifdef FT_NEED_EXTERN_C
+  }
+#endif
+
+#undef FT_ERROR_START_LIST
+#undef FT_ERROR_END_LIST
+
+#undef FT_ERRORDEF
+#undef FT_ERRORDEF_
+#undef FT_NOERRORDEF_
+
+#undef FT_NEED_EXTERN_C
+#undef FT_ERR_PREFIX
+#undef FT_ERR_BASE
+#undef FT_ERR_CONCAT
+
+#endif /* __FTERRORS_H__ */
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftglyph.h b/libraries/freetype-2.0.5/include/freetype/ftglyph.h
new file mode 100644 (file)
index 0000000..f966653
--- /dev/null
@@ -0,0 +1,475 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftglyph.h                                                              */
+/*                                                                         */
+/*    FreeType convenience functions to handle glyphs (specification).     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file contains the definition of several convenience functions    */
+  /* that can be used by client applications to easily retrieve glyph      */
+  /* bitmaps and outlines from a given face.                               */
+  /*                                                                       */
+  /* These functions should be optional if you are writing a font server   */
+  /* or text layout engine on top of FreeType.  However, they are pretty   */
+  /* handy for many other simple uses of the library.                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTGLYPH_H__
+#define __FTGLYPH_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    glyph_management                                                   */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Glyph Management                                                   */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    Generic interface to manage individual glyph data.                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This section contains definitions used to manage glyph data        */
+  /*    through generic FT_Glyph objects.  Each of them can contain a      */
+  /*    bitmap, a vector outline, or even images in other formats.         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* forward declaration to a private type */
+  typedef struct FT_Glyph_Class_  FT_Glyph_Class;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_GlyphRec                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The root glyph structure contains a given glyph image plus its     */
+  /*    advance width in 16.16 fixed float format.                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    library :: A handle to the FreeType library object.                */
+  /*                                                                       */
+  /*    clazz   :: A pointer to the glyph's class.  Private.               */
+  /*                                                                       */
+  /*    format  :: The format of the glyph's image.                        */
+  /*                                                                       */
+  /*    advance :: A 16.16 vector that gives the glyph's advance width.    */
+  /*                                                                       */
+  typedef struct  FT_GlyphRec_
+  {
+    FT_Library             library;
+    const FT_Glyph_Class*  clazz;
+    FT_Glyph_Format        format;
+    FT_Vector              advance;
+
+  } FT_GlyphRec, *FT_Glyph;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_BitmapGlyphRec                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used for bitmap glyph images.  This really is a        */
+  /*    `sub-class' of `FT_GlyphRec'.                                      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root   :: The root FT_Glyph fields.                                */
+  /*                                                                       */
+  /*    left   :: The left-side bearing, i.e., the horizontal distance     */
+  /*              from the current pen position to the left border of the  */
+  /*              glyph bitmap.                                            */
+  /*                                                                       */
+  /*    top    :: The top-side bearing, i.e., the vertical distance from   */
+  /*              the current pen position to the top border of the glyph  */
+  /*              bitmap.  This distance is positive for upwards-y!        */
+  /*                                                                       */
+  /*    bitmap :: A descriptor for the bitmap.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You can typecast FT_Glyph to FT_BitmapGlyph if you have            */
+  /*    glyph->format == ft_glyph_format_bitmap.  This lets you access     */
+  /*    the bitmap's contents easily.                                      */
+  /*                                                                       */
+  /*    The corresponding pixel buffer is always owned by the BitmapGlyph  */
+  /*    and is thus created and destroyed with it.                         */
+  /*                                                                       */
+  typedef struct  FT_BitmapGlyphRec_
+  {
+    FT_GlyphRec  root;
+    FT_Int       left;
+    FT_Int       top;
+    FT_Bitmap    bitmap;
+
+  } FT_BitmapGlyphRec, *FT_BitmapGlyph;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_OutlineGlyphRec                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used for outline (vectorial) glyph images.  This       */
+  /*    really is a `sub-class' of `FT_GlyphRec'.                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root    :: The root FT_Glyph fields.                               */
+  /*                                                                       */
+  /*    outline :: A descriptor for the outline.                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You can typecast FT_Glyph to FT_OutlineGlyph if you have           */
+  /*    glyph->format == ft_glyph_format_outline.  This lets you access    */
+  /*    the outline's content easily.                                      */
+  /*                                                                       */
+  /*    As the outline is extracted from a glyph slot, its coordinates are */
+  /*    expressed normally in 26.6 pixels, unless the flag                 */
+  /*    FT_LOAD_NO_SCALE was used in FT_Load_Glyph() or FT_Load_Char().    */
+  /*                                                                       */
+  /*    The outline's tables are always owned by the object and are        */
+  /*    destroyed with it.                                                 */
+  /*                                                                       */
+  typedef struct  FT_OutlineGlyphRec_
+  {
+    FT_GlyphRec  root;
+    FT_Outline   outline;
+
+  } FT_OutlineGlyphRec, *FT_OutlineGlyph;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Glyph                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to extract a glyph image from a slot.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot   :: A handle to the source glyph slot.                       */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aglyph :: A handle to the glyph object.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Get_Glyph( FT_GlyphSlot  slot,
+                FT_Glyph     *aglyph );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_Copy                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to copy a glyph image.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    source :: A handle to the source glyph object.                     */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    target :: A handle to the target glyph object.  0 in case of       */
+  /*              error.                                                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Glyph_Copy( FT_Glyph   source,
+                 FT_Glyph  *target );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_Transform                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Transforms a glyph image if its format is scalable.                */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    glyph  :: A handle to the target glyph object.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    matrix :: A pointer to a 2x2 matrix to apply.                      */
+  /*                                                                       */
+  /*    delta  :: A pointer to a 2d vector to apply.  Coordinates are      */
+  /*              expressed in 1/64th of a pixel.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code (the glyph format is not scalable if it is     */
+  /*    not zero).                                                         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The 2x2 transformation matrix is also applied to the glyph's       */
+  /*    advance vector.                                                    */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Glyph_Transform( FT_Glyph    glyph,
+                      FT_Matrix*  matrix,
+                      FT_Vector*  delta );
+
+  /* */
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_Get_CBox                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns a glyph's `control box'.  The control box encloses all the */
+  /*    outline's points, including Bezier control points.  Though it      */
+  /*    coincides with the exact bounding box for most glyphs, it can be   */
+  /*    slightly larger in some situations (like when rotating an outline  */
+  /*    which contains Bezier outside arcs).                               */
+  /*                                                                       */
+  /*    Computing the control box is very fast, while getting the bounding */
+  /*    box can take much more time as it needs to walk over all segments  */
+  /*    and arcs in the outline.  To get the latter, you can use the       */
+  /*    `ftbbox' component which is dedicated to this single task.         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph :: A handle to the source glyph object.                      */
+  /*                                                                       */
+  /*    mode  :: The mode which indicates how to interpret the returned    */
+  /*             bounding box values.                                      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    acbox :: The glyph coordinate bounding box.  Coordinates are       */
+  /*             expressed in 1/64th of pixels if it is grid-fitted.       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Coordinates are relative to the glyph origin, using the Y-upwards  */
+  /*    convention.                                                        */
+  /*                                                                       */
+  /*    If the glyph has been loaded with FT_LOAD_NO_SCALE, `bbox_mode'    */
+  /*    must be set to `ft_glyph_bbox_unscaled' to get unscaled font       */
+  /*    units.                                                             */
+  /*                                                                       */
+  /*    If `bbox_mode' is set to `ft_glyph_bbox_subpixels' the bbox        */
+  /*    coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels).   */
+  /*                                                                       */
+  /*    Note that the maximum coordinates are exclusive, which means that  */
+  /*    one can compute the width and height of the glyph image (be it in  */
+  /*    integer or 26.6 pixels) as:                                        */
+  /*                                                                       */
+  /*      width  = bbox.xMax - bbox.xMin;                                  */
+  /*      height = bbox.yMax - bbox.yMin;                                  */
+  /*                                                                       */
+  /*    Note also that for 26.6 coordinates, if `bbox_mode' is set to      */
+  /*    `ft_glyph_bbox_gridfit', the coordinates will also be grid-fitted, */
+  /*    which corresponds to:                                              */
+  /*                                                                       */
+  /*      bbox.xMin = FLOOR(bbox.xMin);                                    */
+  /*      bbox.yMin = FLOOR(bbox.yMin);                                    */
+  /*      bbox.xMax = CEILING(bbox.xMax);                                  */
+  /*      bbox.yMax = CEILING(bbox.yMax);                                  */
+  /*                                                                       */
+  /*    To get the bbox in pixel coordinates, set `bbox_mode' to           */
+  /*    `ft_glyph_bbox_truncate'.                                          */
+  /*                                                                       */
+  /*    To get the bbox in grid-fitted pixel coordinates, set `bbox_mode'  */
+  /*    to `ft_glyph_bbox_pixels'.                                         */
+  /*                                                                       */
+  /*    The default value for `bbox_mode' is `ft_glyph_bbox_pixels'.       */
+  /*                                                                       */
+  enum
+  {
+    ft_glyph_bbox_unscaled  = 0, /* return unscaled font units           */
+    ft_glyph_bbox_subpixels = 0, /* return unfitted 26.6 coordinates     */
+    ft_glyph_bbox_gridfit   = 1, /* return grid-fitted 26.6 coordinates  */
+    ft_glyph_bbox_truncate  = 2, /* return coordinates in integer pixels */
+    ft_glyph_bbox_pixels    = 3  /* return grid-fitted pixel coordinates */
+  };
+
+
+  FT_EXPORT( void )
+  FT_Glyph_Get_CBox( FT_Glyph  glyph,
+                     FT_UInt   bbox_mode,
+                     FT_BBox  *acbox );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Glyph_To_Bitmap                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts a given glyph object to a bitmap glyph object.            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    the_glyph   :: A pointer to a handle to the target glyph.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    render_mode :: A set of bit flags that describe how the data is    */
+  /*                                                                       */
+  /*                                                                       */
+  /*    origin      :: A pointer to a vector used to translate the glyph   */
+  /*                   image before rendering.  Can be 0 (if no            */
+  /*                   translation).  The origin is expressed in           */
+  /*                   26.6 pixels.                                        */
+  /*                                                                       */
+  /*    destroy     :: A boolean that indicates that the original glyph    */
+  /*                   image should be destroyed by this function.  It is  */
+  /*                   never destroyed in case of error.                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The glyph image is translated with the `origin' vector before      */
+  /*    rendering.  In case of error, it it translated back to its         */
+  /*    original position and the glyph is left untouched.                 */
+  /*                                                                       */
+  /*    The first parameter is a pointer to a FT_Glyph handle, that will   */
+  /*    be replaced by this function.  Typically, you would use (omitting  */
+  /*    error handling):                                                   */
+  /*                                                                       */
+  /*                                                                       */
+  /*      {                                                                */
+  /*        FT_Glyph        glyph;                                         */
+  /*        FT_BitmapGlyph  glyph_bitmap;                                  */
+  /*                                                                       */
+  /*                                                                       */
+  /*        // load glyph                                                  */
+  /*        error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT );     */
+  /*                                                                       */
+  /*        // extract glyph image                                         */
+  /*        error = FT_Get_Glyph( face->glyph, &glyph );                   */
+  /*                                                                       */
+  /*        // convert to a bitmap (default render mode + destroy old)     */
+  /*        if ( glyph->format != ft_glyph_format_bitmap )                 */
+  /*        {                                                              */
+  /*          error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_default,  */
+  /*                                      0, 1 );                          */
+  /*          if ( error ) // glyph unchanged                              */
+  /*            ...                                                        */
+  /*        }                                                              */
+  /*                                                                       */
+  /*        // access bitmap content by typecasting                        */
+  /*        glyph_bitmap = (FT_BitmapGlyph)glyph;                          */
+  /*                                                                       */
+  /*        // do funny stuff with it, like blitting/drawing               */
+  /*        ...                                                            */
+  /*                                                                       */
+  /*        // discard glyph image (bitmap or not)                         */
+  /*        FT_Done_Glyph( glyph );                                        */
+  /*      }                                                                */
+  /*                                                                       */
+  /*                                                                       */
+  /*    This function will always fail if the glyph's format isn't         */
+  /*    scalable.                                                          */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Glyph_To_Bitmap( FT_Glyph*   the_glyph,
+                      FT_ULong    render_mode,
+                      FT_Vector*  origin,
+                      FT_Bool     destroy );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given glyph.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph :: A handle to the target glyph object.                      */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Done_Glyph( FT_Glyph  glyph );
+
+
+  /* other helpful functions */
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    computations                                                       */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Matrix_Multiply                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Performs the matrix operation `b = a*b'.                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    a :: A pointer to matrix `a'.                                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    b :: A pointer to matrix `b'.                                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The result is undefined if either `a' or `b' is zero.              */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Matrix_Multiply( FT_Matrix*  a,
+                      FT_Matrix*  b );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Matrix_Invert                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Inverts a 2x2 matrix.  Returns an error if it can't be inverted.   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    matrix :: A pointer to the target matrix.  Remains untouched in    */
+  /*              case of error.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Matrix_Invert( FT_Matrix*  matrix );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTGLYPH_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftimage.h b/libraries/freetype-2.0.5/include/freetype/ftimage.h
new file mode 100644 (file)
index 0000000..21f320d
--- /dev/null
@@ -0,0 +1,1109 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftimage.h                                                              */
+/*                                                                         */
+/*    FreeType glyph image formats and default raster interface            */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Note: A `raster' is simply a scan-line converter, used to render      */
+  /*       FT_Outlines into FT_Bitmaps.                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTIMAGE_H__
+#define __FTIMAGE_H__
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    basic_types                                                        */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Pos                                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The type FT_Pos is a 32-bit integer used to store vectorial        */
+  /*    coordinates.  Depending on the context, these can represent        */
+  /*    distances in integer font units, or 26.6 fixed float pixel         */
+  /*    coordinates.                                                       */
+  /*                                                                       */
+  typedef signed long  FT_Pos;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Vector                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to store a 2D vector; coordinates are of   */
+  /*    the FT_Pos type.                                                   */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    x :: The horizontal coordinate.                                    */
+  /*    y :: The vertical coordinate.                                      */
+  /*                                                                       */
+  typedef struct  FT_Vector_
+  {
+    FT_Pos  x;
+    FT_Pos  y;
+
+  } FT_Vector;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_BBox                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to hold an outline's bounding box, i.e., the      */
+  /*    coordinates of its extrema in the horizontal and vertical          */
+  /*    directions.                                                        */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    xMin :: The horizontal minimum (left-most).                        */
+  /*                                                                       */
+  /*    yMin :: The vertical minimum (bottom-most).                        */
+  /*                                                                       */
+  /*    xMax :: The horizontal maximum (right-most).                       */
+  /*                                                                       */
+  /*    yMax :: The vertical maximum (top-most).                           */
+  /*                                                                       */
+  typedef struct  FT_BBox_
+  {
+    FT_Pos  xMin, yMin;
+    FT_Pos  xMax, yMax;
+
+  } FT_BBox;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Pixel_Mode                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration type used to describe the format of pixels in a     */
+  /*    given bitmap.  Note that additional formats may be added in the    */
+  /*    future.                                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_pixel_mode_mono  :: A monochrome bitmap (1 bit/pixel).          */
+  /*                                                                       */
+  /*    ft_pixel_mode_grays :: An 8-bit gray-levels bitmap.  Note that the */
+  /*                           total number of gray levels is given in the */
+  /*                           `num_grays' field of the FT_Bitmap          */
+  /*                           structure.                                  */
+  /*                                                                       */
+  /*    ft_pixel_mode_pal2  :: A 2-bit paletted bitmap.                    */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_pal4  :: A 4-bit paletted bitmap.                    */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_pal8  :: An 8-bit paletted bitmap.                   */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_rgb15 :: A 15-bit RGB bitmap.  Uses 5:5:5 encoding.  */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_rgb16 :: A 16-bit RGB bitmap.  Uses 5:6:5 encoding.  */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_rgb24 :: A 24-bit RGB bitmap.                        */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /*    ft_pixel_mode_rgb32 :: A 32-bit RGB bitmap.                        */
+  /*                           Currently unused by FreeType.               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Some anti-aliased bitmaps might be embedded in TrueType fonts      */
+  /*    using formats pal2 or pal4, though no fonts presenting those have  */
+  /*    been found to date.                                                */
+  /*                                                                       */
+  typedef enum  FT_Pixel_Mode_
+  {
+    ft_pixel_mode_none = 0,
+    ft_pixel_mode_mono,
+    ft_pixel_mode_grays,
+    ft_pixel_mode_pal2,
+    ft_pixel_mode_pal4,
+    ft_pixel_mode_pal8,
+    ft_pixel_mode_rgb15,
+    ft_pixel_mode_rgb16,
+    ft_pixel_mode_rgb24,
+    ft_pixel_mode_rgb32,
+
+    ft_pixel_mode_max      /* do not remove */
+
+  } FT_Pixel_Mode;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Palette_Mode                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration type used to describe the format of a bitmap        */
+  /*    palette, used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8.      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_palette_mode_rgb  :: The palette is an array of 3-bytes RGB     */
+  /*                            records.                                   */
+  /*                                                                       */
+  /*    ft_palette_mode_rgba :: The palette is an array of 4-bytes RGBA    */
+  /*                            records.                                   */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by       */
+  /*    FreeType, these types are not handled by the library itself.       */
+  /*                                                                       */
+  typedef enum  FT_Palette_Mode_
+  {
+    ft_palette_mode_rgb = 0,
+    ft_palette_mode_rgba,
+
+    ft_palettte_mode_max   /* do not remove */
+
+  } FT_Palette_Mode;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Bitmap                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe a bitmap or pixmap to the raster.     */
+  /*    Note that we now manage pixmaps of various depths through the      */
+  /*    `pixel_mode' field.                                                */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    rows         :: The number of bitmap rows.                         */
+  /*                                                                       */
+  /*    width        :: The number of pixels in bitmap row.                */
+  /*                                                                       */
+  /*    pitch        :: The pitch's absolute value is the number of bytes  */
+  /*                    taken by one bitmap row, including padding.        */
+  /*                    However, the pitch is positive when the bitmap has */
+  /*                    a `down' flow, and negative when it has an `up'    */
+  /*                    flow.  In all cases, the pitch is an offset to add */
+  /*                    to a bitmap pointer in order to go down one row.   */
+  /*                                                                       */
+  /*    buffer       :: A typeless pointer to the bitmap buffer.  This     */
+  /*                    value should be aligned on 32-bit boundaries in    */
+  /*                    most cases.                                        */
+  /*                                                                       */
+  /*    num_grays    :: This field is only used with                       */
+  /*                    `ft_pixel_mode_grays'; it gives the number of gray */
+  /*                    levels used in the bitmap.                         */
+  /*                                                                       */
+  /*    pixel_mode   :: The pixel_mode, i.e., how pixel bits are stored.   */
+  /*                                                                       */
+  /*    palette_mode :: This field is only used with paletted pixel modes; */
+  /*                    it indicates how the palette is stored.            */
+  /*                                                                       */
+  /*    palette      :: A typeless pointer to the bitmap palette; only     */
+  /*                    used for paletted pixel modes.                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*   For now, the only pixel mode supported by FreeType are mono and     */
+  /*   grays.  However, drivers might be added in the future to support    */
+  /*   more `colorful' options.                                            */
+  /*                                                                       */
+  /*   When using pixel modes pal2, pal4 and pal8 with a void `palette'    */
+  /*   field, a gray pixmap with respectively 4, 16, and 256 levels of     */
+  /*   gray is assumed.  This, in order to be compatible with some         */
+  /*   embedded bitmap formats defined in the TrueType specification.      */
+  /*                                                                       */
+  /*   Note that no font was found presenting such embedded bitmaps, so    */
+  /*   this is currently completely unhandled by the library.              */
+  /*                                                                       */
+  typedef struct  FT_Bitmap_
+  {
+    int             rows;
+    int             width;
+    int             pitch;
+    unsigned char*  buffer;
+    short           num_grays;
+    char            pixel_mode;
+    char            palette_mode;
+    void*           palette;
+
+  } FT_Bitmap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    outline_processing                                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Outline                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure is used to describe an outline to the scan-line     */
+  /*    converter.                                                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    n_contours :: The number of contours in the outline.               */
+  /*                                                                       */
+  /*    n_points   :: The number of points in the outline.                 */
+  /*                                                                       */
+  /*    points     :: A pointer to an array of `n_points' FT_Vector        */
+  /*                  elements, giving the outline's point coordinates.    */
+  /*                                                                       */
+  /*    tags       :: A pointer to an array of `n_points' chars, giving    */
+  /*                  each outline point's type.  If bit 0 is unset, the   */
+  /*                  point is `off' the curve, i.e. a Bezier control      */
+  /*                  point, while it is `on' when set.                    */
+  /*                                                                       */
+  /*                  Bit 1 is meaningful for `off' points only.  If set,  */
+  /*                  it indicates a third-order Bezier arc control point; */
+  /*                  and a second-order control point if unset.           */
+  /*                                                                       */
+  /*    contours   :: An array of `n_contours' shorts, giving the end      */
+  /*                  point of each contour within the outline.  For       */
+  /*                  example, the first contour is defined by the points  */
+  /*                  `0' to `contours[0]', the second one is defined by   */
+  /*                  the points `contours[0]+1' to `contours[1]', etc.    */
+  /*                                                                       */
+  /*    flags      :: A set of bit flags used to characterize the outline  */
+  /*                  and give hints to the scan-converter and hinter on   */
+  /*                  how to convert/grid-fit it.  See FT_Outline_Flags.   */
+  /*                                                                       */
+  typedef struct  FT_Outline_
+  {
+    short       n_contours;      /* number of contours in glyph        */
+    short       n_points;        /* number of points in the glyph      */
+
+    FT_Vector*  points;          /* the outline's points               */
+    char*       tags;            /* the points flags                   */
+    short*      contours;        /* the contour end points             */
+
+    int         flags;           /* outline masks                      */
+
+  } FT_Outline;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*   FT_Outline_Flags                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple type used to enumerates the flags in an outline's         */
+  /*    `outline_flags' field.                                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_outline_owner          :: If set, this flag indicates that the  */
+  /*                                 outline's field arrays (i.e.          */
+  /*                                 `points', `flags' & `contours') are   */
+  /*                                 `owned' by the outline object, and    */
+  /*                                 should thus be freed when it is       */
+  /*                                 destroyed.                            */
+  /*                                                                       */
+  /*   ft_outline_even_odd_fill   :: By default, outlines are filled using */
+  /*                                 the non-zero winding rule.  If set to */
+  /*                                 1, the outline will be filled using   */
+  /*                                 the even-odd fill rule (only works    */
+  /*                                 with the smooth raster).              */
+  /*                                                                       */
+  /*   ft_outline_reverse_fill    :: By default, outside contours of an    */
+  /*                                 outline are oriented in clock-wise    */
+  /*                                 direction, as defined in the TrueType */
+  /*                                 specification.  This flag is set if   */
+  /*                                 the outline uses the opposite         */
+  /*                                 direction (typically for Type 1       */
+  /*                                 fonts).  This flag is ignored by the  */
+  /*                                 scan-converter.  However, it is very  */
+  /*                                 important for the auto-hinter.        */
+  /*                                                                       */
+  /*   ft_outline_ignore_dropouts :: By default, the scan converter will   */
+  /*                                 try to detect drop-outs in an outline */
+  /*                                 and correct the glyph bitmap to       */
+  /*                                 ensure consistent shape continuity.   */
+  /*                                 If set, this flag hints the scan-line */
+  /*                                 converter to ignore such cases.       */
+  /*                                                                       */
+  /*   ft_outline_high_precision  :: This flag indicates that the          */
+  /*                                 scan-line converter should try to     */
+  /*                                 convert this outline to bitmaps with  */
+  /*                                 the highest possible quality.  It is  */
+  /*                                 typically set for small character     */
+  /*                                 sizes.  Note that this is only a      */
+  /*                                 hint, that might be completely        */
+  /*                                 ignored by a given scan-converter.    */
+  /*                                                                       */
+  /*   ft_outline_single_pass     :: This flag is set to force a given     */
+  /*                                 scan-converter to only use a single   */
+  /*                                 pass over the outline to render a     */
+  /*                                 bitmap glyph image.  Normally, it is  */
+  /*                                 set for very large character sizes.   */
+  /*                                 It is only a hint, that might be      */
+  /*                                 completely ignored by a given         */
+  /*                                 scan-converter.                       */
+  /*                                                                       */
+  typedef enum  FT_Outline_Flags_
+  {
+    ft_outline_none            = 0,
+    ft_outline_owner           = 1,
+    ft_outline_even_odd_fill   = 2,
+    ft_outline_reverse_fill    = 4,
+    ft_outline_ignore_dropouts = 8,
+    ft_outline_high_precision  = 256,
+    ft_outline_single_pass     = 512
+
+  } FT_Outline_Flags;
+
+  /* */
+
+#define FT_CURVE_TAG( flag )  ( flag & 3 )
+
+#define FT_Curve_Tag_On           1
+#define FT_Curve_Tag_Conic        0
+#define FT_Curve_Tag_Cubic        2
+
+#define FT_Curve_Tag_Touch_X      8  /* reserved for the TrueType hinter */
+#define FT_Curve_Tag_Touch_Y     16  /* reserved for the TrueType hinter */
+
+#define FT_Curve_Tag_Touch_Both  ( FT_Curve_Tag_Touch_X | \
+                                   FT_Curve_Tag_Touch_Y )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Outline_MoveTo_Func                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function pointer type used to describe the signature of a `move  */
+  /*    to' function during outline walking/decomposition.                 */
+  /*                                                                       */
+  /*    A `move to' is emitted to start a new contour in an outline.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    to   :: A pointer to the target point of the `move to'.            */
+  /*                                                                       */
+  /*    user :: A typeless pointer which is passed from the caller of the  */
+  /*            decomposition function.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  typedef int
+  (*FT_Outline_MoveTo_Func)( FT_Vector*  to,
+                             void*       user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Outline_LineTo_Func                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function pointer type used to describe the signature of a `line  */
+  /*    to' function during outline walking/decomposition.                 */
+  /*                                                                       */
+  /*    A `line to' is emitted to indicate a segment in the outline.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    to   :: A pointer to the target point of the `line to'.            */
+  /*                                                                       */
+  /*    user :: A typeless pointer which is passed from the caller of the  */
+  /*            decomposition function.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  typedef int
+  (*FT_Outline_LineTo_Func)( FT_Vector*  to,
+                             void*       user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Outline_ConicTo_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function pointer type use to describe the signature of a `conic  */
+  /*    to' function during outline walking/decomposition.                 */
+  /*                                                                       */
+  /*    A `conic to' is emitted to indicate a second-order Bezier arc in   */
+  /*    the outline.                                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    control :: An intermediate control point between the last position */
+  /*               and the new target in `to'.                             */
+  /*                                                                       */
+  /*    to      :: A pointer to the target end point of the conic arc.     */
+  /*                                                                       */
+  /*    user    :: A typeless pointer which is passed from the caller of   */
+  /*               the decomposition function.                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  typedef int
+  (*FT_Outline_ConicTo_Func)( FT_Vector*  control,
+                              FT_Vector*  to,
+                              void*       user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Outline_CubicTo_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function pointer type used to describe the signature of a `cubic */
+  /*    to' function during outline walking/decomposition.                 */
+  /*                                                                       */
+  /*    A `cubic to' is emitted to indicate a third-order Bezier arc.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    control1 :: A pointer to the first Bezier control point.           */
+  /*                                                                       */
+  /*    control2 :: A pointer to the second Bezier control point.          */
+  /*                                                                       */
+  /*    to       :: A pointer to the target end point.                     */
+  /*                                                                       */
+  /*    user     :: A typeless pointer which is passed from the caller of  */
+  /*                the decomposition function.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  typedef int
+  (*FT_Outline_CubicTo_Func)( FT_Vector*  control1,
+                              FT_Vector*  control2,
+                              FT_Vector*  to,
+                              void*       user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Outline_Funcs                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure to hold various function pointers used during outline  */
+  /*    decomposition in order to emit segments, conic, and cubic Beziers, */
+  /*    as well as `move to' and `close to' operations.                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    move_to  :: The `move to' emitter.                                 */
+  /*                                                                       */
+  /*    line_to  :: The segment emitter.                                   */
+  /*                                                                       */
+  /*    conic_to :: The second-order Bezier arc emitter.                   */
+  /*                                                                       */
+  /*    cubic_to :: The third-order Bezier arc emitter.                    */
+  /*                                                                       */
+  /*    shift    :: The shift that is applied to coordinates before they   */
+  /*                are sent to the emitter.                               */
+  /*                                                                       */
+  /*    delta    :: The delta that is applied to coordinates before they   */
+  /*                are sent to the emitter, but after the shift.          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The point coordinates sent to the emitters are the transformed     */
+  /*    version of the original coordinates (this is important for high    */
+  /*    accuracy during scan-conversion).  The transformation is simple:   */
+  /*                                                                       */
+  /*      x' = (x << shift) - delta                                        */
+  /*      y' = (x << shift) - delta                                        */
+  /*                                                                       */
+  /*    Set the value of `shift' and `delta' to 0 to get the original      */
+  /*    point coordinates.                                                 */
+  /*                                                                       */
+  typedef struct  FT_Outline_Funcs_
+  {
+    FT_Outline_MoveTo_Func   move_to;
+    FT_Outline_LineTo_Func   line_to;
+    FT_Outline_ConicTo_Func  conic_to;
+    FT_Outline_CubicTo_Func  cubic_to;
+
+    int                      shift;
+    FT_Pos                   delta;
+
+  } FT_Outline_Funcs;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    basic_types                                                        */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Macro>                                                               */
+  /*    FT_IMAGE_TAG                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This macro converts four letter tags into an unsigned long.        */
+  /*                                                                       */
+#ifndef FT_IMAGE_TAG
+#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 )  \
+          value = ( ( (unsigned long)_x1 << 24 ) | \
+                    ( (unsigned long)_x2 << 16 ) | \
+                    ( (unsigned long)_x3 << 8  ) | \
+                      (unsigned long)_x4         )
+#endif /* FT_IMAGE_TAG */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Glyph_Format                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration type used to describe the format of a given glyph   */
+  /*    image.  Note that this version of FreeType only supports two image */
+  /*    formats, even though future font drivers will be able to register  */
+  /*    their own format.                                                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_glyph_format_composite :: The glyph image is a composite of     */
+  /*                                 several other images.  This glyph     */
+  /*                                 format is _only_ used with the        */
+  /*                                 FT_LOAD_FLAG_NO_RECURSE flag (XXX:    */
+  /*                                 Which is currently unimplemented).    */
+  /*                                                                       */
+  /*    ft_glyph_format_bitmap    :: The glyph image is a bitmap, and can  */
+  /*                                 be described as a FT_Bitmap.          */
+  /*                                                                       */
+  /*    ft_glyph_format_outline   :: The glyph image is a vectorial image  */
+  /*                                 made of bezier control points, and    */
+  /*                                 can be described as a FT_Outline.     */
+  /*                                                                       */
+  /*    ft_glyph_format_plotter   :: The glyph image is a vectorial image  */
+  /*                                 made of plotter lines (some T1 fonts  */
+  /*                                 like Hershey contain glyph in this    */
+  /*                                 format).                              */
+  /*                                                                       */
+  typedef enum  FT_Glyph_Format_
+  {
+    FT_IMAGE_TAG( ft_glyph_format_none, 0, 0, 0, 0 ),
+
+    FT_IMAGE_TAG( ft_glyph_format_composite, 'c', 'o', 'm', 'p' ),
+    FT_IMAGE_TAG( ft_glyph_format_bitmap,    'b', 'i', 't', 's' ),
+    FT_IMAGE_TAG( ft_glyph_format_outline,   'o', 'u', 't', 'l' ),
+    FT_IMAGE_TAG( ft_glyph_format_plotter,   'p', 'l', 'o', 't' )
+
+  } FT_Glyph_Format;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****            R A S T E R   D E F I N I T I O N S                *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A raster is a scan converter, in charge of rendering an outline into  */
+  /* a a bitmap.  This section contains the public API for rasters.        */
+  /*                                                                       */
+  /* Note that in FreeType 2, all rasters are now encapsulated within      */
+  /* specific modules called `renderers'.  See `freetype/ftrender.h' for   */
+  /* more details on renderers.                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    Raster                                                             */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Scanline converter                                                 */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    How vectorial outlines are converted into bitmaps and pixmaps.     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This section contains technical definitions.                       */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Raster                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle (pointer) to a raster object.  Each object can be used    */
+  /*    independently to convert an outline into a bitmap or pixmap.       */
+  /*                                                                       */
+  typedef struct FT_RasterRec_*  FT_Raster;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Span                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a single span of gray (or black) pixels  */
+  /*    when rendering a monochrome or anti-aliased bitmap.                */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    x        :: The span's horizontal start position.                  */
+  /*                                                                       */
+  /*    len      :: The span's length in pixels.                           */
+  /*                                                                       */
+  /*    coverage :: The span color/coverage, ranging from 0 (background)   */
+  /*                to 255 (foreground).  Only used for anti-aliased       */
+  /*                rendering.                                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This structure is used by the span drawing callback type named     */
+  /*    FT_Raster_Span_Func(), which takes the y-coordinate of the span as */
+  /*    a parameter.                                                       */
+  /*                                                                       */
+  /*    The coverage value is always between 0 and 255, even if the number */
+  /*    of gray levels have been set through FT_Set_Gray_Levels().         */
+  /*                                                                       */
+  typedef struct  FT_Span_
+  {
+    short           x;
+    unsigned short  len;
+    unsigned char   coverage;
+
+  } FT_Span;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_Span_Func                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used as a call-back by the anti-aliased renderer in     */
+  /*    order to let client applications draw themselves the gray pixel    */
+  /*    spans on each scan line.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    y     :: The scanline's y-coordinate.                              */
+  /*                                                                       */
+  /*    count :: The number of spans to draw on this scanline.             */
+  /*                                                                       */
+  /*    spans :: A table of `count' spans to draw on the scanline.         */
+  /*                                                                       */
+  /*    user  :: User-supplied data that is passed to the callback.        */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This callback allows client applications to directly render the    */
+  /*    gray spans of the anti-aliased bitmap to any kind of surfaces.     */
+  /*                                                                       */
+  /*    This can be used to write anti-aliased outlines directly to a      */
+  /*    given background bitmap, and even perform translucency.            */
+  /*                                                                       */
+  /*    Note that the `count' field cannot be greater than a fixed value   */
+  /*    defined by the FT_MAX_GRAY_SPANS configuration macro in            */
+  /*    ftoption.h.  By default, this value is set to 32, which means that */
+  /*    if there are more than 32 spans on a given scanline, the callback  */
+  /*    will be called several times with the same `y' parameter in order  */
+  /*    to draw all callbacks.                                             */
+  /*                                                                       */
+  /*    Otherwise, the callback is only called once per scan-line, and     */
+  /*    only for those scanlines that do have `gray' pixels on them.       */
+  /*                                                                       */
+  typedef void
+  (*FT_Raster_Span_Func)( int       y,
+                          int       count,
+                          FT_Span*  spans,
+                          void*     user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_BitTest_Func                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used as a call-back by the monochrome scan-converter    */
+  /*    to test whether a given target pixel is already set to the drawing */
+  /*    `color'.  These tests are crucial to implement drop-out control    */
+  /*    per-se the TrueType spec.                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    y     :: The pixel's y-coordinate.                                 */
+  /*                                                                       */
+  /*    x     :: The pixel's x-coordinate.                                 */
+  /*                                                                       */
+  /*    user  :: User-supplied data that is passed to the callback.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   1 if the pixel is `set', 0 otherwise.                               */
+  /*                                                                       */
+  typedef int
+  (*FT_Raster_BitTest_Func)( int    y,
+                             int    x,
+                             void*  user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_BitSet_Func                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used as a call-back by the monochrome scan-converter    */
+  /*    to set an individual target pixel.  This is crucial to implement   */
+  /*    drop-out control according to the TrueType specification.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    y     :: The pixel's y-coordinate.                                 */
+  /*                                                                       */
+  /*    x     :: The pixel's x-coordinate.                                 */
+  /*                                                                       */
+  /*    user  :: User-supplied data that is passed to the callback.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    1 if the pixel is `set', 0 otherwise.                              */
+  /*                                                                       */
+  typedef void
+  (*FT_Raster_BitSet_Func)( int    y,
+                            int    x,
+                            void*  user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    FT_Raster_Flag                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An enumeration to list the bit flags as used in the `flags' field  */
+  /*    of a FT_Raster_Params structure.                                   */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ft_raster_flag_default :: This value is 0.                         */
+  /*                                                                       */
+  /*    ft_raster_flag_aa      :: This flag is set to indicate that an     */
+  /*                              anti-aliased glyph image should be       */
+  /*                              generated.  Otherwise, it will be        */
+  /*                              monochrome (1-bit)                       */
+  /*                                                                       */
+  /*    ft_raster_flag_direct  :: This flag is set to indicate direct      */
+  /*                              rendering.  In this mode, client         */
+  /*                              applications must provide their own span */
+  /*                              callback.  This lets them directly       */
+  /*                              draw or compose over an existing bitmap. */
+  /*                              If this bit is not set, the target       */
+  /*                              pixmap's buffer _must_ be zeroed before  */
+  /*                              rendering.                               */
+  /*                                                                       */
+  /*                              Note that for now, direct rendering is   */
+  /*                              only possible with anti-aliased glyphs.  */
+  /*                                                                       */
+  /*    ft_raster_flag_clip    :: This flag is only used in direct         */
+  /*                              rendering mode.  If set, the output will */
+  /*                              be clipped to a box specified in the     */
+  /*                              "clip_box" field of the FT_Raster_Params */
+  /*                              structure.                               */
+  /*                                                                       */
+  /*                              Note that by default, the glyph bitmap   */
+  /*                              is clipped to the target pixmap, except  */
+  /*                              in direct rendering mode where all spans */
+  /*                              are generated if no clipping box is set. */
+  /*                                                                       */
+  typedef  enum
+  {
+    ft_raster_flag_default = 0,
+    ft_raster_flag_aa      = 1,
+    ft_raster_flag_direct  = 2,
+    ft_raster_flag_clip    = 4
+
+  } FT_Raster_Flag;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Raster_Params                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure to hold the arguments used by a raster's render        */
+  /*    function.                                                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    target      :: The target bitmap.                                  */
+  /*                                                                       */
+  /*    source      :: A pointer to the source glyph image (e.g. an        */
+  /*                   FT_Outline).                                        */
+  /*                                                                       */
+  /*    flags       :: The rendering flags.                                */
+  /*                                                                       */
+  /*    gray_spans  :: The gray span drawing callback.                     */
+  /*                                                                       */
+  /*    black_spans :: The black span drawing callback.                    */
+  /*                                                                       */
+  /*    bit_test    :: The bit test callback.                              */
+  /*                                                                       */
+  /*    bit_set     :: The bit set callback.                               */
+  /*                                                                       */
+  /*    user        :: User-supplied data that is passed to each drawing   */
+  /*                   callback.                                           */
+  /*                                                                       */
+  /*    clip_box    :: an optional clipping box. It is only used in        */
+  /*                   direct rendering mode                               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An anti-aliased glyph bitmap is drawn if the ft_raster_flag_aa bit */
+  /*    flag is set in the `flags' field, otherwise a monochrome bitmap    */
+  /*    will be generated.                                                 */
+  /*                                                                       */
+  /*    If the ft_raster_flag_direct bit flag is set in `flags', the       */
+  /*    raster will call the `gray_spans' callback to draw gray pixel      */
+  /*    spans, in the case of an aa glyph bitmap, it will call             */
+  /*    `black_spans', and `bit_test' and `bit_set' in the case of a       */
+  /*    monochrome bitmap.  This allows direct composition over a          */
+  /*    pre-existing bitmap through user-provided callbacks to perform the */
+  /*    span drawing/composition.                                          */
+  /*                                                                       */
+  /*    Note that the `bit_test' and `bit_set' callbacks are required when */
+  /*    rendering a monochrome bitmap, as they are crucial to implement    */
+  /*    correct drop-out control as defined in the TrueType specification. */
+  /*                                                                       */
+  typedef struct  FT_Raster_Params_
+  {
+    FT_Bitmap*              target;
+    void*                   source;
+    int                     flags;
+    FT_Raster_Span_Func     gray_spans;
+    FT_Raster_Span_Func     black_spans;
+    FT_Raster_BitTest_Func  bit_test;
+    FT_Raster_BitSet_Func   bit_set;
+    void*                   user;
+    FT_BBox                 clip_box;
+
+  } FT_Raster_Params;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_New_Func                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to create a new raster object.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A handle to the memory allocator.                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    raster :: A handle to the new raster object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The `memory' parameter is a typeless pointer in order to avoid     */
+  /*    un-wanted dependencies on the rest of the FreeType code.  In       */
+  /*    practice, it is a FT_Memory, i.e., a handle to the standard        */
+  /*    FreeType memory allocator.  However, this field can be completely  */
+  /*    ignored by a given raster implementation.                          */
+  /*                                                                       */
+  typedef int
+  (*FT_Raster_New_Func)( void*       memory,
+                         FT_Raster*  raster );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_Done_Func                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to destroy a given raster object.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    raster :: A handle to the raster object.                           */
+  /*                                                                       */
+  typedef void
+  (*FT_Raster_Done_Func)( FT_Raster  raster );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_Reset_Func                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    FreeType provides an area of memory called the `render pool',      */
+  /*    available to all registered rasters.  This pool can be freely used */
+  /*    during a given scan-conversion but is shared by all rasters.  Its  */
+  /*    content is thus transient.                                         */
+  /*                                                                       */
+  /*    This function is called each time the render pool changes, or just */
+  /*    after a new raster object is created.                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    raster    :: A handle to the new raster object.                    */
+  /*                                                                       */
+  /*    pool_base :: The address in memory of the render pool.             */
+  /*                                                                       */
+  /*    pool_size :: The size in bytes of the render pool.                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Rasters can ignore the render pool and rely on dynamic memory      */
+  /*    allocation if they want to (a handle to the memory allocator is    */
+  /*    passed to the raster constructor).  However, this is not           */
+  /*    recommended for efficiency purposes.                               */
+  /*                                                                       */
+  typedef void
+  (*FT_Raster_Reset_Func)( FT_Raster       raster,
+                           unsigned char*  pool_base,
+                           unsigned long   pool_size );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_Set_Mode_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is a generic facility to change modes or attributes  */
+  /*    in a given raster.  This can be used for debugging purposes, or    */
+  /*    simply to allow implementation-specific `features' in a given      */
+  /*    raster module.                                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    raster :: A handle to the new raster object.                       */
+  /*                                                                       */
+  /*    mode   :: A 4-byte tag used to name the mode or property.          */
+  /*                                                                       */
+  /*    args   :: A pointer to the new mode/property to use.               */
+  /*                                                                       */
+  typedef int
+  (*FT_Raster_Set_Mode_Func)( FT_Raster      raster,
+                              unsigned long  mode,
+                              void*          args );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Raster_Render_Func                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   Invokes a given raster to scan-convert a given glyph image into a   */
+  /*   target bitmap.                                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    raster :: A handle to the raster object.                           */
+  /*                                                                       */
+  /*    params :: A pointer to a FT_Raster_Params structure used to store  */
+  /*              the rendering parameters.                                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Error code.  0 means success.                                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The exact format of the source image depends on the raster's glyph */
+  /*    format defined in its FT_Raster_Funcs structure.  It can be an     */
+  /*    FT_Outline or anything else in order to support a large array of   */
+  /*    glyph formats.                                                     */
+  /*                                                                       */
+  /*    Note also that the render function can fail and return a           */
+  /*    FT_Err_Unimplemented_Feature error code if the raster used does    */
+  /*    not support direct composition.                                    */
+  /*                                                                       */
+  /*    XXX: For now, the standard raster doesn't support direct           */
+  /*         composition but this should change for the final release (see */
+  /*         the files demos/src/ftgrays.c and demos/src/ftgrays2.c for    */
+  /*         examples of distinct implementations which support direct     */
+  /*         composition).                                                 */
+  /*                                                                       */
+  typedef int
+  (*FT_Raster_Render_Func)( FT_Raster          raster,
+                            FT_Raster_Params*  params );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Raster_Funcs                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*   A structure used to describe a given raster class to the library.   */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    glyph_format  :: The supported glyph format for this raster.       */
+  /*                                                                       */
+  /*    raster_new    :: The raster constructor.                           */
+  /*                                                                       */
+  /*    raster_reset  :: Used to reset the render pool within the raster.  */
+  /*                                                                       */
+  /*    raster_render :: A function to render a glyph into a given bitmap. */
+  /*                                                                       */
+  /*    raster_done   :: The raster destructor.                            */
+  /*                                                                       */
+  typedef struct  FT_Raster_Funcs_
+  {
+    FT_Glyph_Format          glyph_format;
+    FT_Raster_New_Func       raster_new;
+    FT_Raster_Reset_Func     raster_reset;
+    FT_Raster_Set_Mode_Func  raster_set_mode;
+    FT_Raster_Render_Func    raster_render;
+    FT_Raster_Done_Func      raster_done;
+
+  } FT_Raster_Funcs;
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTIMAGE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftlist.h b/libraries/freetype-2.0.5/include/freetype/ftlist.h
new file mode 100644 (file)
index 0000000..1c51017
--- /dev/null
@@ -0,0 +1,268 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftlist.h                                                               */
+/*                                                                         */
+/*    Generic list support for FreeType (specification).                   */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  This file implements functions relative to list processing.  Its     */
+  /*  data structures are defined in `freetype.h'.                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTLIST_H__
+#define __FTLIST_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    list_processing                                                    */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    List Processing                                                    */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    Simple management of lists.                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This section contains various definitions related to list          */
+  /*    processing using doubly-linked nodes.                              */
+  /*                                                                       */
+  /* <Order>                                                               */
+  /*    FT_List                                                            */
+  /*    FT_ListNode                                                        */
+  /*    FT_ListRec                                                         */
+  /*    FT_ListNodeRec                                                     */
+  /*                                                                       */
+  /*    FT_List_Add                                                        */
+  /*    FT_List_Insert                                                     */
+  /*    FT_List_Find                                                       */
+  /*    FT_List_Remove                                                     */
+  /*    FT_List_Up                                                         */
+  /*    FT_List_Iterate                                                    */
+  /*    FT_List_Iterator                                                   */
+  /*    FT_List_Finalize                                                   */
+  /*    FT_List_Destructor                                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Find                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finds the list node for a given listed object.                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    list :: A pointer to the parent list.                              */
+  /*    data :: The address of the listed object.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    List node.  NULL if it wasn't found.                               */
+  /*                                                                       */
+  FT_EXPORT( FT_ListNode )
+  FT_List_Find( FT_List  list,
+                void*    data );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Add                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Appends an element to the end of a list.                           */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    list :: A pointer to the parent list.                              */
+  /*    node :: The node to append.                                        */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_List_Add( FT_List      list,
+               FT_ListNode  node );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Insert                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Inserts an element at the head of a list.                          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    list :: A pointer to parent list.                                  */
+  /*    node :: The node to insert.                                        */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_List_Insert( FT_List      list,
+                  FT_ListNode  node );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Remove                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Removes a node from a list.  This function doesn't check whether   */
+  /*    the node is in the list!                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    node :: The node to remove.                                        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    list :: A pointer to the parent list.                              */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_List_Remove( FT_List      list,
+                  FT_ListNode  node );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Up                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Moves a node to the head/top of a list.  Used to maintain LRU      */
+  /*    lists.                                                             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    list :: A pointer to the parent list.                              */
+  /*    node :: The node to move.                                          */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_List_Up( FT_List      list,
+              FT_ListNode  node );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_List_Iterator                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An FT_List iterator function which is called during a list parse   */
+  /*    by FT_List_Iterate().                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    node :: The current iteration list node.                           */
+  /*                                                                       */
+  /*    user :: A typeless pointer passed to FT_List_Iterate().            */
+  /*            Can be used to point to the iteration's state.             */
+  /*                                                                       */
+  typedef FT_Error
+  (*FT_List_Iterator)( FT_ListNode  node,
+                       void*        user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Iterate                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parses a list and calls a given iterator function on each element. */
+  /*    Note that parsing is stopped as soon as one of the iterator calls  */
+  /*    returns a non-zero value.                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    list     :: A handle to the list.                                  */
+  /*    iterator :: An interator function, called on each node of the      */
+  /*                list.                                                  */
+  /*    user     :: A user-supplied field which is passed as the second    */
+  /*                argument to the iterator.                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result (a FreeType error code) of the last iterator call.      */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_List_Iterate( FT_List           list,
+                   FT_List_Iterator  iterator,
+                   void*             user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_List_Destructor                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An FT_List iterator function which is called during a list         */
+  /*    finalization by FT_List_Finalize() to destroy all elements in a    */
+  /*    given list.                                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    system :: The current system object.                               */
+  /*                                                                       */
+  /*    data   :: The current object to destroy.                           */
+  /*                                                                       */
+  /*    user   :: A typeless pointer passed to FT_List_Iterate().  It can  */
+  /*              be used to point to the iteration's state.               */
+  /*                                                                       */
+  typedef void
+  (*FT_List_Destructor)( FT_Memory  memory,
+                         void*      data,
+                         void*      user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_List_Finalize                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys all elements in the list as well as the list itself.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    list    :: A handle to the list.                                   */
+  /*                                                                       */
+  /*    destroy :: A list destructor that will be applied to each element  */
+  /*               of the list.                                            */
+  /*                                                                       */
+  /*    memory  :: The current memory object which handles deallocation.   */
+  /*                                                                       */
+  /*    user    :: A user-supplied field which is passed as the last       */
+  /*               argument to the destructor.                             */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_List_Finalize( FT_List             list,
+                    FT_List_Destructor  destroy,
+                    FT_Memory           memory,
+                    void*               user );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTLIST_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftmac.h b/libraries/freetype-2.0.5/include/freetype/ftmac.h
new file mode 100644 (file)
index 0000000..6a1b4c8
--- /dev/null
@@ -0,0 +1,104 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmac.h                                                                */
+/*                                                                         */
+/*    Additional Mac-specific API.                                         */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.     */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/*                                                                         */
+/* NOTE: Include this file after <freetype/freetype.h> and after the       */
+/*       Mac-specific <Types.h> header (or any other Mac header that       */
+/*       includes <Types.h>); we use Handle type.                          */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FT_MAC_H__
+#define __FT_MAC_H__
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    mac_specific                                                       */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Mac-Specific Interface                                             */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    Only available on the Macintosh.                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The following definitions are only available if FreeType is        */
+  /*    compiled on a Macintosh.                                           */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Face_From_FOND                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new face object from an FOND resource.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library resource.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    fond       :: An FOND resource.                                    */
+  /*                                                                       */
+  /*    face_index :: Only supported for the -1 `sanity check' special     */
+  /*                  case.                                                */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aface      :: A handle to a new face object.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Notes>                                                               */
+  /*    This function can be used to create FT_Face abjects from fonts     */
+  /*    that are installed in the system like so:                          */
+  /*                                                                       */
+  /*    {                                                                  */
+  /*      fond = GetResource( 'FOND', fontName );                          */
+  /*      error = FT_New_Face_From_FOND( library, fond, 0, &face );        */
+  /*    }                                                                  */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_New_Face_From_FOND( FT_Library  library,
+                         Handle      fond,
+                         FT_Long     face_index,
+                         FT_Face    *aface );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __FT_MAC_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftmm.h b/libraries/freetype-2.0.5/include/freetype/ftmm.h
new file mode 100644 (file)
index 0000000..5e681b2
--- /dev/null
@@ -0,0 +1,203 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmm.h                                                                 */
+/*                                                                         */
+/*    FreeType Multiple Master font interface (specification).             */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTMM_H__
+#define __FTMM_H__
+
+
+#include <ft2build.h>
+#include FT_TYPE1_TABLES_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    multiple_masters                                                   */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Multiple Masters                                                   */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    How to manage Multiple Masters fonts.                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The following types and functions are used to manage Multiple      */
+  /*    Master fonts, i.e. the selection of specific design instances by   */
+  /*    setting design axis coordinates.                                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_MM_Axis                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to model a given axis in design space for  */
+  /*    Multiple Masters fonts.                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    name    :: The axis's name.                                        */
+  /*                                                                       */
+  /*    minimum :: The axis's minimum design coordinate.                   */
+  /*                                                                       */
+  /*    maximum :: The axis's maximum design coordinate.                   */
+  /*                                                                       */
+  typedef struct  FT_MM_Axis_
+  {
+    FT_String*  name;
+    FT_Long     minimum;
+    FT_Long     maximum;
+
+  } FT_MM_Axis;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Multi_Master                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model the axes and space of a Multiple Masters */
+  /*    font.                                                              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_axis    :: Number of axes.  Cannot exceed 4.                   */
+  /*                                                                       */
+  /*    num_designs :: Number of designs; should ne normally 2^num_axis    */
+  /*                   even though the Type 1 specification strangely      */
+  /*                   allows for intermediate designs to be present. This */
+  /*                   number cannot exceed 16.                            */
+  /*                                                                       */
+  /*    axis        :: A table of axis descriptors.                        */
+  /*                                                                       */
+  typedef struct  FT_Multi_Master_
+  {
+    FT_UInt     num_axis;
+    FT_UInt     num_designs;
+    FT_MM_Axis  axis[T1_MAX_MM_AXIS];
+
+  } FT_Multi_Master;
+
+  /* */
+
+  typedef FT_Error
+  (*FT_Get_MM_Func)( FT_Face           face,
+                     FT_Multi_Master*  master );
+
+  typedef FT_Error
+  (*FT_Set_MM_Design_Func)( FT_Face   face,
+                            FT_UInt   num_coords,
+                            FT_Long*  coords );
+
+  typedef FT_Error
+  (*FT_Set_MM_Blend_Func)( FT_Face   face,
+                           FT_UInt   num_coords,
+                           FT_Long*  coords );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Multi_Master                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the Multiple Master descriptor of a given font.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face    :: A handle to the source face.                            */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    amaster :: The Multiple Masters descriptor.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Get_Multi_Master( FT_Face           face,
+                       FT_Multi_Master  *amaster );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_MM_Design_Coordinates                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    For Multiple Masters fonts, choose an interpolated font design     */
+  /*    through design coordinates.                                        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: A handle to the source face.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    num_coords :: The number of design coordinates (must be equal to   */
+  /*                  the number of axes in the font).                     */
+  /*                                                                       */
+  /*    coords     :: An array of design coordinates.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Set_MM_Design_Coordinates( FT_Face   face,
+                                FT_UInt   num_coords,
+                                FT_Long*  coords );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_MM_Blend_Coordinates                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    For Multiple Masters fonts, choose an interpolated font design     */
+  /*    through normalized blend coordinates.                              */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: A handle to the source face.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    num_coords :: The number of design coordinates (must be equal to   */
+  /*                  the number of axes in the font).                     */
+  /*                                                                       */
+  /*    coords     :: The design coordinates array (each element must be   */
+  /*                  between 0 and 1.0).                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Set_MM_Blend_Coordinates( FT_Face    face,
+                               FT_UInt    num_coords,
+                               FT_Fixed*  coords );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTMM_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftmoderr.h b/libraries/freetype-2.0.5/include/freetype/ftmoderr.h
new file mode 100644 (file)
index 0000000..94659a3
--- /dev/null
@@ -0,0 +1,148 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmoderr.h                                                             */
+/*                                                                         */
+/*    FreeType module error offsets (specification).                       */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the FreeType module error offsets.        */
+  /*                                                                       */
+  /* The lower byte gives the error code, the higher byte gives the        */
+  /* module.  The base module has error offset 0.  For example, the error  */
+  /* `FT_Err_Invalid_File_Format' has value 0x003, the error               */
+  /* `TT_Err_Invalid_File_Format' has value 0xB03, the error               */
+  /* `T1_Err_Invalid_File_Format' has value 0xC03, etc.                    */
+  /*                                                                       */
+  /* Undefine the macro FT_CONFIG_OPTION_USE_MODULE_ERRORS in ftoption.h   */
+  /* to make the higher byte always zero (disabling the module error       */
+  /* mechanism).                                                           */
+  /*                                                                       */
+  /* It can also be used to create a module error message table easily     */
+  /* with something like                                                   */
+  /*                                                                       */
+  /*   {                                                                   */
+  /*     #undef __FTMODERR_H__                                             */
+  /*     #define FT_MODERRDEF( e, v, s )  { FT_Mod_Err_ ## e, s },         */
+  /*     #define FT_MODERR_START_LIST     {                                */
+  /*     #define FT_MODERR_END_LIST       { 0, 0 } };                      */
+  /*                                                                       */
+  /*     const struct                                                      */
+  /*     {                                                                 */
+  /*       int          mod_err_offset;                                    */
+  /*       const char*  mod_err_msg                                        */
+  /*     } ft_mod_errors[] =                                               */
+  /*                                                                       */
+  /*     #include FT_MODULE_ERRORS_H                                       */
+  /*   }                                                                   */
+  /*                                                                       */
+  /* To use such a table, all errors must be ANDed with 0xFF00 to remove   */
+  /* the error code.                                                       */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTMODERR_H__
+#define __FTMODERR_H__
+
+
+  /*******************************************************************/
+  /*******************************************************************/
+  /*****                                                         *****/
+  /*****                       SETUP MACROS                      *****/
+  /*****                                                         *****/
+  /*******************************************************************/
+  /*******************************************************************/
+
+
+#undef  FT_NEED_EXTERN_C
+
+#ifndef FT_MODERRDEF
+
+#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS
+#define FT_MODERRDEF( e, v, s )  FT_Mod_Err_ ## e = v,
+#else
+#define FT_MODERRDEF( e, v, s )  FT_Mod_Err_ ## e = 0,
+#endif
+
+#define FT_MODERR_START_LIST  enum {
+#define FT_MODERR_END_LIST    FT_Mod_Err_Max };
+
+#ifdef __cplusplus
+#define FT_NEED_EXTERN_C
+  extern "C" {
+#endif
+
+#endif /* !FT_MODERRDEF */
+
+
+  /*******************************************************************/
+  /*******************************************************************/
+  /*****                                                         *****/
+  /*****               LIST MODULE ERROR BASES                   *****/
+  /*****                                                         *****/
+  /*******************************************************************/
+  /*******************************************************************/
+
+
+#ifdef FT_MODERR_START_LIST
+  FT_MODERR_START_LIST
+#endif
+
+
+  FT_MODERRDEF( Base,     0x000, "base module" )
+  FT_MODERRDEF( Autohint, 0x100, "autohinter module" )
+  FT_MODERRDEF( Cache,    0x200, "cache module" )
+  FT_MODERRDEF( CFF,      0x300, "CFF module" )
+  FT_MODERRDEF( CID,      0x400, "CID module" )
+  FT_MODERRDEF( PCF,      0x500, "PCF module" )
+  FT_MODERRDEF( PSaux,    0x600, "PS auxiliary module" )
+  FT_MODERRDEF( PSnames,  0x700, "PS names module" )
+  FT_MODERRDEF( Raster,   0x800, "raster module" )
+  FT_MODERRDEF( SFNT,     0x900, "SFNT module" )
+  FT_MODERRDEF( Smooth,   0xA00, "smooth raster module" )
+  FT_MODERRDEF( TrueType, 0xB00, "TrueType module" )
+  FT_MODERRDEF( Type1,    0xC00, "Type 1 module" )
+  FT_MODERRDEF( Winfonts, 0xD00, "Windows FON/FNT module" )
+
+
+#ifdef FT_MODERR_END_LIST
+  FT_MODERR_END_LIST
+#endif
+
+
+  /*******************************************************************/
+  /*******************************************************************/
+  /*****                                                         *****/
+  /*****                      CLEANUP                            *****/
+  /*****                                                         *****/
+  /*******************************************************************/
+  /*******************************************************************/
+
+
+#ifdef FT_NEED_EXTERN_C
+  }
+#endif
+
+#undef FT_MODERR_START_LIST
+#undef FT_MODERR_END_LIST
+#undef FT_MODERRDEF
+#undef FT_NEED_EXTERN_C
+
+
+#endif /* __FTMODERR_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftmodule.h b/libraries/freetype-2.0.5/include/freetype/ftmodule.h
new file mode 100644 (file)
index 0000000..97718ad
--- /dev/null
@@ -0,0 +1,307 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmodule.h                                                             */
+/*                                                                         */
+/*    FreeType modules public interface (specification).                   */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTMODULE_H__
+#define __FTMODULE_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    module_management                                                  */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Module Management                                                  */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    How to add, upgrade, and remove modules from FreeType.             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The definitions below are used to manage modules within FreeType.  */
+  /*    Modules can be added, upgraded, and removed at runtime.            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* module bit flags */
+  typedef enum  FT_Module_Flags_
+  {
+    ft_module_font_driver         = 1,     /* this module is a font driver  */
+    ft_module_renderer            = 2,     /* this module is a renderer     */
+    ft_module_hinter              = 4,     /* this module is a glyph hinter */
+    ft_module_styler              = 8,     /* this module is a styler       */
+
+    ft_module_driver_scalable     = 0x100, /* the driver supports scalable  */
+                                           /* fonts                         */
+    ft_module_driver_no_outlines  = 0x200, /* the driver does not support   */
+                                           /* vector outlines               */
+    ft_module_driver_has_hinter   = 0x400  /* the driver provides its own   */
+                                           /* hinter                        */
+
+  } FT_Module_Flags;
+
+
+  typedef void
+  (*FT_Module_Interface)( void );
+
+  typedef FT_Error
+  (*FT_Module_Constructor)( FT_Module  module );
+
+  typedef void
+  (*FT_Module_Destructor)( FT_Module  module );
+
+  typedef FT_Module_Interface
+  (*FT_Module_Requester)( FT_Module    module,
+                          const char*  name );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Module_Class                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The module class descriptor.                                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    module_flags      :: Bit flags describing the module.              */
+  /*                                                                       */
+  /*    module_size       :: The size of one module object/instance in     */
+  /*                         bytes.                                        */
+  /*                                                                       */
+  /*    module_name       :: The name of the module.                       */
+  /*                                                                       */
+  /*    module_version    :: The version, as a 16.16 fixed number          */
+  /*                         (major.minor).                                */
+  /*                                                                       */
+  /*    module_requires   :: The version of FreeType this module requires  */
+  /*                         (starts at version 2.0, i.e 0x20000)          */
+  /*                                                                       */
+  /*    module_init       :: A function used to initialize (not create) a  */
+  /*                         new module object.                            */
+  /*                                                                       */
+  /*    module_done       :: A function used to finalize (not destroy) a   */
+  /*                         given module object                           */
+  /*                                                                       */
+  /*    get_interface     :: Queries a given module for a specific         */
+  /*                         interface by name.                            */
+  /*                                                                       */
+  typedef struct  FT_Module_Class_
+  {
+    FT_ULong               module_flags;
+    FT_Int                 module_size;
+    const FT_String*       module_name;
+    FT_Fixed               module_version;
+    FT_Fixed               module_requires;
+
+    const void*            module_interface;
+
+    FT_Module_Constructor  module_init;
+    FT_Module_Destructor   module_done;
+    FT_Module_Requester    get_interface;
+
+  } FT_Module_Class;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Add_Module                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adds a new module to a given library instance.                     */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library :: A handle to the library object.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    clazz   :: A pointer to class descriptor for the module.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An error will be returned if a module already exists by that name, */
+  /*    or if the module requires a version of FreeType that is too great. */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Add_Module( FT_Library              library,
+                 const FT_Module_Class*  clazz );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Module                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finds a module by its name.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library     :: A handle to the library object.                     */
+  /*                                                                       */
+  /*    module_name :: The module's name (as an ASCII string).             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A module handle.  0 if none was found.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You should better be familiar with FreeType internals to know      */
+  /*    which module to look for :-)                                       */
+  /*                                                                       */
+  FT_EXPORT( FT_Module )
+  FT_Get_Module( FT_Library   library,
+                 const char*  module_name );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Remove_Module                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Removes a given module from a library instance.                    */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library :: A handle to a library object.                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    module  :: A handle to a module object.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The module object is destroyed by the function in case of success. */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Remove_Module( FT_Library  library,
+                    FT_Module   module );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Library                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used to create a new FreeType library instance    */
+  /*    from a given memory object.  It is thus possible to use libraries  */
+  /*    with distinct memory allocators within the same program.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory   :: A handle to the original memory object.                */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    alibrary :: A pointer to handle of a new library object.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_New_Library( FT_Memory    memory,
+                  FT_Library  *alibrary );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Library                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards a given library object.  This closes all drivers and      */
+  /*    discards all resource objects.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the target library.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Done_Library( FT_Library  library );
+
+
+
+  typedef void
+  (*FT_DebugHook_Func)( void*  arg );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Debug_Hook                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets a debug hook function for debugging the interpreter of a font */
+  /*    format.                                                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    hook_index :: The index of the debug hook.  You should use the     */
+  /*                  values defined in ftobjs.h, e.g.                     */
+  /*                  FT_DEBUG_HOOK_TRUETYPE.                              */
+  /*                                                                       */
+  /*    debug_hook :: The function used to debug the interpreter.          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Currently, four debug hook slots are available, but only two (for  */
+  /*    the TrueType and the Type 1 interpreter) are defined.              */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Set_Debug_Hook( FT_Library         library,
+                     FT_UInt            hook_index,
+                     FT_DebugHook_Func  debug_hook );
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Add_Default_Modules                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adds the set of default drivers to a given library object.         */
+  /*    This is only useful when you create a library object with          */
+  /*    FT_New_Library() (usually to plug a custom memory manager).        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library :: A handle to a new library object.                       */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Add_Default_Modules( FT_Library  library );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTMODULE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftoutln.h b/libraries/freetype-2.0.5/include/freetype/ftoutln.h
new file mode 100644 (file)
index 0000000..9dc1c64
--- /dev/null
@@ -0,0 +1,379 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftoutln.h                                                              */
+/*                                                                         */
+/*    Support for the FT_Outline type used to store glyph shapes of        */
+/*    most scalable font formats (specification).                          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTOUTLN_H__
+#define __FTOUTLN_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    outline_processing                                                 */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Outline Processing                                                 */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    Functions to create, transform, and render vectorial glyph images. */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This section contains routines used to create and destroy scalable */
+  /*    glyph images known as `outlines'.  These can also be measured,     */
+  /*    transformed, and converted into bitmaps and pixmaps.               */
+  /*                                                                       */
+  /* <Order>                                                               */
+  /*    FT_Outline                                                         */
+  /*    FT_Outline_Flags                                                   */
+  /*    FT_Outline_New                                                     */
+  /*    FT_Outline_Done                                                    */
+  /*    FT_Outline_Copy                                                    */
+  /*    FT_Outline_Translate                                               */
+  /*    FT_Outline_Transform                                               */
+  /*    FT_Outline_Reverse                                                 */
+  /*                                                                       */
+  /*    FT_Outline_Get_CBox                                                */
+  /*    FT_Outline_Get_BBox                                                */
+  /*                                                                       */
+  /*    FT_Outline_Get_Bitmap                                              */
+  /*    FT_Outline_Render                                                  */
+  /*                                                                       */
+  /*    FT_Outline_Decompose                                               */
+  /*    FT_Outline_Funcs                                                   */
+  /*    FT_Outline_MoveTo_Func                                             */
+  /*    FT_Outline_LineTo_Func                                             */
+  /*    FT_Outline_ConicTo_Func                                            */
+  /*    FT_Outline_CubicTo_Func                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Decompose                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Walks over an outline's structure to decompose it into individual  */
+  /*    segments and Bezier arcs.  This function is also able to emit      */
+  /*    `move to' and `close to' operations to indicate the start and end  */
+  /*    of new contours in the outline.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline   :: A pointer to the source target.                       */
+  /*                                                                       */
+  /*    interface :: A table of `emitters', i.e,. function pointers called */
+  /*                 during decomposition to indicate path operations.     */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    user      :: A typeless pointer which is passed to each emitter    */
+  /*                 during the decomposition.  It can be used to store    */
+  /*                 the state during the decomposition.                   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means sucess.                              */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Outline_Decompose( FT_Outline*              outline,
+                        const FT_Outline_Funcs*  interface,
+                        void*                    user );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_New                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new outline of a given size.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library     :: A handle to the library object from where the       */
+  /*                   outline is allocated.  Note however that the new    */
+  /*                   outline will NOT necessarily be FREED, when         */
+  /*                   destroying the library, by FT_Done_FreeType().      */
+  /*                                                                       */
+  /*    numPoints   :: The maximal number of points within the outline.    */
+  /*                                                                       */
+  /*    numContours :: The maximal number of contours within the outline.  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    anoutline   :: A handle to the new outline.  NULL in case of       */
+  /*                   error.                                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The reason why this function takes a `library' parameter is simply */
+  /*    to use the library's memory allocator.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Outline_New( FT_Library   library,
+                  FT_UInt      numPoints,
+                  FT_Int       numContours,
+                  FT_Outline  *anoutline );
+
+
+  FT_EXPORT( FT_Error )
+  FT_Outline_New_Internal( FT_Memory    memory,
+                           FT_UInt      numPoints,
+                           FT_Int       numContours,
+                           FT_Outline  *anoutline );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Done                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys an outline created with FT_Outline_New().                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle of the library object used to allocate the     */
+  /*               outline.                                                */
+  /*                                                                       */
+  /*    outline :: A pointer to the outline object to be discarded.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If the outline's `owner' field is not set, only the outline        */
+  /*    descriptor will be released.                                       */
+  /*                                                                       */
+  /*    The reason why this function takes an `library' parameter is       */
+  /*    simply to use FT_Free().                                           */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Outline_Done( FT_Library   library,
+                   FT_Outline*  outline );
+
+
+  FT_EXPORT( FT_Error )
+  FT_Outline_Done_Internal( FT_Memory    memory,
+                            FT_Outline*  outline );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Get_CBox                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns an outline's `control box'.  The control box encloses all  */
+  /*    the outline's points, including Bezier control points.  Though it  */
+  /*    coincides with the exact bounding box for most glyphs, it can be   */
+  /*    slightly larger in some situations (like when rotating an outline  */
+  /*    which contains Bezier outside arcs).                               */
+  /*                                                                       */
+  /*    Computing the control box is very fast, while getting the bounding */
+  /*    box can take much more time as it needs to walk over all segments  */
+  /*    and arcs in the outline.  To get the latter, you can use the       */
+  /*    `ftbbox' component which is dedicated to this single task.         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    acbox   :: The outline's control box.                              */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Outline_Get_CBox( FT_Outline*  outline,
+                       FT_BBox     *acbox );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Translate                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Applies a simple translation to the points of an outline.          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    outline :: A pointer to the target outline descriptor.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    xOffset :: The horizontal offset.                                  */
+  /*                                                                       */
+  /*    yOffset :: The vertical offset.                                    */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Outline_Translate( FT_Outline*  outline,
+                        FT_Pos       xOffset,
+                        FT_Pos       yOffset );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Copy                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Copies an outline into another one.  Both objects must have the    */
+  /*    same sizes (number of points & number of contours) when this       */
+  /*    function is called.                                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    source :: A handle to the source outline.                          */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    target :: A handle to the target outline.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Outline_Copy( FT_Outline*  source,
+                   FT_Outline  *target );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Transform                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Applies a simple 2x2 matrix to all of an outline's points.  Useful */
+  /*    for applying rotations, slanting, flipping, etc.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    outline :: A pointer to the target outline descriptor.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    matrix  :: A pointer to the transformation matrix.                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You can use FT_Outline_Translate() if you need to translate the    */
+  /*    outline's points.                                                  */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Outline_Transform( FT_Outline*  outline,
+                        FT_Matrix*   matrix );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Reverse                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Reverses the drawing direction of an outline.  This is used to     */
+  /*    ensure consistent fill conventions for mirrored glyphs.            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    outline :: A pointer to the target outline descriptor.             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This functions toggles the bit flag `ft_outline_reverse_fill' in   */
+  /*    the outline's `flags' field.                                       */
+  /*                                                                       */
+  /*    It shouldn't be used by a normal client application, unless it     */
+  /*    knows what it is doing.                                            */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Outline_Reverse( FT_Outline*  outline );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Get_Bitmap                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders an outline within a bitmap.  The outline's image is simply */
+  /*    OR-ed to the target bitmap.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to a FreeType library object.                  */
+  /*                                                                       */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    abitmap :: A pointer to the target bitmap descriptor.              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT CREATE the bitmap, it only renders an       */
+  /*    outline image within the one you pass to it!                       */
+  /*                                                                       */
+  /*    It will use the raster correponding to the default glyph format.   */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Outline_Get_Bitmap( FT_Library   library,
+                         FT_Outline*  outline,
+                         FT_Bitmap   *abitmap );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Outline_Render                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders an outline within a bitmap using the current scan-convert. */
+  /*    This functions uses an FT_Raster_Params structure as an argument,  */
+  /*    allowing advanced features like direct composition, translucency,  */
+  /*    etc.                                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to a FreeType library object.                  */
+  /*                                                                       */
+  /*    outline :: A pointer to the source outline descriptor.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    params  :: A pointer to a FT_Raster_Params structure used to       */
+  /*               describe the rendering operation.                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You should know what you are doing and how FT_Raster_Params works  */
+  /*    to use this function.                                              */
+  /*                                                                       */
+  /*    The field `params.source' will be set to `outline' before the scan */
+  /*    converter is called, which means that the value you give to it is  */
+  /*    actually ignored.                                                  */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Outline_Render( FT_Library         library,
+                     FT_Outline*        outline,
+                     FT_Raster_Params*  params );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTOUTLN_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftrender.h b/libraries/freetype-2.0.5/include/freetype/ftrender.h
new file mode 100644 (file)
index 0000000..2a0b122
--- /dev/null
@@ -0,0 +1,213 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftrender.h                                                             */
+/*                                                                         */
+/*    FreeType renderer modules public interface (specification).          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTRENDER_H__
+#define __FTRENDER_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+#include FT_GLYPH_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    module_management                                                  */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* create a new glyph object */
+  typedef FT_Error
+  (*FT_Glyph_Init_Func)( FT_Glyph      glyph,
+                         FT_GlyphSlot  slot );
+
+  /* destroys a given glyph object */
+  typedef void
+  (*FT_Glyph_Done_Func)( FT_Glyph  glyph );
+
+  typedef void
+  (*FT_Glyph_Transform_Func)( FT_Glyph    glyph,
+                              FT_Matrix*  matrix,
+                              FT_Vector*  delta );
+
+  typedef void
+  (*FT_Glyph_BBox_Func)( FT_Glyph  glyph,
+                         FT_BBox*  abbox );
+
+  typedef FT_Error
+  (*FT_Glyph_Copy_Func)( FT_Glyph   source,
+                         FT_Glyph   target );
+
+  typedef FT_Error
+  (*FT_Glyph_Prepare_Func)( FT_Glyph      glyph,
+                            FT_GlyphSlot  slot );
+
+
+  struct  FT_Glyph_Class_
+  {
+    FT_UInt                  glyph_size;
+    FT_Glyph_Format          glyph_format;
+    FT_Glyph_Init_Func       glyph_init;
+    FT_Glyph_Done_Func       glyph_done;
+    FT_Glyph_Copy_Func       glyph_copy;
+    FT_Glyph_Transform_Func  glyph_transform;
+    FT_Glyph_BBox_Func       glyph_bbox;
+    FT_Glyph_Prepare_Func    glyph_prepare;
+  };
+
+
+  typedef FT_Error
+  (*FTRenderer_render)( FT_Renderer   renderer,
+                        FT_GlyphSlot  slot,
+                        FT_UInt       mode,
+                        FT_Vector*    origin );
+
+  typedef FT_Error
+  (*FTRenderer_transform)( FT_Renderer   renderer,
+                           FT_GlyphSlot  slot,
+                           FT_Matrix*    matrix,
+                           FT_Vector*    delta );
+
+  typedef void
+  (*FTRenderer_getCBox)( FT_Renderer   renderer,
+                         FT_GlyphSlot  slot,
+                         FT_BBox*      cbox );
+
+  typedef FT_Error
+  (*FTRenderer_setMode)( FT_Renderer  renderer,
+                         FT_ULong     mode_tag,
+                         FT_Pointer   mode_ptr );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Renderer_Class                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The renderer module class descriptor.                              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root         :: The root FT_Module_Class fields.                   */
+  /*                                                                       */
+  /*    glyph_format :: The glyph image format this renderer handles.      */
+  /*                                                                       */
+  /*    render_glyph :: A method used to render the image that is in a     */
+  /*                    given glyph slot into a bitmap.                    */
+  /*                                                                       */
+  /*    set_mode     :: A method used to pass additional parameters.       */
+  /*                                                                       */
+  /*    raster_class :: For `ft_glyph_format_outline' renderers only, this */
+  /*                    is a pointer to its raster's class.                */
+  /*                                                                       */
+  /*    raster       :: For `ft_glyph_format_outline' renderers only. this */
+  /*                    is a pointer to the corresponding raster object,   */
+  /*                    if any.                                            */
+  /*                                                                       */
+  typedef struct  FT_Renderer_Class_
+  {
+    FT_Module_Class       root;
+
+    FT_Glyph_Format       glyph_format;
+
+    FTRenderer_render     render_glyph;
+    FTRenderer_transform  transform_glyph;
+    FTRenderer_getCBox    get_glyph_cbox;
+    FTRenderer_setMode    set_mode;
+
+    FT_Raster_Funcs*      raster_class;
+
+  } FT_Renderer_Class;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Renderer                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the current renderer for a given glyph format.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library :: A handle to the library object.                         */
+  /*                                                                       */
+  /*    format  :: The glyph format.                                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A renderer handle.  0 if none found.                               */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    An error will be returned if a module already exists by that name, */
+  /*    or if the module requires a version of FreeType that is too great. */
+  /*                                                                       */
+  /*    To add a new renderer, simply use FT_Add_Module().  To retrieve a  */
+  /*    renderer by its name, use FT_Get_Module().                         */
+  /*                                                                       */
+  FT_EXPORT( FT_Renderer )
+  FT_Get_Renderer( FT_Library       library,
+                   FT_Glyph_Format  format );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Set_Renderer                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the current renderer to use, and set additional mode.         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    library    :: A handle to the library object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    renderer   :: A handle to the renderer object.                     */
+  /*                                                                       */
+  /*    num_params :: The number of additional parameters.                 */
+  /*                                                                       */
+  /*    parameters :: Additional parameters.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    In case of success, the renderer will be used to convert glyph     */
+  /*    images in the renderer's known format into bitmaps.                */
+  /*                                                                       */
+  /*    This doesn't change the current renderer for other formats.        */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Set_Renderer( FT_Library     library,
+                   FT_Renderer    renderer,
+                   FT_UInt        num_params,
+                   FT_Parameter*  parameters );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTRENDER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftsizes.h b/libraries/freetype-2.0.5/include/freetype/ftsizes.h
new file mode 100644 (file)
index 0000000..87196a5
--- /dev/null
@@ -0,0 +1,151 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsizes.h                                                              */
+/*                                                                         */
+/*    FreeType size objects management (specification).                    */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Typical application would normally not need to use these functions.   */
+  /* However, they have been placed in a public API for the rare cases     */
+  /* where they are needed.                                                */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTSIZES_H__
+#define __FTSIZES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    sizes_management                                                   */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Size management                                                    */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    Managing multiple sizes per face                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    When creating a new face object (e.g. with @FT_New_Face), an       */
+  /*    @FT_Size object is automatically created and used to store all     */
+  /*    pixel-size dependent information, available in the "face->size"    */
+  /*    field.                                                             */
+  /*                                                                       */
+  /*    It is however possible to create more sizes for a given face,      */
+  /*    mostly in order to manage several character pixel sizes of the     */
+  /*    same font family and style.  See @FT_New_Size and @FT_Done_Size.   */
+  /*                                                                       */
+  /*    Note that @FT_Set_Pixel_Sizes and @FT_Set_Character_Size only      */
+  /*    modify the contents of the current "active" size; you thus need    */
+  /*    to use @FT_Activate_Size to change it.                             */
+  /*                                                                       */
+  /*    99% of applications won't need the functions provided here,        */
+  /*    especially if they use the caching sub-system, so be cautious      */
+  /*    when using these.                                                  */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Size                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new size object from a given face object.                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to a parent face object.                          */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    asize :: A handle to a new size object.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You need to call @FT_Activate_Size in order to select the new size */
+  /*    for upcoming calls to @FT_Set_Pixel_Sizes, @FT_Set_Char_Size,      */
+  /*    @FT_Load_Glyph, @FT_Load_Char, etc.                                */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_New_Size( FT_Face   face,
+               FT_Size*  size );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Size                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards a given size object.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to a target size object.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Done_Size( FT_Size  size );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Activate_Size                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Even though it is possible to create several size objects for a    */
+  /*    given face (see @FT_New_Size for details), functions like          */
+  /*    @FT_Load_Glyph or @FT_Load_Char only use the last-created one to   */
+  /*    determine the "current character pixel size".                      */
+  /*                                                                       */
+  /*    This function can be used to "activate" a previously created size  */
+  /*    object.                                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to a target size object.                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If "face" is the size's parent face object, this function changes  */
+  /*    the value of "face->size" to the input size handle.                */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Activate_Size( FT_Size  size );
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTSIZES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftsnames.h b/libraries/freetype-2.0.5/include/freetype/ftsnames.h
new file mode 100644 (file)
index 0000000..727e451
--- /dev/null
@@ -0,0 +1,161 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsnames.h                                                             */
+/*                                                                         */
+/*    Simple interface to access SFNT name tables (which are used          */
+/*    to hold font names, copyright info, notices, etc.) (specification).  */
+/*                                                                         */
+/*    This is _not_ used to retrieve glyph names!                          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FT_SFNT_NAMES_H__
+#define __FT_SFNT_NAMES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    sfnt_names                                                         */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    SFNT Names                                                         */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    Access the names embedded in TrueType and OpenType files.          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The TrueType and OpenType specification allow the inclusion of     */
+  /*    a special `names table' in font files.  This table contains        */
+  /*    textual (and internationalized) information regarding the font,    */
+  /*    like family name, copyright, version, etc.                         */
+  /*                                                                       */
+  /*    The definitions below are used to access them if available.        */
+  /*                                                                       */
+  /*    Note that this has nothing to do with glyph names!                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_SfntName                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model an SFNT `name' table entry.              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    platform_id :: The platform ID for `string'.                       */
+  /*                                                                       */
+  /*    encoding_id :: The encoding ID for `string'.                       */
+  /*                                                                       */
+  /*    language_id :: The language ID for `string'.                       */
+  /*                                                                       */
+  /*    name_id     :: An identifier for `string'.                         */
+  /*                                                                       */
+  /*    string      :: The `name' string.  Note that its format differs    */
+  /*                   depending on the (platform,encoding) pair. It can   */
+  /*                   be a Pascal String, a UTF-16 one, etc..             */
+  /*                                                                       */
+  /*                   Generally speaking, the string is not               */
+  /*                   zero-terminated. Please refer to the TrueType       */
+  /*                   specification for details..                         */
+  /*                                                                       */
+  /*    string_len  :: The length of `string' in bytes.                    */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Possible values for `platform_id', `encoding_id', `language_id',   */
+  /*    and `name_id' are given in the file `ttnameid.h'.  For details     */
+  /*    please refer to the TrueType or OpenType specification.            */
+  /*                                                                       */
+  typedef struct  FT_SfntName_
+  {
+    FT_UShort  platform_id;
+    FT_UShort  encoding_id;
+    FT_UShort  language_id;
+    FT_UShort  name_id;
+
+    FT_Byte*   string;      /* this string is *not* null-terminated! */
+    FT_UInt    string_len;  /* in bytes */
+
+  } FT_SfntName;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Sfnt_Name_Count                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the number of name strings in the SFNT `name' table.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the source face.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The number of strings in the `name' table.                         */
+  /*                                                                       */
+  FT_EXPORT( FT_UInt )
+  FT_Get_Sfnt_Name_Count( FT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Sfnt_Name                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves a string of the SFNT `name' table for a given index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face  :: A handle to the source face.                              */
+  /*                                                                       */
+  /*    index :: The index of the `name' string.                           */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aname :: The indexed FT_SfntName structure.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The `string' array returned in the `aname' structure is not        */
+  /*    null-terminated.                                                   */
+  /*                                                                       */
+  /*    Use FT_Get_Sfnt_Name_Count() to get the total number of available  */
+  /*    `name' table entries, then do a loop until you get the right       */
+  /*    platform, encoding, and name ID.                                   */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Get_Sfnt_Name( FT_Face       face,
+                    FT_UInt       index,
+                    FT_SfntName  *aname );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FT_SFNT_NAMES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftsynth.h b/libraries/freetype-2.0.5/include/freetype/ftsynth.h
new file mode 100644 (file)
index 0000000..4c7752a
--- /dev/null
@@ -0,0 +1,67 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsynth.h                                                              */
+/*                                                                         */
+/*    FreeType synthesizing code for emboldening and slanting              */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*********                                                       *********/
+  /*********        WARNING, THIS IS ALPHA CODE, THIS API          *********/
+  /*********    IS DUE TO CHANGE UNTIL STRICTLY NOTIFIED BY THE    *********/
+  /*********            FREETYPE DEVELOPMENT TEAM                  *********/
+  /*********                                                       *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#ifndef __FTSYNTH_H__
+#define __FTSYNTH_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /* This code is completely experimental -- use with care! */
+  /* It will probably be completely rewritten in the future */
+  /* or even integrated into the library.                   */
+  FT_EXPORT( FT_Error )
+  FT_Outline_Embolden( FT_GlyphSlot  original,
+                       FT_Outline*   outline,
+                       FT_Pos*       advance );
+
+  FT_EXPORT( FT_Error )
+  FT_Outline_Oblique( FT_GlyphSlot  original,
+                      FT_Outline*   outline,
+                      FT_Pos*       advance );
+
+
+FT_END_HEADER
+
+#endif /* __FTSYNTH_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ftsystem.h b/libraries/freetype-2.0.5/include/freetype/ftsystem.h
new file mode 100644 (file)
index 0000000..d6fc3e1
--- /dev/null
@@ -0,0 +1,307 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsystem.h                                                             */
+/*                                                                         */
+/*    FreeType low-level system interface definition (specification).      */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTSYSTEM_H__
+#define __FTSYSTEM_H__
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    system_interface                                                   */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    System Interface                                                   */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    How FreeType manages memory and i/o.                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This section contains various definitions related to memory        */
+  /*    management and i/o access.  You need to understand this            */
+  /*    information if you want to use a custom memory manager or you own  */
+  /*    input i/o streams.                                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                  M E M O R Y   M A N A G E M E N T                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @type:                                                                */
+  /*    FT_Memory                                                          */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A handle to a given memory manager object, defined with a          */
+  /*    @FT_MemoryRec structure.                                           */
+  /*                                                                       */
+  typedef struct FT_MemoryRec_*  FT_Memory;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @functype:                                                            */
+  /*    FT_Alloc_Func                                                      */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A function used to allocate `size' bytes from `memory'.            */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    memory :: A handle to the source memory manager.                   */
+  /*                                                                       */
+  /*    size   :: The size in bytes to allocate.                           */
+  /*                                                                       */
+  /* @return:                                                              */
+  /*    Address of new memory block.  0 in case of failure.                */
+  /*                                                                       */
+  typedef void*
+  (*FT_Alloc_Func)( FT_Memory  memory,
+                    long       size );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @functype:                                                            */
+  /*    FT_Free_Func                                                       */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A function used to release a given block of memory.                */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    memory :: A handle to the source memory manager.                   */
+  /*                                                                       */
+  /*    block  :: The address of the target memory block.                  */
+  /*                                                                       */
+  typedef void
+  (*FT_Free_Func)( FT_Memory  memory,
+                   void*      block );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @functype:                                                            */
+  /*    FT_Realloc_Func                                                    */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    a function used to re-allocate a given block of memory.            */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    memory   :: A handle to the source memory manager.                 */
+  /*                                                                       */
+  /*    cur_size :: The block's current size in bytes.                     */
+  /*                                                                       */
+  /*    new_size :: The block's requested new size.                        */
+  /*                                                                       */
+  /*    block    :: The block's current address.                           */
+  /*                                                                       */
+  /* @return:                                                              */
+  /*    New block address.  0 in case of memory shortage.                  */
+  /*                                                                       */
+  /* @note:                                                                */
+  /*   In case of error, the old block must still be available.            */
+  /*                                                                       */
+  typedef void*
+  (*FT_Realloc_Func)( FT_Memory  memory,
+                      long       cur_size,
+                      long       new_size,
+                      void*      block );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @struct:                                                              */
+  /*    FT_MemoryRec                                                       */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A structure used to describe a given memory manager to FreeType 2. */
+  /*                                                                       */
+  /* @fields:                                                              */
+  /*    user    :: A generic typeless pointer for user data.               */
+  /*                                                                       */
+  /*    alloc   :: A pointer type to an allocation function.               */
+  /*                                                                       */
+  /*    free    :: A pointer type to an memory freeing function.           */
+  /*                                                                       */
+  /*    realloc :: A pointer type to a reallocation function.              */
+  /*                                                                       */
+  struct  FT_MemoryRec_
+  {
+    void*            user;
+    FT_Alloc_Func    alloc;
+    FT_Free_Func     free;
+    FT_Realloc_Func  realloc;
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       I / O   M A N A G E M E N T                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @type:                                                                */
+  /*    FT_Stream                                                          */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A handle to an input stream.                                       */
+  /*                                                                       */
+  typedef struct FT_StreamRec_*  FT_Stream;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @struct:                                                              */
+  /*    FT_StreamDesc                                                      */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A union type used to store either a long or a pointer.  This is    */
+  /*    used to store a file descriptor or a FILE* in an input stream.     */
+  /*                                                                       */
+  typedef union  FT_StreamDesc_
+  {
+    long   value;
+    void*  pointer;
+
+  } FT_StreamDesc;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @functype:                                                            */
+  /*    FT_Stream_IO                                                       */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A function used to seek and read data from a given input stream.   */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    stream :: A handle to the source stream.                           */
+  /*                                                                       */
+  /*    offset :: The offset of read in stream (always from start).        */
+  /*                                                                       */
+  /*    buffer :: The address of the read buffer.                          */
+  /*                                                                       */
+  /*    count  :: The number of bytes to read from the stream.             */
+  /*                                                                       */
+  /* @return:                                                              */
+  /*    The number of bytes effectively read by the stream.                */
+  /*                                                                       */
+  /* @note:                                                                */
+  /*    This function might be called to perform a seek or skip operation  */
+  /*    with a `count' of 0.                                               */
+  /*                                                                       */
+  typedef unsigned long
+  (*FT_Stream_IO)( FT_Stream       stream,
+                   unsigned long   offset,
+                   unsigned char*  buffer,
+                   unsigned long   count );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @functype:                                                            */
+  /*    FT_Stream_Close                                                    */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    A function used to close a given input stream.                     */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*   stream :: A handle to the target stream.                            */
+  /*                                                                       */
+  typedef void
+  (*FT_Stream_Close)( FT_Stream  stream );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @struct:                                                              */
+  /*    FT_StreamRec                                                       */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   A structure used to describe an input stream.                       */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*   base       :: For memory-based streams, this is the address of the  */
+  /*                 first stream byte in memory.  This field should       */
+  /*                 always be set to NULL for disk-based streams.         */
+  /*                                                                       */
+  /*   size       :: The stream size in bytes.                             */
+  /*                                                                       */
+  /*   pos        :: The current position within the stream.               */
+  /*                                                                       */
+  /*   descriptor :: This field is a union that can hold an integer or a   */
+  /*                 pointer.  It is used by stream implementations to     */
+  /*                 store file descriptors or FILE* pointers.             */
+  /*                                                                       */
+  /*   pathname   :: This field is completely ignored by FreeType.         */
+  /*                 However, it is often useful during debugging to use   */
+  /*                 it to store the stream's filename (where available).  */
+  /*                                                                       */
+  /*   read       :: The stream's input function.                          */
+  /*                                                                       */
+  /*   close      :: The stream;s close function.                          */
+  /*                                                                       */
+  /*   memory     :: The memory manager to use to preload frames.  This is */
+  /*                 set internally by FreeType and shouldn't be touched   */
+  /*                 by stream implementations.                            */
+  /*                                                                       */
+  /*   cursor     :: This field is set and used internally by FreeType     */
+  /*                 when parsing frames.                                  */
+  /*                                                                       */
+  /*   limit      :: This field is set and used internally by FreeType     */
+  /*                 when parsing frames.                                  */
+  /*                                                                       */
+  struct  FT_StreamRec_
+  {
+    unsigned char*   base;
+    unsigned long    size;
+    unsigned long    pos;
+
+    FT_StreamDesc    descriptor;
+    FT_StreamDesc    pathname;
+    FT_Stream_IO     read;
+    FT_Stream_Close  close;
+
+    FT_Memory        memory;
+    unsigned char*   cursor;
+    unsigned char*   limit;
+  };
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTSYSTEM_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/fttrigon.h b/libraries/freetype-2.0.5/include/freetype/fttrigon.h
new file mode 100644 (file)
index 0000000..9762189
--- /dev/null
@@ -0,0 +1,281 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fttrigon.h                                                             */
+/*                                                                         */
+/*    FreeType trigonometric functions (specification).                    */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTTRIGON_H__
+#define __FTTRIGON_H__
+
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @section:                                                             */
+  /*   computations                                                        */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @type:                                                                */
+  /*    FT_Angle                                                           */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    This type is used to model angle values in FreeType.  Note that    */
+  /*    the angle is a 16.16 fixed float value expressed in degrees.       */
+  /*                                                                       */
+  typedef FT_Fixed  FT_Angle;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_ANGLE_PI                                                        */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   The angle pi expressed in @FT_Angle units.                          */
+  /*                                                                       */
+#define FT_ANGLE_PI  ( 180L << 16 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_ANGLE_2PI                                                       */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    The angle 2*pi expressed in @FT_Angle units.                       */
+  /*                                                                       */
+#define FT_ANGLE_2PI  ( FT_ANGLE_PI * 2 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_ANGLE_PI2                                                       */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    The angle pi/2 expressed in @FT_Angle units.                       */
+  /*                                                                       */
+#define FT_ANGLE_PI2  ( FT_ANGLE_PI / 2 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @macro:                                                               */
+  /*    FT_ANGLE_PI4                                                       */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    The angle pi/4 expressed in @FT_Angle units.                       */
+  /*                                                                       */
+#define FT_ANGLE_PI4  ( FT_ANGLE_PI / 4 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @function:                                                            */
+  /*    FT_Sin                                                             */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    Return the sinus of a given angle in fixed point format.           */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    angle :: The input angle.                                          */
+  /*                                                                       */
+  /* @return:                                                              */
+  /*    The sinus value.                                                   */
+  /*                                                                       */
+  /* @note:                                                                */
+  /*    If you need both the sinus and cosinus for a given angle, use the  */
+  /*    function @FT_Vector_Unit.                                          */
+  /*                                                                       */
+  FT_EXPORT( FT_Fixed )
+  FT_Sin( FT_Angle  angle );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @function:                                                            */
+  /*    FT_Cos                                                             */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    Return the cosinus of a given angle in fixed point format.         */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    angle :: The input angle.                                          */
+  /*                                                                       */
+  /* @return:                                                              */
+  /*    The cosinus value.                                                 */
+  /*                                                                       */
+  /* @note:                                                                */
+  /*    If you need both the sinus and cosinus for a given angle, use the  */
+  /*    function @FT_Vector_Unit.                                          */
+  /*                                                                       */
+  FT_EXPORT( FT_Fixed )
+  FT_Cos( FT_Angle  angle );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @function:                                                            */
+  /*    FT_Tan                                                             */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    Return the tangent of a given angle in fixed point format.         */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    angle :: The input angle.                                          */
+  /*                                                                       */
+  /* @return:                                                              */
+  /*    The tangent value.                                                 */
+  /*                                                                       */
+  FT_EXPORT( FT_Fixed )
+  FT_Tan( FT_Angle  angle );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @function:                                                            */
+  /*    FT_Atan2                                                           */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    Return the arc-tangent corresponding to a given vector (x,y) in    */
+  /*    the 2d plane.                                                      */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    x :: The horizontal vector coordinate.                             */
+  /*                                                                       */
+  /*    y :: The vertical vector coordinate.                               */
+  /*                                                                       */
+  /* @return:                                                              */
+  /*    The arc-tangent value (i.e. angle).                                */
+  /*                                                                       */
+  FT_EXPORT( FT_Angle )
+  FT_Atan2( FT_Fixed  x,
+            FT_Fixed  y );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @function:                                                            */
+  /*    FT_Vector_Unit                                                     */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    Return the unit vector corresponding to a given angle.  After the  */
+  /*    call, the value of `vec.x' will be `sin(angle)', and the value of  */
+  /*    `vec.y' will be `cos(angle)'.                                      */
+  /*                                                                       */
+  /*    This function is useful to retrieve both the sinus and cosinus of  */
+  /*    a given angle quickly.                                             */
+  /*                                                                       */
+  /* @output:                                                              */
+  /*    vec   :: The address of target vector.                             */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    angle :: The address of angle.                                     */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Vector_Unit( FT_Vector*  vec,
+                  FT_Angle    angle );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @function:                                                            */
+  /*    FT_Vector_Rotate                                                   */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    Rotate a vector by a given angle.                                  */
+  /*                                                                       */
+  /* @inout:                                                               */
+  /*    vec   :: The address of target vector.                             */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    angle :: The address of angle.                                     */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Vector_Rotate( FT_Vector*  vec,
+                    FT_Angle    angle );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @function:                                                            */
+  /*   FT_Vector_Length                                                    */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*   Return the length of a given vector.                                */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*   vec :: The address of target vector.                                */
+  /*                                                                       */
+  /* @return:                                                              */
+  /*   The vector length, expressed in the same units that the original    */
+  /*   vector coordinates.                                                 */
+  /*                                                                       */
+  FT_EXPORT( FT_Fixed )
+  FT_Vector_Length( FT_Vector*  vec );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @function:                                                            */
+  /*    FT_Vector_Normalize                                                */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    Normalize a given vector (i.e. compute the equivalent unit         */
+  /*    vector).                                                           */
+  /*                                                                       */
+  /* @inout:                                                               */
+  /*    vec :: The address of target vector.                               */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Vector_Normalize( FT_Vector*  vec );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* @function:                                                            */
+  /*    FT_Vector_Polarize                                                 */
+  /*                                                                       */
+  /* @description:                                                         */
+  /*    Compute both the length and angle of a given vector.               */
+  /*                                                                       */
+  /* @input:                                                               */
+  /*    vec    :: The address of source vector.                            */
+  /*                                                                       */
+  /* @output:                                                              */
+  /*    length :: The vector length.                                       */
+  /*    angle  :: The vector angle.                                        */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Vector_Polarize( FT_Vector*  vec,
+                      FT_Fixed   *length,
+                      FT_Angle   *angle );
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __FTTRIGON_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/fttypes.h b/libraries/freetype-2.0.5/include/freetype/fttypes.h
new file mode 100644 (file)
index 0000000..15aa6a5
--- /dev/null
@@ -0,0 +1,525 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fttypes.h                                                              */
+/*                                                                         */
+/*    FreeType simple types definitions (specification only).              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTTYPES_H__
+#define __FTTYPES_H__
+
+
+#include <ft2build.h>
+#include FT_SYSTEM_H
+#include FT_IMAGE_H
+
+#include <stddef.h>
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    basic_types                                                        */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Basic Types                                                        */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    The basic data types defined by the library.                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This section contains the basic data types defined by FreeType 2,  */
+  /*    ranging from simple scalar types to font specific ones.            */
+  /*                                                                       */
+  /* <Order>                                                               */
+  /*    FT_Byte                                                            */
+  /*    FT_Char                                                            */
+  /*    FT_Int                                                             */
+  /*    FT_UInt                                                            */
+  /*    FT_Short                                                           */
+  /*    FT_UShort                                                          */
+  /*    FT_Long                                                            */
+  /*    FT_ULong                                                           */
+  /*    FT_Bool                                                            */
+  /*    FT_Offset                                                          */
+  /*    FT_PtrDist                                                         */
+  /*    FT_Error                                                           */
+  /*    FT_Fixed                                                           */
+  /*    FT_Pointer                                                         */
+  /*    FT_Pos                                                             */
+  /*    FT_Vector                                                          */
+  /*    FT_BBox                                                            */
+  /*    FT_Matrix                                                          */
+  /*                                                                       */
+  /*    FT_Generic                                                         */
+  /*    FT_Generic_Finalizer                                               */
+  /*                                                                       */
+  /*    FT_Bitmap                                                          */
+  /*    FT_Pixel_Mode                                                      */
+  /*    FT_Palette_Mode                                                    */
+  /*    FT_Glyph_Format                                                    */
+  /*    FT_IMAGE_TAG                                                       */
+  /*    FT_Glyph_Format                                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Bool                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef of unsigned char, used for simple booleans.              */
+  /*                                                                       */
+  typedef unsigned char  FT_Bool;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_FWord                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A signed 16-bit integer used to store a distance in original font  */
+  /*    units.                                                             */
+  /*                                                                       */
+  typedef signed short  FT_FWord;   /* distance in FUnits */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_UFWord                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    An unsigned 16-bit integer used to store a distance in original    */
+  /*    font units.                                                        */
+  /*                                                                       */
+  typedef unsigned short  FT_UFWord;  /* unsigned distance */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Char                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple typedef for the _signed_ char type.                       */
+  /*                                                                       */
+  typedef signed char  FT_Char;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Byte                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple typedef for the _unsigned_ char type.                     */
+  /*                                                                       */
+  typedef unsigned char  FT_Byte;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_String                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple typedef for the char type, usually used for strings.      */
+  /*                                                                       */
+  typedef char  FT_String;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Short                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for signed short.                                        */
+  /*                                                                       */
+  typedef signed short  FT_Short;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_UShort                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for unsigned short.                                      */
+  /*                                                                       */
+  typedef unsigned short  FT_UShort;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Int                                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for the int type.                                        */
+  /*                                                                       */
+  typedef int  FT_Int;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_UInt                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for the unsigned int type.                               */
+  /*                                                                       */
+  typedef unsigned int  FT_UInt;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Long                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for signed long.                                         */
+  /*                                                                       */
+  typedef signed long  FT_Long;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_ULong                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A typedef for unsigned long.                                       */
+  /*                                                                       */
+  typedef unsigned long  FT_ULong;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_F2Dot14                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A signed 2.14 fixed float type used for unit vectors.              */
+  /*                                                                       */
+  typedef signed short  FT_F2Dot14;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_F26Dot6                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A signed 26.6 fixed float type used for vectorial pixel            */
+  /*    coordinates.                                                       */
+  /*                                                                       */
+  typedef signed long  FT_F26Dot6;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Fixed                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This type is used to store 16.16 fixed float values, like scales   */
+  /*    or matrix coefficients.                                            */
+  /*                                                                       */
+  typedef signed long  FT_Fixed;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Error                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The FreeType error code type.  A value of 0 is always interpreted  */
+  /*    as a successful operation.                                         */
+  /*                                                                       */
+  typedef int  FT_Error;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Pointer                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple typedef for a typeless pointer.                           */
+  /*                                                                       */
+  typedef void*  FT_Pointer;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Offset                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This is equivalent to the ANSI C `size_t' type, i.e. the largest   */
+  /*    _unsigned_ integer type used to express a file size or position,   */
+  /*    or a memory block size.                                            */
+  /*                                                                       */
+  typedef size_t  FT_Offset;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_PtrDist                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This is equivalent to the ANSI C `ptrdiff_t' type, i.e. the        */
+  /*    largest _signed_ integer type used to express the distance         */
+  /*    between two pointers.                                              */
+  /*                                                                       */
+  typedef size_t  FT_PtrDist;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_UnitVector                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to store a 2D vector unit vector.  Uses    */
+  /*    FT_F2Dot14 types.                                                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    x :: Horizontal coordinate.                                        */
+  /*                                                                       */
+  /*    y :: Vertical coordinate.                                          */
+  /*                                                                       */
+  typedef struct  FT_UnitVector_
+  {
+    FT_F2Dot14  x;
+    FT_F2Dot14  y;
+
+  } FT_UnitVector;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Matrix                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to store a 2x2 matrix.  Coefficients are   */
+  /*    in 16.16 fixed float format.  The computation performed is:        */
+  /*                                                                       */
+  /*       {                                                               */
+  /*          x' = x*xx + y*xy                                             */
+  /*          y' = x*yx + y*yy                                             */
+  /*       }                                                               */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    xx :: Matrix coefficient.                                          */
+  /*                                                                       */
+  /*    xy :: Matrix coefficient.                                          */
+  /*                                                                       */
+  /*    yx :: Matrix coefficient.                                          */
+  /*                                                                       */
+  /*    yy :: Matrix coefficient.                                          */
+  /*                                                                       */
+  typedef struct  FT_Matrix_
+  {
+    FT_Fixed  xx, xy;
+    FT_Fixed  yx, yy;
+
+  } FT_Matrix;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Generic_Finalizer                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Describes a function used to destroy the `client' data of any      */
+  /*    FreeType object.  See the description of the FT_Generic type for   */
+  /*    details of usage.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    The address of the FreeType object which is under finalization.    */
+  /*    Its client data is accessed through its `generic' field.           */
+  /*                                                                       */
+  typedef void  (*FT_Generic_Finalizer)(void*  object);
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Generic                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Client applications often need to associate their own data to a    */
+  /*    variety of FreeType core objects.  For example, a text layout API  */
+  /*    might want to associate a glyph cache to a given size object.      */
+  /*                                                                       */
+  /*    Most FreeType object contains a `generic' field, of type           */
+  /*    FT_Generic, which usage is left to client applications and font    */
+  /*    servers.                                                           */
+  /*                                                                       */
+  /*    It can be used to store a pointer to client-specific data, as well */
+  /*    as the address of a `finalizer' function, which will be called by  */
+  /*    FreeType when the object is destroyed (for example, the previous   */
+  /*    client example would put the address of the glyph cache destructor */
+  /*    in the `finalizer' field).                                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    data      :: A typeless pointer to any client-specified data. This */
+  /*                 field is completely ignored by the FreeType library.  */
+  /*                                                                       */
+  /*    finalizer :: A pointer to a `generic finalizer' function, which    */
+  /*                 will be called when the object is destroyed.  If this */
+  /*                 field is set to NULL, no code will be called.         */
+  /*                                                                       */
+  typedef struct  FT_Generic_
+  {
+    void*                 data;
+    FT_Generic_Finalizer  finalizer;
+
+  } FT_Generic;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Macro>                                                               */
+  /*    FT_MAKE_TAG                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This macro converts four letter tags which are used to label       */
+  /*    TrueType tables into an unsigned long to be used within FreeType.  */
+  /*                                                                       */
+#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
+          ( ( (FT_ULong)_x1 << 24 ) |     \
+            ( (FT_ULong)_x2 << 16 ) |     \
+            ( (FT_ULong)_x3 <<  8 ) |     \
+              (FT_ULong)_x4         )
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*                                                                       */
+  /*                    L I S T   M A N A G E M E N T                      */
+  /*                                                                       */
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    list_processing                                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_ListNode                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*     Many elements and objects in FreeType are listed through a        */
+  /*     FT_List record (see FT_ListRec).  As its name suggests, a         */
+  /*     FT_ListNode is a handle to a single list element.                 */
+  /*                                                                       */
+  typedef struct FT_ListNodeRec_*  FT_ListNode;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_List                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a list record (see FT_ListRec).                        */
+  /*                                                                       */
+  typedef struct FT_ListRec_*  FT_List;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_ListNodeRec                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to hold a single list element.                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    prev :: The previous element in the list.  NULL if first.          */
+  /*                                                                       */
+  /*    next :: The next element in the list.  NULL if last.               */
+  /*                                                                       */
+  /*    data :: A typeless pointer to the listed object.                   */
+  /*                                                                       */
+  typedef struct  FT_ListNodeRec_
+  {
+    FT_ListNode  prev;
+    FT_ListNode  next;
+    void*        data;
+
+  } FT_ListNodeRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_ListRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to hold a simple doubly-linked list.  These are   */
+  /*    used in many parts of FreeType.                                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    head :: The head (first element) of doubly-linked list.            */
+  /*                                                                       */
+  /*    tail :: The tail (last element) of doubly-linked list.             */
+  /*                                                                       */
+  typedef struct  FT_ListRec_
+  {
+    FT_ListNode  head;
+    FT_ListNode  tail;
+
+  } FT_ListRec;
+
+
+  /* */
+
+#define FT_IS_EMPTY( list )  ( (list).head == 0 )
+
+  /* return base error code (without module-specific prefix) */
+#define FT_ERROR_BASE( x )    ( (x) & 0xFF )
+
+  /* return module error code */
+#define FT_ERROR_MODULE( x )  ( (x) & 0xFF00U )
+
+#define FT_BOOL( x )  ( (FT_Bool)( x ) )
+
+FT_END_HEADER
+
+#endif /* __FTTYPES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/Makefile.am b/libraries/freetype-2.0.5/include/freetype/internal/Makefile.am
new file mode 100644 (file)
index 0000000..958084e
--- /dev/null
@@ -0,0 +1,5 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_HEADERS = \
+ autohint.h  fnttypes.h  ftdebug.h   ftextend.h  ftobjs.h    internal.h  psaux.h     sfnt.h      tttypes.h    \
+ cfftypes.h  ftcalc.h    ftdriver.h  ftmemory.h  ftstream.h  pcftypes.h  psnames.h   t1types.h   
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/autohint.h b/libraries/freetype-2.0.5/include/freetype/internal/autohint.h
new file mode 100644 (file)
index 0000000..40ade95
--- /dev/null
@@ -0,0 +1,204 @@
+/***************************************************************************/
+/*                                                                         */
+/*  autohint.h                                                             */
+/*                                                                         */
+/*    High-level `autohint' module-specific interface (specification).     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The auto-hinter is used to load and automatically hint glyphs if a    */
+  /* format-specific hinter isn't available.                               */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __AUTOHINT_H__
+#define __AUTOHINT_H__
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A small technical note regarding automatic hinting in order to        */
+  /* clarify this module interface.                                        */
+  /*                                                                       */
+  /* An automatic hinter might compute two kinds of data for a given face: */
+  /*                                                                       */
+  /* - global hints: Usually some metrics that describe global properties  */
+  /*                 of the face.  It is computed by scanning more or less */
+  /*                 agressively the glyphs in the face, and thus can be   */
+  /*                 very slow to compute (even if the size of global      */
+  /*                 hints is really small).                               */
+  /*                                                                       */
+  /* - glyph hints:  These describe some important features of the glyph   */
+  /*                 outline, as well as how to align them.  They are      */
+  /*                 generally much faster to compute than global hints.   */
+  /*                                                                       */
+  /* The current FreeType auto-hinter does a pretty good job while         */
+  /* performing fast computations for both global and glyph hints.         */
+  /* However, we might be interested in introducing more complex and       */
+  /* powerful algorithms in the future, like the one described in the John */
+  /* D. Hobby paper, which unfortunately requires a lot more horsepower.   */
+  /*                                                                       */
+  /* Because a sufficiently sophisticated font management system would     */
+  /* typically implement an LRU cache of opened face objects to reduce     */
+  /* memory usage, it is a good idea to be able to avoid recomputing       */
+  /* global hints every time the same face is re-opened.                   */
+  /*                                                                       */
+  /* We thus provide the ability to cache global hints outside of the face */
+  /* object, in order to speed up font re-opening time.  Of course, this   */
+  /* feature is purely optional, so most client programs won't even notice */
+  /* it.                                                                   */
+  /*                                                                       */
+  /* I initially thought that it would be a good idea to cache the glyph   */
+  /* hints too.  However, my general idea now is that if you really need   */
+  /* to cache these too, you are simply in need of a new font format,      */
+  /* where all this information could be stored within the font file and   */
+  /* decoded on the fly.                                                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  typedef struct FT_AutoHinterRec_  *FT_AutoHinter;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_AutoHinter_Get_Global_Func                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Retrieves the global hints computed for a given face object the    */
+  /*    resulting data is dissociated from the face and will survive a     */
+  /*    call to FT_Done_Face(). It must be discarded through the API       */
+  /*    FT_AutoHinter_Done_Global_Func().                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    hinter        :: A handle to the source auto-hinter.               */
+  /*                                                                       */
+  /*    face          :: A handle to the source face object.               */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    global_hints  :: A typeless pointer to the global hints.           */
+  /*                                                                       */
+  /*    global_len    :: The size in bytes of the global hints.            */
+  /*                                                                       */
+  typedef void
+  (*FT_AutoHinter_Get_Global_Func)( FT_AutoHinter  hinter,
+                                    FT_Face        face,
+                                    void**         global_hints,
+                                    long*          global_len );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_AutoHinter_Done_Global_Func                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards the global hints retrieved through                        */
+  /*    FT_AutoHinter_Get_Global_Func().  This is the only way these hints */
+  /*    are freed from memory.                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    hinter :: A handle to the auto-hinter module.                      */
+  /*                                                                       */
+  /*    global :: A pointer to retrieved global hints to discard.          */
+  /*                                                                       */
+  typedef void
+  (*FT_AutoHinter_Done_Global_Func)( FT_AutoHinter  hinter,
+                                     void*          global );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_AutoHinter_Reset_Func                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used to recompute the global metrics in a given   */
+  /*    font.  This is useful when global font data changes (e.g. Multiple */
+  /*    Masters fonts where blend coordinates change).                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    hinter :: A handle to the source auto-hinter.                      */
+  /*                                                                       */
+  /*    face   :: A handle to the face.                                    */
+  /*                                                                       */
+  typedef void
+  (*FT_AutoHinter_Reset_Func)( FT_AutoHinter  hinter,
+                               FT_Face        face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_AutoHinter_Load_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used to load, scale, and automatically hint a     */
+  /*    glyph from a given face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the face.                               */
+  /*    glyph_index :: The glyph index.                                    */
+  /*    load_flags  :: The load flags.                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function is capable of loading composite glyphs by hinting    */
+  /*    each sub-glyph independently (which improves quality).             */
+  /*                                                                       */
+  /*    It will call the font driver with FT_Load_Glyph(), with            */
+  /*    FT_LOAD_NO_SCALE set.                                              */
+  /*                                                                       */
+  typedef FT_Error
+  (*FT_AutoHinter_Load_Func)( FT_AutoHinter  hinter,
+                              FT_GlyphSlot   slot,
+                              FT_Size        size,
+                              FT_UInt        glyph_index,
+                              FT_ULong       load_flags );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_AutoHinter_Interface                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The auto-hinter module's interface.                                */
+  /*                                                                       */
+  typedef struct  FT_AutoHinter_Interface
+  {
+    FT_AutoHinter_Reset_Func        reset_face;
+    FT_AutoHinter_Load_Func         load_glyph;
+
+    FT_AutoHinter_Get_Global_Func   get_global_hints;
+    FT_AutoHinter_Done_Global_Func  done_global_hints;
+
+  } FT_AutoHinter_Interface;
+
+
+FT_END_HEADER
+
+#endif /* __AUTOHINT_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/cfftypes.h b/libraries/freetype-2.0.5/include/freetype/internal/cfftypes.h
new file mode 100644 (file)
index 0000000..4465f57
--- /dev/null
@@ -0,0 +1,249 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cfftypes.h                                                             */
+/*                                                                         */
+/*    Basic OpenType/CFF type definitions and interface (specification     */
+/*    only).                                                               */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CFFTYPES_H__
+#define __CFFTYPES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    CFF_Index                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a CFF Index table.                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    stream      :: The source input stream.                            */
+  /*                                                                       */
+  /*    count       :: The number of elements in the index.                */
+  /*                                                                       */
+  /*    off_size    :: The size in bytes of object offsets in index.       */
+  /*                                                                       */
+  /*    data_offset :: The position of first data byte in the index's      */
+  /*                   bytes.                                              */
+  /*                                                                       */
+  /*    offsets     :: A table of element offsets in the index.            */
+  /*                                                                       */
+  /*    bytes       :: If the index is loaded in memory, its bytes.        */
+  /*                                                                       */
+  typedef struct  CFF_Index_
+  {
+    FT_Stream  stream;
+    FT_UInt    count;
+    FT_Byte    off_size;
+    FT_ULong   data_offset;
+
+    FT_ULong*  offsets;
+    FT_Byte*   bytes;
+
+  } CFF_Index;
+
+
+  typedef struct  CFF_Encoding_
+  {
+    FT_UInt     format;
+    FT_ULong    offset;
+
+    FT_UShort*  sids;
+    FT_UShort*  codes;
+
+  } CFF_Encoding;
+
+
+  typedef struct  CFF_Charset_
+  {
+
+    FT_UInt     format;
+    FT_ULong    offset;
+
+    FT_UShort*  sids;
+
+  } CFF_Charset;
+
+
+  typedef struct  CFF_Font_Dict_
+  {
+    FT_UInt    version;
+    FT_UInt    notice;
+    FT_UInt    copyright;
+    FT_UInt    full_name;
+    FT_UInt    family_name;
+    FT_UInt    weight;
+    FT_Bool    is_fixed_pitch;
+    FT_Fixed   italic_angle;
+    FT_Pos     underline_position;
+    FT_Pos     underline_thickness;
+    FT_Int     paint_type;
+    FT_Int     charstring_type;
+    FT_Matrix  font_matrix;
+    FT_UShort  units_per_em;
+    FT_Vector  font_offset;
+    FT_ULong   unique_id;
+    FT_BBox    font_bbox;
+    FT_Pos     stroke_width;
+    FT_ULong   charset_offset;
+    FT_ULong   encoding_offset;
+    FT_ULong   charstrings_offset;
+    FT_ULong   private_offset;
+    FT_ULong   private_size;
+    FT_Long    synthetic_base;
+    FT_UInt    embedded_postscript;
+    FT_UInt    base_font_name;
+    FT_UInt    postscript;
+
+    /* these should only be used for the top-level font dictionary */
+    FT_UInt    cid_registry;
+    FT_UInt    cid_ordering;
+    FT_ULong   cid_supplement;
+
+    FT_Long    cid_font_version;
+    FT_Long    cid_font_revision;
+    FT_Long    cid_font_type;
+    FT_Long    cid_count;
+    FT_ULong   cid_uid_base;
+    FT_ULong   cid_fd_array_offset;
+    FT_ULong   cid_fd_select_offset;
+    FT_UInt    cid_font_name;
+
+  } CFF_Font_Dict;
+
+
+  typedef struct  CFF_Private_
+  {
+    FT_Byte   num_blue_values;
+    FT_Byte   num_other_blues;
+    FT_Byte   num_family_blues;
+    FT_Byte   num_family_other_blues;
+
+    FT_Pos    blue_values[14];
+    FT_Pos    other_blues[10];
+    FT_Pos    family_blues[14];
+    FT_Pos    family_other_blues[10];
+
+    FT_Fixed  blue_scale;
+    FT_Pos    blue_shift;
+    FT_Pos    blue_fuzz;
+    FT_Pos    standard_width;
+    FT_Pos    standard_height;
+
+    FT_Byte   num_snap_widths;
+    FT_Byte   num_snap_heights;
+    FT_Pos    snap_widths[13];
+    FT_Pos    snap_heights[13];
+    FT_Bool   force_bold;
+    FT_Fixed  force_bold_threshold;
+    FT_Int    lenIV;
+    FT_Int    language_group;
+    FT_Fixed  expansion_factor;
+    FT_Long   initial_random_seed;
+    FT_ULong  local_subrs_offset;
+    FT_Pos    default_width;
+    FT_Pos    nominal_width;
+
+  } CFF_Private;
+
+
+  typedef struct  CFF_FD_Select_
+  {
+    FT_Byte   format;
+    FT_UInt   range_count;
+
+    /* that's the table, taken from the file `as is' */
+    FT_Byte*  data;
+    FT_UInt   data_size;
+
+    /* small cache for format 3 only */
+    FT_UInt   cache_first;
+    FT_UInt   cache_count;
+    FT_Byte   cache_fd;
+
+  } CFF_FD_Select;
+
+
+  /* A SubFont packs a font dict and a private dict together. They are */
+  /* needed to support CID-keyed CFF fonts.                            */
+  typedef struct  CFF_SubFont_
+  {
+    CFF_Font_Dict  font_dict;
+    CFF_Private    private_dict;
+
+    CFF_Index      local_subrs_index;
+    FT_UInt        num_local_subrs;
+    FT_Byte**      local_subrs;
+
+  } CFF_SubFont;
+
+
+  /* maximum number of sub-fonts in a CID-keyed file */
+#define CFF_MAX_CID_FONTS  16
+
+
+  typedef struct  CFF_Font_
+  {
+    FT_Stream      stream;
+    FT_Memory      memory;
+    FT_UInt        num_faces;
+    FT_UInt        num_glyphs;
+
+    FT_Byte        version_major;
+    FT_Byte        version_minor;
+    FT_Byte        header_size;
+    FT_Byte        absolute_offsize;
+
+
+    CFF_Index      name_index;
+    CFF_Index      top_dict_index;
+    CFF_Index      string_index;
+    CFF_Index      global_subrs_index;
+
+    CFF_Encoding   encoding;
+    CFF_Charset    charset;
+
+    CFF_Index      charstrings_index;
+    CFF_Index      font_dict_index;
+    CFF_Index      private_index;
+    CFF_Index      local_subrs_index;
+
+    FT_String*     font_name;
+    FT_UInt        num_global_subrs;
+    FT_Byte**      global_subrs;
+
+    CFF_SubFont    top_font;
+    FT_UInt        num_subfonts;
+    CFF_SubFont*   subfonts[CFF_MAX_CID_FONTS];
+
+    CFF_FD_Select  fd_select;
+
+  } CFF_Font;
+
+
+FT_END_HEADER
+
+#endif /* __CFFTYPES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/fnttypes.h b/libraries/freetype-2.0.5/include/freetype/internal/fnttypes.h
new file mode 100644 (file)
index 0000000..31edaa9
--- /dev/null
@@ -0,0 +1,155 @@
+/***************************************************************************/
+/*                                                                         */
+/*  fnttypes.h                                                             */
+/*                                                                         */
+/*    Basic Windows FNT/FON type definitions and interface (specification  */
+/*    only).                                                               */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FNTTYPES_H__
+#define __FNTTYPES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  typedef struct  WinMZ_Header_
+  {
+    FT_UShort  magic;
+    /* skipped content */
+    FT_UShort  lfanew;
+
+  } WinMZ_Header;
+
+
+  typedef struct  WinNE_Header_
+  {
+    FT_UShort  magic;
+    /* skipped content */
+    FT_UShort  resource_tab_offset;
+    FT_UShort  rname_tab_offset;
+
+  } WinNE_Header;
+
+
+  typedef struct  WinNameInfo_
+  {
+    FT_UShort  offset;
+    FT_UShort  length;
+    FT_UShort  flags;
+    FT_UShort  id;
+    FT_UShort  handle;
+    FT_UShort  usage;
+
+  } WinNameInfo;
+
+
+  typedef struct  WinResourceInfo_
+  {
+    FT_UShort  type_id;
+    FT_UShort  count;
+
+  } WinResourceInfo;
+
+
+#define WINFNT_MZ_MAGIC  0x5A4D
+#define WINFNT_NE_MAGIC  0x454E
+
+
+  typedef struct  WinFNT_Header_
+  {
+    FT_UShort  version;
+    FT_ULong   file_size;
+    FT_Byte    copyright[60];
+    FT_UShort  file_type;
+    FT_UShort  nominal_point_size;
+    FT_UShort  vertical_resolution;
+    FT_UShort  horizontal_resolution;
+    FT_UShort  ascent;
+    FT_UShort  internal_leading;
+    FT_UShort  external_leading;
+    FT_Byte    italic;
+    FT_Byte    underline;
+    FT_Byte    strike_out;
+    FT_UShort  weight;
+    FT_Byte    charset;
+    FT_UShort  pixel_width;
+    FT_UShort  pixel_height;
+    FT_Byte    pitch_and_family;
+    FT_UShort  avg_width;
+    FT_UShort  max_width;
+    FT_Byte    first_char;
+    FT_Byte    last_char;
+    FT_Byte    default_char;
+    FT_Byte    break_char;
+    FT_UShort  bytes_per_row;
+    FT_ULong   device_offset;
+    FT_ULong   face_name_offset;
+    FT_ULong   bits_pointer;
+    FT_ULong   bits_offset;
+    FT_Byte    reserved;
+    FT_ULong   flags;
+    FT_UShort  A_space;
+    FT_UShort  B_space;
+    FT_UShort  C_space;
+    FT_UShort  color_table_offset;
+    FT_Byte    reserved2[4];
+
+  } WinFNT_Header;
+
+
+  typedef struct  FNT_Font_
+  {
+    FT_ULong       offset;
+    FT_Int         size_shift;
+
+    WinFNT_Header  header;
+
+    FT_Byte*       fnt_frame;
+    FT_ULong       fnt_size;
+
+  } FNT_Font;
+
+
+  typedef struct  FNT_SizeRec_
+  {
+    FT_SizeRec  root;
+    FNT_Font*   font;
+
+  } FNT_SizeRec, *FNT_Size;
+
+
+  typedef struct  FNT_FaceRec_
+  {
+    FT_FaceRec     root;
+
+    FT_UInt        num_fonts;
+    FNT_Font*      fonts;
+
+    FT_CharMap     charmap_handle;
+    FT_CharMapRec  charmap;  /* a single charmap per face */
+
+  } FNT_FaceRec, *FNT_Face;
+
+
+FT_END_HEADER
+
+#endif /* __FNTTYPES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/ftcalc.h b/libraries/freetype-2.0.5/include/freetype/internal/ftcalc.h
new file mode 100644 (file)
index 0000000..4cdf40f
--- /dev/null
@@ -0,0 +1,234 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcalc.h                                                               */
+/*                                                                         */
+/*    Arithmetic computations (specification).                             */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTCALC_H__
+#define __FTCALC_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+/* OLD 64-bits internal API */
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+#ifdef FT_LONG64
+
+  typedef FT_INT64  FT_Int64;
+
+#define ADD_64( x, y, z )  z = (x) + (y)
+#define MUL_64( x, y, z )  z = (FT_Int64)(x) * (y)
+#define DIV_64( x, y )     ( (x) / (y) )
+
+#define SQRT_64( z )  FT_Sqrt64( z )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Sqrt64                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the square root of a 64-bit value.  That sounds stupid,   */
+  /*    but it is needed to obtain maximal accuracy in the TrueType        */
+  /*    bytecode interpreter.                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    l :: A 64-bit integer.                                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The 32-bit square-root.                                            */
+  /*                                                                       */
+  FT_EXPORT( FT_Int32 )
+  FT_Sqrt64( FT_Int64  l );
+
+
+#else /* !FT_LONG64 */
+
+
+  typedef struct  FT_Int64_
+  {
+    FT_UInt32  lo;
+    FT_UInt32  hi;
+
+  } FT_Int64;
+
+
+#define ADD_64( x, y, z )  FT_Add64( &x, &y, &z )
+#define MUL_64( x, y, z )  FT_MulTo64( x, y, &z )
+#define DIV_64( x, y )     FT_Div64by32( &x, y )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Add64                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Add two Int64 values.                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x :: A pointer to the first value to be added.                     */
+  /*    y :: A pointer to the second value to be added.                    */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    z :: A pointer to the result of `x + y'.                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Will be wrapped by the ADD_64() macro.                             */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Add64( FT_Int64*  x,
+            FT_Int64*  y,
+            FT_Int64  *z );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_MulTo64                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Multiplies two Int32 integers.  Returns an Int64 integer.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x :: The first multiplier.                                         */
+  /*    y :: The second multiplier.                                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    z :: A pointer to the result of `x * y'.                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Will be wrapped by the MUL_64() macro.                             */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_MulTo64( FT_Int32   x,
+              FT_Int32   y,
+              FT_Int64  *z );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Div64by32                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Divides an Int64 value by an Int32 value.  Returns an Int32        */
+  /*    integer.                                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x :: A pointer to the dividend.                                    */
+  /*    y :: The divisor.                                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `x / y'.                                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Will be wrapped by the DIV_64() macro.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Int32 )
+  FT_Div64by32( FT_Int64*  x,
+                FT_Int32   y );
+
+
+#define SQRT_64( z )  FT_Sqrt64( &z )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Sqrt64                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the square root of a 64-bits value.  That sounds stupid,  */
+  /*    but it is needed to obtain maximal accuracy in the TrueType        */
+  /*    bytecode interpreter.                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    z :: A pointer to a 64-bit integer.                                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The 32-bit square-root.                                            */
+  /*                                                                       */
+  FT_EXPORT( FT_Int32 )
+  FT_Sqrt64( FT_Int64*  x );
+
+
+#endif /* !FT_LONG64 */
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+
+  FT_EXPORT( FT_Int32 )  FT_SqrtFixed( FT_Int32  x );
+
+
+#ifndef FT_CONFIG_OPTION_OLD_CALCS
+
+#define SQRT_32( x )  FT_Sqrt32( x )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Sqrt32                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the square root of an Int32 integer (which will be        */
+  /*    handled as an unsigned long value).                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x :: The value to compute the root for.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The result of `sqrt(x)'.                                           */
+  /*                                                                       */
+  FT_EXPORT( FT_Int32 )
+  FT_Sqrt32( FT_Int32  x );
+
+
+#endif /* !FT_CONFIG_OPTION_OLD_CALCS */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FT_MulDiv() and FT_MulFix() are declared in freetype.h.               */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define INT_TO_F26DOT6( x )    ( (FT_Long)(x) << 6  )
+#define INT_TO_F2DOT14( x )    ( (FT_Long)(x) << 14 )
+#define INT_TO_FIXED( x )      ( (FT_Long)(x) << 16 )
+#define F2DOT14_TO_FIXED( x )  ( (FT_Long)(x) << 2  )
+#define FLOAT_TO_FIXED( x )    ( (FT_Long)( x * 65536.0 ) )
+
+#define ROUND_F26DOT6( x )     ( x >= 0 ? (    ( (x) + 32 ) & -64 )     \
+                                        : ( -( ( 32 - (x) ) & -64 ) ) )
+
+
+FT_END_HEADER
+
+#endif /* __FTCALC_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/ftdebug.h b/libraries/freetype-2.0.5/include/freetype/internal/ftdebug.h
new file mode 100644 (file)
index 0000000..f876580
--- /dev/null
@@ -0,0 +1,242 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftdebug.h                                                              */
+/*                                                                         */
+/*    Debugging and logging component (specification).                     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTDEBUG_H__
+#define __FTDEBUG_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+
+
+FT_BEGIN_HEADER
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+
+  /* note that not all levels are used currently */
+
+  typedef enum  FT_Trace_
+  {
+    /* the first level must always be `trace_any' */
+    trace_any = 0,
+
+    /* base components */
+    trace_aaraster,  /* anti-aliasing raster    (ftgrays.c)  */
+    trace_calc,      /* calculations            (ftcalc.c)   */
+    trace_extend,    /* extension manager       (ftextend.c) */
+    trace_glyph,     /* glyph manager           (ftglyph.c)  */
+    trace_io,        /* i/o monitoring          (ftsystem.c) */
+    trace_init,      /* initialization          (ftinit.c)   */
+    trace_list,      /* list manager            (ftlist.c)   */
+    trace_memory,    /* memory manager          (ftobjs.c)   */
+    trace_mm,        /* MM interface            (ftmm.c)     */
+    trace_objs,      /* base objects            (ftobjs.c)   */
+    trace_outline,   /* outline management      (ftoutln.c)  */
+    trace_raster,    /* rasterizer              (ftraster.c) */
+    trace_stream,    /* stream manager          (ftstream.c) */
+
+    /* Cache sub-system */
+    trace_cache,
+
+    /* SFNT driver components */
+    trace_sfobjs,    /* SFNT object handler     (sfobjs.c)   */
+    trace_ttcmap,    /* charmap handler         (ttcmap.c)   */
+    trace_ttload,    /* basic TrueType tables   (ttload.c)   */
+    trace_ttpost,    /* PS table processing     (ttpost.c)   */
+    trace_ttsbit,    /* TrueType sbit handling  (ttsbit.c)   */
+
+    /* TrueType driver components */
+    trace_ttdriver,  /* TT font driver          (ttdriver.c) */
+    trace_ttgload,   /* TT glyph loader         (ttgload.c)  */
+    trace_ttinterp,  /* bytecode interpreter    (ttinterp.c) */
+    trace_ttobjs,    /* TT objects manager      (ttobjs.c)   */
+    trace_ttpload,   /* TT data/program loader  (ttpload.c)  */
+
+    /* Type 1 driver components */
+    trace_t1driver,
+    trace_t1gload,
+    trace_t1hint,
+    trace_t1load,
+    trace_t1objs,
+    trace_t1parse,
+
+    /* PostScript helper module `psaux' */
+    trace_t1decode,
+    trace_psobjs,
+
+    /* Type 2 driver components */
+    trace_cffdriver,
+    trace_cffgload,
+    trace_cffload,
+    trace_cffobjs,
+    trace_cffparse,
+
+    /* CID driver components */
+    trace_cidafm,
+    trace_ciddriver,
+    trace_cidgload,
+    trace_cidload,
+    trace_cidobjs,
+    trace_cidparse,
+
+    /* Windows fonts component */
+    trace_winfnt,
+
+    /* PCF fonts component */
+    trace_pcfdriver,
+    trace_pcfread,
+
+    /* the last level must always be `trace_max' */
+    trace_max
+
+  } FT_Trace;
+
+
+  /* declared in ftdebug.c */
+  extern char  ft_trace_levels[trace_max];
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IMPORTANT!                                                            */
+  /*                                                                       */
+  /* Each component must define the macro FT_COMPONENT to a valid FT_Trace */
+  /* value before using any TRACE macro.                                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define FT_TRACE( level, varformat )                      \
+          do                                              \
+          {                                               \
+            if ( ft_trace_levels[FT_COMPONENT] >= level ) \
+              FT_Message varformat;                       \
+          } while ( 0 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_SetTraceLevel                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the trace level for debugging.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    component :: The component which should be traced.  See above for  */
+  /*                 a complete list.  If set to `trace_any', all          */
+  /*                 components will be traced.                            */
+  /*                                                                       */
+  /*    level     :: The tracing level.                                    */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_SetTraceLevel( FT_Trace  component,
+                    char      level );
+
+
+#elif defined( FT_DEBUG_LEVEL_ERROR )
+
+
+#define FT_TRACE( level, varformat )  do ; while ( 0 )      /* nothing */
+
+
+#else  /* release mode */
+
+
+#define FT_Assert( condition )        do ; while ( 0 )      /* nothing */
+
+#define FT_TRACE( level, varformat )  do ; while ( 0 )      /* nothing */
+#define FT_ERROR( varformat )         do ; while ( 0 )      /* nothing */
+
+
+#endif /* FT_DEBUG_LEVEL_TRACE, FT_DEBUG_LEVEL_ERROR */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Define macros and functions that are common to the debug and trace    */
+  /* modes.                                                                */
+  /*                                                                       */
+  /* You need vprintf() to be able to compile ftdebug.c.                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#if defined( FT_DEBUG_LEVEL_TRACE ) || defined( FT_DEBUG_LEVEL_ERROR )
+
+
+#include "stdio.h"  /* for vprintf() */
+
+
+#define FT_Assert( condition )                                      \
+          do                                                        \
+          {                                                         \
+            if ( !( condition ) )                                   \
+              FT_Panic( "assertion failed on line %d of file %s\n", \
+                        __LINE__, __FILE__ );                       \
+          } while ( 0 )
+
+  /* print a message */
+  FT_EXPORT( void )
+  FT_Message( const char*  fmt, ... );
+
+  /* print a message and exit */
+  FT_EXPORT( void )
+  FT_Panic( const char*  fmt, ... );
+
+#define FT_ERROR( varformat )  FT_Message varformat
+
+
+#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* You need two opening resp. closing parentheses!                       */
+  /*                                                                       */
+  /* Example: FT_TRACE0(( "Value is %i", foo ))                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+#define FT_TRACE0( varformat )  FT_TRACE( 0, varformat )
+#define FT_TRACE1( varformat )  FT_TRACE( 1, varformat )
+#define FT_TRACE2( varformat )  FT_TRACE( 2, varformat )
+#define FT_TRACE3( varformat )  FT_TRACE( 3, varformat )
+#define FT_TRACE4( varformat )  FT_TRACE( 4, varformat )
+#define FT_TRACE5( varformat )  FT_TRACE( 5, varformat )
+#define FT_TRACE6( varformat )  FT_TRACE( 6, varformat )
+#define FT_TRACE7( varformat )  FT_TRACE( 7, varformat )
+
+
+#if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
+
+  /* we disable the warning `conditional expression is constant' here */
+  /* in order to compile cleanly with the maximum level of warnings   */
+#pragma warning( disable : 4127 )
+
+#endif /* _MSC_VER */
+
+
+FT_END_HEADER
+
+#endif /* __FTDEBUG_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/ftdriver.h b/libraries/freetype-2.0.5/include/freetype/internal/ftdriver.h
new file mode 100644 (file)
index 0000000..6d58573
--- /dev/null
@@ -0,0 +1,200 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftdriver.h                                                             */
+/*                                                                         */
+/*    FreeType font driver interface (specification).                      */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTDRIVER_H__
+#define __FTDRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+  typedef FT_Error
+  (*FTDriver_initFace)( FT_Stream      stream,
+                        FT_Face        face,
+                        FT_Int         typeface_index,
+                        FT_Int         num_params,
+                        FT_Parameter*  parameters );
+
+  typedef void
+  (*FTDriver_doneFace)( FT_Face  face );
+
+
+  typedef FT_Error
+  (*FTDriver_initSize)( FT_Size  size );
+
+  typedef void
+  (*FTDriver_doneSize)( FT_Size  size );
+
+
+  typedef FT_Error
+  (*FTDriver_initGlyphSlot)( FT_GlyphSlot  slot );
+
+  typedef void
+  (*FTDriver_doneGlyphSlot)( FT_GlyphSlot  slot );
+
+
+  typedef FT_Error
+  (*FTDriver_setCharSizes)( FT_Size     size,
+                            FT_F26Dot6  char_width,
+                            FT_F26Dot6  char_height,
+                            FT_UInt     horz_resolution,
+                            FT_UInt     vert_resolution );
+
+  typedef FT_Error
+  (*FTDriver_setPixelSizes)( FT_Size  size,
+                             FT_UInt  pixel_width,
+                             FT_UInt  pixel_height );
+
+  typedef FT_Error
+  (*FTDriver_loadGlyph)( FT_GlyphSlot  slot,
+                         FT_Size       size,
+                         FT_UInt       glyph_index,
+                         FT_Int        load_flags );
+
+
+  typedef FT_UInt
+  (*FTDriver_getCharIndex)( FT_CharMap  charmap,
+                            FT_Long     charcode );
+
+  typedef FT_Error
+  (*FTDriver_getKerning)( FT_Face      face,
+                          FT_UInt      left_glyph,
+                          FT_UInt      right_glyph,
+                          FT_Vector*   kerning );
+
+
+  typedef FT_Error
+  (*FTDriver_attachFile)( FT_Face    face,
+                          FT_Stream  stream );
+
+
+  typedef FT_Error
+  (*FTDriver_getAdvances)( FT_Face     face,
+                           FT_UInt     first,
+                           FT_UInt     count,
+                           FT_Bool     vertical,
+                           FT_UShort*  advances );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Driver_Class                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The font driver class.  This structure mostly contains pointers to */
+  /*    driver methods.                                                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root             :: The parent module.                             */
+  /*                                                                       */
+  /*    face_object_size :: The size of a face object in bytes.            */
+  /*                                                                       */
+  /*    size_object_size :: The size of a size object in bytes.            */
+  /*                                                                       */
+  /*    slot_object_size :: The size of a glyph object in bytes.           */
+  /*                                                                       */
+  /*    init_face        :: The format-specific face constructor.          */
+  /*                                                                       */
+  /*    done_face        :: The format-specific face destructor.           */
+  /*                                                                       */
+  /*    init_size        :: The format-specific size constructor.          */
+  /*                                                                       */
+  /*    done_size        :: The format-specific size destructor.           */
+  /*                                                                       */
+  /*    init_slot        :: The format-specific slot constructor.          */
+  /*                                                                       */
+  /*    done_slot        :: The format-specific slot destructor.           */
+  /*                                                                       */
+  /*    set_char_sizes   :: A handle to a function used to set the new     */
+  /*                        character size in points + resolution.  Can be */
+  /*                        set to 0 to indicate default behaviour.        */
+  /*                                                                       */
+  /*    set_pixel_sizes  :: A handle to a function used to set the new     */
+  /*                        character size in pixels.  Can be set to 0 to  */
+  /*                        indicate default behaviour.                    */
+  /*                                                                       */
+  /*    load_glyph       :: A function handle to load a given glyph image  */
+  /*                        in a slot.  This field is mandatory!           */
+  /*                                                                       */
+  /*    get_char_index   :: A function handle to return the glyph index of */
+  /*                        a given character for a given charmap.  This   */
+  /*                        field is mandatory!                            */
+  /*                                                                       */
+  /*    get_kerning      :: A function handle to return the unscaled       */
+  /*                        kerning for a given pair of glyphs.  Can be    */
+  /*                        set to 0 if the format doesn't support         */
+  /*                        kerning.                                       */
+  /*                                                                       */
+  /*    attach_file      :: This function handle is used to read           */
+  /*                        additional data for a face from another        */
+  /*                        file/stream.  For example, this can be used to */
+  /*                        add data from AFM or PFM files on a Type 1     */
+  /*                        face, or a CIDMap on a CID-keyed face.         */
+  /*                                                                       */
+  /*    get_advances     :: A function handle used to return the advances  */
+  /*                        of 'count' glyphs, starting at `index'.  the   */
+  /*                        `vertical' flags must be set when vertical     */
+  /*                        advances are queried.  The advances buffer is  */
+  /*                        caller-allocated.                              */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Most function pointers, with the exception of `load_glyph' and     */
+  /*    `get_char_index' can be set to 0 to indicate a default behaviour.  */
+  /*                                                                       */
+  typedef struct  FT_Driver_Class_
+  {
+    FT_Module_Class         root;
+
+    FT_Int                  face_object_size;
+    FT_Int                  size_object_size;
+    FT_Int                  slot_object_size;
+
+    FTDriver_initFace       init_face;
+    FTDriver_doneFace       done_face;
+
+    FTDriver_initSize       init_size;
+    FTDriver_doneSize       done_size;
+
+    FTDriver_initGlyphSlot  init_slot;
+    FTDriver_doneGlyphSlot  done_slot;
+
+    FTDriver_setCharSizes   set_char_sizes;
+    FTDriver_setPixelSizes  set_pixel_sizes;
+
+    FTDriver_loadGlyph      load_glyph;
+    FTDriver_getCharIndex   get_char_index;
+
+    FTDriver_getKerning     get_kerning;
+    FTDriver_attachFile     attach_file;
+
+    FTDriver_getAdvances    get_advances;
+
+  } FT_Driver_Class;
+
+
+FT_END_HEADER
+
+#endif /* __FTDRIVER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/ftextend.h b/libraries/freetype-2.0.5/include/freetype/internal/ftextend.h
new file mode 100644 (file)
index 0000000..8257a2a
--- /dev/null
@@ -0,0 +1,211 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftextend.h                                                             */
+/*                                                                         */
+/*    FreeType extensions implementation (specification).                  */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTEXTEND_H__
+#define __FTEXTEND_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The extensions don't need to be integrated at compile time into the   */
+  /* engine, only at link time.                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Extension_Initializer                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Each new face object can have several extensions associated with   */
+  /*    it at creation time.  This function is used to initialize given    */
+  /*    extension data for a given face.                                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    ext  :: A typeless pointer to the extension data.                  */
+  /*                                                                       */
+  /*    face :: A handle to the source face object the extension is        */
+  /*            associated with.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    In case of error, the initializer should not destroy the extension */
+  /*    data, as the finalizer will get called later by the function's     */
+  /*    caller.                                                            */
+  /*                                                                       */
+  typedef FT_Error
+  (*FT_Extension_Initializer)( void*    ext,
+                               FT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    FT_Extension_Finalizer                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Each new face object can have several extensions associated with   */
+  /*    it at creation time.  This function is used to finalize given      */
+  /*    extension data for a given face; it occurs before the face object  */
+  /*    itself is finalized.                                               */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    ext  :: A typeless pointer to the extension data.                  */
+  /*                                                                       */
+  /*    face :: A handle to the source face object the extension is        */
+  /*            associated with.                                           */
+  /*                                                                       */
+  typedef void
+  (*FT_Extension_Finalizer)( void*    ext,
+                             FT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Extension_Class                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure used to describe a given extension to the       */
+  /*    FreeType base layer.  An FT_Extension_Class is used as a parameter */
+  /*    for FT_Register_Extension().                                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    id        :: The extension's ID.  This is a normal C string that   */
+  /*                 is used to uniquely reference the extension's         */
+  /*                 interface.                                            */
+  /*                                                                       */
+  /*    size      :: The size in bytes of the extension data that must be  */
+  /*                 associated with each face object.                     */
+  /*                                                                       */
+  /*    init      :: A pointer to the extension data's initializer.        */
+  /*                                                                       */
+  /*    finalize  :: A pointer to the extension data's finalizer.          */
+  /*                                                                       */
+  /*    interface :: This pointer can be anything, but should usually      */
+  /*                 point to a table of function pointers which implement */
+  /*                 the extension's interface.                            */
+  /*                                                                       */
+  /*    offset    :: This field is set and used within the base layer and  */
+  /*                 should be set to 0 when registering an extension      */
+  /*                 through FT_Register_Extension().  It contains an      */
+  /*                 offset within the face's extension block for the      */
+  /*                 current extension's data.                             */
+  /*                                                                       */
+  typedef struct  FT_Extension_Class_
+  {
+    const char*               id;
+    FT_ULong                  size;
+    FT_Extension_Initializer  init;
+    FT_Extension_Finalizer    finalize;
+    void*                     interface;
+
+    FT_ULong                  offset;
+
+  } FT_Extension_Class;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Register_Extension                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Registers a new extension.                                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    driver :: A handle to the driver object.                           */
+  /*                                                                       */
+  /*    class  :: A pointer to a class describing the extension.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Register_Extension( FT_Driver            driver,
+                         FT_Extension_Class*  clazz );
+
+
+#ifdef FT_CONFIG_OPTION_EXTEND_ENGINE
+
+
+  /* Initialize the extension component */
+  FT_LOCAL FT_Error
+  FT_Init_Extensions( FT_Library  library );
+
+  /* Finalize the extension component */
+  FT_LOCAL FT_Error
+  FT_Done_Extensions( FT_Library  library );
+
+  /* Create an extension within a face object.  Called by the */
+  /* face object constructor.                                 */
+  FT_LOCAL FT_Error
+  FT_Create_Extensions( FT_Face  face );
+
+  /* Destroy all extensions within a face object.  Called by the */
+  /* face object destructor.                                     */
+  FT_LOCAL FT_Error
+  FT_Destroy_Extensions( FT_Face  face );
+
+
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Extension                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Queries an extension block by an extension ID string.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face                :: A handle to the face object.                */
+  /*    extension_id        :: An ID string identifying the extension.     */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    extension_interface :: A generic pointer, usually pointing to a    */
+  /*                           table of functions implementing the         */
+  /*                           extension interface.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A generic pointer to the extension block.                          */
+  /*                                                                       */
+  FT_EXPORT( void* )
+  FT_Get_Extension( FT_Face      face,
+                    const char*  extension_id,
+                    void**       extension_interface );
+
+
+FT_END_HEADER
+
+#endif /* __FTEXTEND_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/ftmemory.h b/libraries/freetype-2.0.5/include/freetype/internal/ftmemory.h
new file mode 100644 (file)
index 0000000..e64865e
--- /dev/null
@@ -0,0 +1,212 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftmemory.h                                                             */
+/*                                                                         */
+/*    The FreeType memory management macros (specification).               */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg                       */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTMEMORY_H__
+#define __FTMEMORY_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Macro>                                                               */
+  /*    FT_SET_ERROR                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This macro is used to set an implicit `error' variable to a given  */
+  /*    expression's value (usually a function call), and convert it to a  */
+  /*    boolean which is set whenever the value is != 0.                   */
+  /*                                                                       */
+#undef  FT_SET_ERROR
+#define FT_SET_ERROR( expression ) \
+          ( ( error = (expression) ) != 0 )
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                           M E M O R Y                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Alloc                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Allocates a new block of memory.  The returned area is always      */
+  /*    zero-filled; this is a strong convention in many FreeType parts.   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A handle to a given `memory object' which handles        */
+  /*              allocation.                                              */
+  /*                                                                       */
+  /*    size   :: The size in bytes of the block to allocate.              */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    P      :: A pointer to the fresh new block.  It should be set to   */
+  /*              NULL if `size' is 0, or in case of error.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_BASE( FT_Error )
+  FT_Alloc( FT_Memory  memory,
+            FT_Long    size,
+            void*     *P );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Realloc                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Reallocates a block of memory pointed to by `*P' to `Size' bytes   */
+  /*    from the heap, possibly changing `*P'.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory  :: A handle to a given `memory object' which handles       */
+  /*               reallocation.                                           */
+  /*                                                                       */
+  /*    current :: The current block size in bytes.                        */
+  /*                                                                       */
+  /*    size    :: The new block size in bytes.                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    P       :: A pointer to the fresh new block.  It should be set to  */
+  /*               NULL if `size' is 0, or in case of error.               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    All callers of FT_Realloc() _must_ provide the current block size  */
+  /*    as well as the new one.                                            */
+  /*                                                                       */
+  FT_BASE( FT_Error )
+  FT_Realloc( FT_Memory  memory,
+              FT_Long    current,
+              FT_Long    size,
+              void**     P );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Free                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Releases a given block of memory allocated through FT_Alloc().     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A handle to a given `memory object' which handles        */
+  /*              memory deallocation                                      */
+  /*                                                                       */
+  /*    P      :: This is the _address_ of a _pointer_ which points to the */
+  /*              allocated block.  It is always set to NULL on exit.      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    If P or *P are NULL, this function should return successfully.     */
+  /*    This is a strong convention within all of FreeType and its         */
+  /*    drivers.                                                           */
+  /*                                                                       */
+  FT_BASE( void )
+  FT_Free( FT_Memory  memory,
+           void**     P );
+
+
+
+  /* This `#include' is needed by the MEM_xxx() macros; it should be */
+  /* available on all platforms we know of.                          */
+#include <string.h>
+
+#define MEM_Set( dest, byte, count )  memset( dest, byte, count )
+
+#define MEM_Copy( dest, source, count )  memcpy( dest, source, count )
+
+#define MEM_Move( dest, source, count )  memmove( dest, source, count )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* We now support closures to produce completely reentrant code.  This   */
+  /* means the allocation functions now takes an additional argument       */
+  /* (`memory').  It is a handle to a given memory object, responsible for */
+  /* all low-level operations, including memory management and             */
+  /* synchronisation.                                                      */
+  /*                                                                       */
+  /* In order to keep our code readable and use the same macros in the     */
+  /* font drivers and the rest of the library, MEM_Alloc(), ALLOC(), and   */
+  /* ALLOC_ARRAY() now use an implicit variable, `memory'.  It must be     */
+  /* defined at all locations where a memory operation is queried.         */
+  /*                                                                       */
+#define MEM_Alloc( _pointer_, _size_ )                     \
+          FT_Alloc( memory, _size_, (void**)&(_pointer_) )
+
+#define MEM_Alloc_Array( _pointer_, _count_, _type_ )    \
+          FT_Alloc( memory, (_count_)*sizeof ( _type_ ), \
+                    (void**)&(_pointer_) )
+
+#define MEM_Realloc( _pointer_, _current_, _size_ )                     \
+          FT_Realloc( memory, _current_, _size_, (void**)&(_pointer_) )
+
+#define MEM_Realloc_Array( _pointer_, _current_, _new_, _type_ )        \
+          FT_Realloc( memory, (_current_)*sizeof ( _type_ ),            \
+                      (_new_)*sizeof ( _type_ ), (void**)&(_pointer_) )
+
+#define ALLOC( _pointer_, _size_ )                       \
+          FT_SET_ERROR( MEM_Alloc( _pointer_, _size_ ) )
+
+#define REALLOC( _pointer_, _current_, _size_ )                       \
+          FT_SET_ERROR( MEM_Realloc( _pointer_, _current_, _size_ ) )
+
+#define ALLOC_ARRAY( _pointer_, _count_, _type_ )       \
+          FT_SET_ERROR( MEM_Alloc( _pointer_,           \
+                        (_count_)*sizeof ( _type_ ) ) )
+
+#define REALLOC_ARRAY( _pointer_, _current_, _count_, _type_ ) \
+          FT_SET_ERROR( MEM_Realloc( _pointer_,                \
+                        (_current_)*sizeof ( _type_ ),         \
+                        (_count_)*sizeof ( _type_ ) ) )
+
+#define FREE( _pointer_ )  FT_Free( memory, (void**)&(_pointer_) )
+
+
+FT_END_HEADER
+
+#endif /* __FTMEMORY_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/ftobjs.h b/libraries/freetype-2.0.5/include/freetype/internal/ftobjs.h
new file mode 100644 (file)
index 0000000..9608ace
--- /dev/null
@@ -0,0 +1,736 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftobjs.h                                                               */
+/*                                                                         */
+/*    The FreeType private base classes (specification).                   */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  This file contains the definition of all internal FreeType classes.  */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTOBJS_H__
+#define __FTOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_RENDER_H
+#include FT_SIZES_H
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_DRIVER_H
+#include FT_INTERNAL_AUTOHINT_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Some generic definitions.                                             */
+  /*                                                                       */
+#ifndef TRUE
+#define TRUE  1
+#endif
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#ifndef NULL
+#define NULL  (void*)0
+#endif
+
+#ifndef UNUSED
+#define UNUSED( arg )  ( (arg)=(arg) )
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The min and max functions missing in C.  As usual, be careful not to  */
+  /* write things like MIN( a++, b++ ) to avoid side effects.              */
+  /*                                                                       */
+#ifndef MIN
+#define MIN( a, b )  ( (a) < (b) ? (a) : (b) )
+#endif
+
+#ifndef MAX
+#define MAX( a, b )  ( (a) > (b) ? (a) : (b) )
+#endif
+
+#ifndef ABS
+#define ABS( a )     ( (a) < 0 ? -(a) : (a) )
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_GlyphLoader                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The glyph loader is an internal object used to load several glyphs */
+  /*    together (for example, in the case of composites).                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The glyph loader implementation is not part of the high-level API, */
+  /*    hence the forward structure declaration.                           */
+  /*                                                                       */
+  typedef struct FT_GlyphLoader_  FT_GlyphLoader;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Face_InternalRec                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure contains the internal fields of each FT_Face        */
+  /*    object.  These fields may change between different releases of     */
+  /*    FreeType.                                                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    max_points       :: The maximal number of points used to store the */
+  /*                        vectorial outline of any glyph in this face.   */
+  /*                        If this value cannot be known in advance, or   */
+  /*                        if the face isn't scalable, this should be set */
+  /*                        to 0.  Only relevant for scalable formats.     */
+  /*                                                                       */
+  /*    max_contours     :: The maximal number of contours used to store   */
+  /*                        the vectorial outline of any glyph in this     */
+  /*                        face.  If this value cannot be known in        */
+  /*                        advance, or if the face isn't scalable, this   */
+  /*                        should be set to 0.  Only relevant for         */
+  /*                        scalable formats.                              */
+  /*                                                                       */
+  /*    transform_matrix :: A 2x2 matrix of 16.16 coefficients used to     */
+  /*                        transform glyph outlines after they are loaded */
+  /*                        from the font.  Only used by the convenience   */
+  /*                        functions.                                     */
+  /*                                                                       */
+  /*    transform_delta  :: A translation vector used to transform glyph   */
+  /*                        outlines after they are loaded from the font.  */
+  /*                        Only used by the convenience functions.        */
+  /*                                                                       */
+  /*    transform_flags  :: Some flags used to classify the transform.     */
+  /*                        Only used by the convenience functions.        */
+  /*                                                                       */
+  /*    postscript_name  :: Postscript font name for this face.            */
+  /*                                                                       */
+  typedef struct  FT_Face_InternalRec_
+  {
+    FT_UShort    max_points;
+    FT_Short     max_contours;
+
+    FT_Matrix    transform_matrix;
+    FT_Vector    transform_delta;
+    FT_Int       transform_flags;
+
+    const char*  postscript_name;
+
+  } FT_Face_InternalRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_Slot_InternalRec                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure contains the internal fields of each FT_GlyphSlot   */
+  /*    object.  These fields may change between different releases of     */
+  /*    FreeType.                                                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    loader            :: The glyph loader object used to load outlines */
+  /*                         into the glyph slot.                          */
+  /*                                                                       */
+  /*    glyph_transformed :: Boolean.  Set to TRUE when the loaded glyph   */
+  /*                         must be transformed through a specific        */
+  /*                         font transformation.  This is _not_ the same  */
+  /*                         as the face transform set through             */
+  /*                         FT_Set_Transform().                           */
+  /*                                                                       */
+  /*    glyph_matrix      :: The 2x2 matrix corresponding to the glyph     */
+  /*                         transformation, if necessary.                 */
+  /*                                                                       */
+  /*    glyph_delta       :: The 2d translation vector corresponding to    */
+  /*                         the glyph transformation, if necessary.       */
+  /*                                                                       */
+  typedef struct FT_Slot_InternalRec_
+  {
+    FT_GlyphLoader*   loader;
+    FT_Bool           glyph_transformed;
+    FT_Matrix         glyph_matrix;
+    FT_Vector         glyph_delta;
+
+  } FT_GlyphSlot_InternalRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                         M O D U L E S                           ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_ModuleRec                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A module object instance.                                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    clazz   :: A pointer to the module's class.                        */
+  /*                                                                       */
+  /*    library :: A handle to the parent library object.                  */
+  /*                                                                       */
+  /*    memory  :: A handle to the memory manager.                         */
+  /*                                                                       */
+  /*    generic :: A generic structure for user-level extensibility (?).   */
+  /*                                                                       */
+  typedef struct  FT_ModuleRec_
+  {
+    FT_Module_Class*  clazz;
+    FT_Library        library;
+    FT_Memory         memory;
+    FT_Generic        generic;
+
+  } FT_ModuleRec;
+
+
+  /* typecast an object to a FT_Module */
+#define FT_MODULE( x )          ((FT_Module)(x))
+#define FT_MODULE_CLASS( x )    FT_MODULE(x)->clazz
+#define FT_MODULE_LIBRARY( x )  FT_MODULE(x)->library
+#define FT_MODULE_MEMORY( x )   FT_MODULE(x)->memory
+
+#define FT_MODULE_IS_DRIVER( x )  ( FT_MODULE_CLASS( x )->module_flags & \
+                                    ft_module_font_driver )
+
+#define FT_MODULE_IS_RENDERER( x )  ( FT_MODULE_CLASS( x )->module_flags & \
+                                      ft_module_renderer )
+
+#define FT_MODULE_IS_HINTER( x )  ( FT_MODULE_CLASS( x )->module_flags & \
+                                    ft_module_hinter )
+
+#define FT_MODULE_IS_STYLER( x )  ( FT_MODULE_CLASS( x )->module_flags & \
+                                    ft_module_styler )
+
+#define FT_DRIVER_IS_SCALABLE( x )  ( FT_MODULE_CLASS(x)->module_flags & \
+                                      ft_module_driver_scalable )
+
+#define FT_DRIVER_USES_OUTLINES( x )  !( FT_MODULE_CLASS(x)->module_flags & \
+                                         ft_module_driver_no_outlines )
+
+#define FT_DRIVER_HAS_HINTER( x )  ( FT_MODULE_CLASS(x)->module_flags & \
+                                     ft_module_driver_has_hinter )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Module_Interface                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finds a module and returns its specific interface as a typeless    */
+  /*    pointer.                                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    library     :: A handle to the library object.                     */
+  /*                                                                       */
+  /*    module_name :: The module's name (as an ASCII string).             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A module-specific interface if available, 0 otherwise.             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    You should better be familiar with FreeType internals to know      */
+  /*    which module to look for, and what its interface is :-)            */
+  /*                                                                       */
+  FT_BASE( const void* )
+  FT_Get_Module_Interface( FT_Library   library,
+                           const char*  mod_name );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* a few macros used to perform easy typecasts with minimal brain damage */
+
+#define FT_FACE( x )          ((FT_Face)(x))
+#define FT_SIZE( x )          ((FT_Size)(x))
+#define FT_SLOT( x )          ((FT_GlyphSlot)(x))
+
+#define FT_FACE_DRIVER( x )   FT_FACE( x )->driver
+#define FT_FACE_LIBRARY( x )  FT_FACE_DRIVER( x )->root.library
+#define FT_FACE_MEMORY( x )   FT_FACE( x )->memory
+
+#define FT_SIZE_FACE( x )     FT_SIZE( x )->face
+#define FT_SLOT_FACE( x )     FT_SLOT( x )->face
+
+#define FT_FACE_SLOT( x )     FT_FACE( x )->glyph
+#define FT_FACE_SIZE( x )     FT_FACE( x )->size
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_GlyphSlot                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    It is sometimes useful to have more than one glyph slot for a      */
+  /*    given face object.  This function is used to create additional     */
+  /*    slots.  All of them are automatically discarded when the face is   */
+  /*    destroyed.                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face  :: A handle to a parent face object.                         */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    aslot :: A handle to a new glyph slot object.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_BASE( FT_Error )
+  FT_New_GlyphSlot( FT_Face        face,
+                    FT_GlyphSlot  *aslot );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_GlyphSlot                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given glyph slot.  Remember however that all slots are  */
+  /*    automatically destroyed with its parent.  Using this function is   */
+  /*    not always mandatory.                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot :: A handle to a target glyph slot.                           */
+  /*                                                                       */
+  FT_BASE( void )
+  FT_Done_GlyphSlot( FT_GlyphSlot  slot );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                   G L Y P H   L O A D E R                       ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS          1
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES      2
+#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID        4
+#define FT_SUBGLYPH_FLAG_SCALE                   8
+#define FT_SUBGLYPH_FLAG_XY_SCALE             0x40
+#define FT_SUBGLYPH_FLAG_2X2                  0x80
+#define FT_SUBGLYPH_FLAG_USE_MY_METRICS      0x200
+
+
+  enum
+  {
+    ft_glyph_own_bitmap = 1
+  };
+
+
+  struct  FT_SubGlyph_
+  {
+    FT_Int     index;
+    FT_UShort  flags;
+    FT_Int     arg1;
+    FT_Int     arg2;
+    FT_Matrix  transform;
+  };
+
+
+  typedef struct  FT_GlyphLoad_
+  {
+    FT_Outline    outline;       /* outline             */
+    FT_UInt       num_subglyphs; /* number of subglyphs */
+    FT_SubGlyph*  subglyphs;     /* subglyphs           */
+    FT_Vector*    extra_points;  /* extra points table  */
+
+  } FT_GlyphLoad;
+
+
+  struct  FT_GlyphLoader_
+  {
+    FT_Memory     memory;
+    FT_UInt       max_points;
+    FT_UInt       max_contours;
+    FT_UInt       max_subglyphs;
+    FT_Bool       use_extra;
+
+    FT_GlyphLoad  base;
+    FT_GlyphLoad  current;
+
+    void*         other;            /* for possible future extension? */
+
+  };
+
+
+  FT_BASE( FT_Error )
+  FT_GlyphLoader_New( FT_Memory         memory,
+                      FT_GlyphLoader*  *aloader );
+
+  FT_BASE( FT_Error )
+  FT_GlyphLoader_Create_Extra( FT_GlyphLoader*  loader );
+
+  FT_BASE( void )
+  FT_GlyphLoader_Done( FT_GlyphLoader*  loader );
+
+  FT_BASE( void )
+  FT_GlyphLoader_Reset( FT_GlyphLoader*  loader );
+
+  FT_BASE( void )
+  FT_GlyphLoader_Rewind( FT_GlyphLoader*  loader );
+
+  FT_BASE( FT_Error )
+  FT_GlyphLoader_Check_Points( FT_GlyphLoader*  loader,
+                               FT_UInt          n_points,
+                               FT_UInt          n_contours );
+
+  FT_BASE( FT_Error )
+  FT_GlyphLoader_Check_Subglyphs( FT_GlyphLoader*  loader,
+                                  FT_UInt          n_subs );
+
+  FT_BASE( void )
+  FT_GlyphLoader_Prepare( FT_GlyphLoader*  loader );
+
+  FT_BASE( void )
+  FT_GlyphLoader_Add( FT_GlyphLoader*  loader );
+
+  FT_BASE( FT_Error )
+  FT_GlyphLoader_Copy_Points( FT_GlyphLoader*  target,
+                              FT_GlyphLoader*  source );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                        R E N D E R E R S                        ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define FT_RENDERER( x )      ((FT_Renderer)( x ))
+#define FT_GLYPH( x )         ((FT_Glyph)( x ))
+#define FT_BITMAP_GLYPH( x )  ((FT_BitmapGlyph)( x ))
+#define FT_OUTLINE_GLYPH( x ) ((FT_OutlineGlyph)( x ))
+
+
+  typedef struct  FT_RendererRec_
+  {
+    FT_ModuleRec           root;
+    FT_Renderer_Class*     clazz;
+    FT_Glyph_Format        glyph_format;
+    FT_Glyph_Class         glyph_class;
+
+    FT_Raster              raster;
+    FT_Raster_Render_Func  raster_render;
+    FTRenderer_render      render;
+
+  } FT_RendererRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                    F O N T   D R I V E R S                      ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* typecast a module into a driver easily */
+#define FT_DRIVER( x )        ((FT_Driver)(x))
+
+  /* typecast a module as a driver, and get its driver class */
+#define FT_DRIVER_CLASS( x )  FT_DRIVER( x )->clazz
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_DriverRec                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The root font driver class.  A font driver is responsible for      */
+  /*    managing and loading font files of a given format.                 */
+  /*                                                                       */
+  /*  <Fields>                                                             */
+  /*     root         :: Contains the fields of the root module class.     */
+  /*                                                                       */
+  /*     clazz        :: A pointer to the font driver's class.  Note that  */
+  /*                     this is NOT root.clazz.  `class' wasn't used      */
+  /*                     as it is a reserved word in C++.                  */
+  /*                                                                       */
+  /*     faces_list   :: The list of faces currently opened by this        */
+  /*                     driver.                                           */
+  /*                                                                       */
+  /*     extensions   :: A typeless pointer to the driver's extensions     */
+  /*                     registry, if they are supported through the       */
+  /*                     configuration macro FT_CONFIG_OPTION_EXTENSIONS.  */
+  /*                                                                       */
+  /*     glyph_loader :: The glyph loader for all faces managed by this    */
+  /*                     driver.  This object isn't defined for unscalable */
+  /*                     formats.                                          */
+  /*                                                                       */
+  typedef struct  FT_DriverRec_
+  {
+    FT_ModuleRec      root;
+    FT_Driver_Class*  clazz;
+
+    FT_ListRec        faces_list;
+    void*             extensions;
+
+    FT_GlyphLoader*   glyph_loader;
+
+  } FT_DriverRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                       L I B R A R I E S                         ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define FT_DEBUG_HOOK_TRUETYPE   0
+#define FT_DEBUG_HOOK_TYPE1      1
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    FT_LibraryRec                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The FreeType library class.  This is the root of all FreeType      */
+  /*    data.  Use FT_New_Library() to create a library object, and        */
+  /*    FT_Done_Library() to discard it and all child objects.             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    memory           :: The library's memory object.  Manages memory   */
+  /*                        allocation.                                    */
+  /*                                                                       */
+  /*    generic          :: Client data variable.  Used to extend the      */
+  /*                        Library class by higher levels and clients.    */
+  /*                                                                       */
+  /*    num_modules      :: The number of modules currently registered     */
+  /*                        within this library.  This is set to 0 for new */
+  /*                        libraries.  New modules are added through the  */
+  /*                        FT_Add_Module() API function.                  */
+  /*                                                                       */
+  /*    modules          :: A table used to store handles to the currently */
+  /*                        registered modules. Note that each font driver */
+  /*                        contains a list of its opened faces.           */
+  /*                                                                       */
+  /*    renderers        :: The list of renderers currently registered     */
+  /*                        within the library.                            */
+  /*                                                                       */
+  /*    cur_renderer     :: The current outline renderer.  This is a       */
+  /*                        shortcut used to avoid parsing the list on     */
+  /*                        each call to FT_Outline_Render().  It is a     */
+  /*                        handle to the current renderer for the         */
+  /*                        ft_glyph_format_outline format.                */
+  /*                                                                       */
+  /*    auto_hinter      :: XXX                                            */
+  /*                                                                       */
+  /*    raster_pool      :: The raster object's render pool.  This can     */
+  /*                        ideally be changed dynamically at run-time.    */
+  /*                                                                       */
+  /*    raster_pool_size :: The size of the render pool in bytes.          */
+  /*                                                                       */
+  /*    debug_hooks      :: XXX                                            */
+  /*                                                                       */
+  typedef struct  FT_LibraryRec_
+  {
+    FT_Memory          memory;           /* library's memory manager */
+
+    FT_Generic         generic;
+
+    FT_UInt            num_modules;
+    FT_Module          modules[FT_MAX_MODULES];  /* module objects  */
+
+    FT_ListRec         renderers;        /* list of renderers        */
+    FT_Renderer        cur_renderer;     /* current outline renderer */
+    FT_Module          auto_hinter;
+
+    FT_Byte*           raster_pool;      /* scan-line conversion */
+                                          /* render pool          */
+    FT_ULong           raster_pool_size; /* size of render pool in bytes */
+
+    FT_DebugHook_Func  debug_hooks[4];
+
+  } FT_LibraryRec;
+
+
+  FT_BASE( FT_Renderer )
+  FT_Lookup_Renderer( FT_Library       library,
+                      FT_Glyph_Format  format,
+                      FT_ListNode*     node );
+
+  FT_BASE( FT_Error )
+  FT_Render_Glyph_Internal( FT_Library    library,
+                            FT_GlyphSlot  slot,
+                            FT_UInt       render_mode );
+
+  typedef const char*
+  (*FT_PSName_Requester)( FT_Face   face );
+
+  typedef FT_Error
+  (*FT_Glyph_Name_Requester)( FT_Face     face,
+                              FT_UInt     glyph_index,
+                              FT_Pointer  buffer,
+                              FT_UInt     buffer_max );
+
+  typedef FT_UInt
+  (*FT_Name_Index_Requester)( FT_Face     face,
+                              FT_String*  glyph_name );
+
+
+#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Stream                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new stream object.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    filepathname :: The name of the stream (usually a file) to be      */
+  /*                    opened.                                            */
+  /*                                                                       */
+  /*    stream       :: A pointer to the stream object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_New_Stream( const char*  filepathname,
+                 FT_Stream    astream );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Stream                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Closes and destroys a stream object.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: The stream to be closed and destroyed.                   */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Done_Stream( FT_Stream  stream );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_New_Memory                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new memory object.                                       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A pointer to the new memory object.  0 in case of error.           */
+  /*                                                                       */
+  FT_EXPORT( FT_Memory )
+  FT_New_Memory( void );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Done_Memory                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards memory manager.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A handle to the memory manager.                          */
+  /*                                                                       */
+  FT_EXPORT( void )
+  FT_Done_Memory( FT_Memory  memory );
+
+#endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */
+
+
+  /* Define default raster's interface.  The default raster is located in  */
+  /* `src/base/ftraster.c'.                                                */
+  /*                                                                       */
+  /* Client applications can register new rasters through the              */
+  /* FT_Set_Raster() API.                                                  */
+
+#ifndef FT_NO_DEFAULT_RASTER
+  FT_EXPORT_VAR( FT_Raster_Funcs )  ft_default_raster;
+#endif
+
+
+FT_END_HEADER
+
+#endif /* __FTOBJS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/ftstream.h b/libraries/freetype-2.0.5/include/freetype/internal/ftstream.h
new file mode 100644 (file)
index 0000000..df9c4e3
--- /dev/null
@@ -0,0 +1,436 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftstream.h                                                             */
+/*                                                                         */
+/*    Stream handling(specification).                                      */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTSTREAM_H__
+#define __FTSTREAM_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+  /* format of an 8-bit frame_op value = [ xxxxx | e | s ] */
+  /* s is set to 1 if the value is signed,                 */
+  /* e is set to 1 if the value is little-endian           */
+  /* xxxxx is a command                                    */
+
+#define FT_FRAME_OP_SHIFT         2
+#define FT_FRAME_OP_SIGNED        1
+#define FT_FRAME_OP_LITTLE        2
+#define FT_FRAME_OP_COMMAND( x )  ( x >> FT_FRAME_OP_SHIFT )
+
+#define FT_MAKE_FRAME_OP( command, little, sign ) \
+          ( ( command << FT_FRAME_OP_SHIFT ) | ( little << 1 ) | sign )
+
+#define FT_FRAME_OP_END   0
+#define FT_FRAME_OP_START 1  /* start a new frame     */
+#define FT_FRAME_OP_BYTE  2  /* read 1-byte value     */
+#define FT_FRAME_OP_SHORT 3  /* read 2-byte value     */
+#define FT_FRAME_OP_LONG  4  /* read 4-byte value     */
+#define FT_FRAME_OP_OFF3  5  /* read 3-byte value     */
+#define FT_FRAME_OP_BYTES 6  /* read a bytes sequence */
+
+
+  typedef enum  FT_Frame_Op_
+  {
+    ft_frame_end       = 0,
+    ft_frame_start     = FT_MAKE_FRAME_OP( FT_FRAME_OP_START, 0, 0 ),
+
+    ft_frame_byte      = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE,  0, 0 ),
+    ft_frame_schar     = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE,  0, 1 ),
+
+    ft_frame_ushort_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 0 ),
+    ft_frame_short_be  = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 1 ),
+    ft_frame_ushort_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 0 ),
+    ft_frame_short_le  = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 1 ),
+
+    ft_frame_ulong_be  = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 0 ),
+    ft_frame_long_be   = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 1 ),
+    ft_frame_ulong_le  = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 0 ),
+    ft_frame_long_le   = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 1 ),
+
+    ft_frame_uoff3_be  = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 0 ),
+    ft_frame_off3_be   = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 1 ),
+    ft_frame_uoff3_le  = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 0 ),
+    ft_frame_off3_le   = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 1 ),
+
+    ft_frame_bytes     = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 0 ),
+    ft_frame_skip      = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 1 )
+
+  } FT_Frame_Op;
+
+
+  typedef struct  FT_Frame_Field_
+  {
+    FT_Byte      value;
+    FT_Byte      size;
+    FT_UShort    offset;
+
+  } FT_Frame_Field;
+
+
+  /* Construct an FT_Frame_Field out of a structure type and a field name. */
+  /* The structure type must be set in the FT_STRUCTURE macro before       */
+  /* calling the FT_FRAME_START() macro.                                   */
+#define FT_FIELD_SIZE( f ) \
+          (FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f )
+
+#define FT_FIELD_SIZE_DELTA( f ) \
+          (FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f[0] )
+
+#define FT_FIELD_OFFSET( f ) \
+          (FT_UShort)( offsetof( FT_STRUCTURE, f ) )
+
+#define FT_FRAME_FIELD( frame_op, field ) \
+          {                               \
+            frame_op,                     \
+            FT_FIELD_SIZE( field ),       \
+            FT_FIELD_OFFSET( field )      \
+          }
+
+#define FT_MAKE_EMPTY_FIELD( frame_op )  { frame_op, 0, 0 }
+
+#define FT_FRAME_START( size )   { ft_frame_start, 0, size }
+#define FT_FRAME_END             { ft_frame_end, 0, 0 }
+
+#define FT_FRAME_LONG( f )       FT_FRAME_FIELD( ft_frame_long_be, f )
+#define FT_FRAME_ULONG( f )      FT_FRAME_FIELD( ft_frame_ulong_be, f )
+#define FT_FRAME_SHORT( f )      FT_FRAME_FIELD( ft_frame_short_be, f )
+#define FT_FRAME_USHORT( f )     FT_FRAME_FIELD( ft_frame_ushort_be, f )
+#define FT_FRAME_BYTE( f )       FT_FRAME_FIELD( ft_frame_byte, f )
+#define FT_FRAME_CHAR( f )       FT_FRAME_FIELD( ft_frame_schar, f )
+
+#define FT_FRAME_LONG_LE( f )    FT_FRAME_FIELD( ft_frame_long_le, f )
+#define FT_FRAME_ULONG_LE( f )   FT_FRAME_FIELD( ft_frame_ulong_le, f )
+#define FT_FRAME_SHORT_LE( f )   FT_FRAME_FIELD( ft_frame_short_le, f )
+#define FT_FRAME_USHORT_LE( f )  FT_FRAME_FIELD( ft_frame_ushort_le, f )
+
+#define FT_FRAME_SKIP_LONG       { ft_frame_long_be, 0, 0 }
+#define FT_FRAME_SKIP_SHORT      { ft_frame_short_be, 0, 0 }
+#define FT_FRAME_SKIP_BYTE       { ft_frame_byte, 0, 0 }
+
+#define FT_FRAME_BYTES( field, count ) \
+          {                            \
+            ft_frame_bytes,            \
+            count,                     \
+            FT_FIELD_OFFSET( field )   \
+          }
+
+#define FT_FRAME_SKIP_BYTES( count )  { ft_frame_skip, count, 0 }
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* integer extraction macros -- the `buffer' parameter must ALWAYS be of */
+  /* type `char*' or equivalent (1-byte elements).                         */
+  /*                                                                       */
+
+#define FT_GET_SHORT_BE( p )                                   \
+          ((FT_Int16)( ( (FT_Int16)(FT_Char)(p)[0] <<  8 ) |   \
+                         (FT_Int16)(FT_Byte)(p)[1]         ) )
+
+#define FT_GET_USHORT_BE( p )                                   \
+          ((FT_Int16)( ( (FT_UInt16)(FT_Byte)(p)[0] <<  8 ) |   \
+                         (FT_UInt16)(FT_Byte)(p)[1]         ) )
+
+#define FT_GET_OFF3_BE( p )                                      \
+          ( (FT_Int32) ( ( (FT_Int32)(FT_Char)(p)[0] << 16 ) |   \
+                         ( (FT_Int32)(FT_Byte)(p)[1] <<  8 ) |   \
+                           (FT_Int32)(FT_Byte)(p)[2]         ) )
+
+#define FT_GET_UOFF3_BE( p )                                      \
+          ( (FT_Int32) ( ( (FT_UInt32)(FT_Byte)(p)[0] << 16 ) |   \
+                         ( (FT_UInt32)(FT_Byte)(p)[1] <<  8 ) |   \
+                           (FT_UInt32)(FT_Byte)(p)[2]         ) )
+
+#define FT_GET_LONG_BE( p )                                      \
+          ( (FT_Int32) ( ( (FT_Int32)(FT_Char)(p)[0] << 24 ) |   \
+                         ( (FT_Int32)(FT_Byte)(p)[1] << 16 ) |   \
+                         ( (FT_Int32)(FT_Byte)(p)[2] <<  8 ) |   \
+                           (FT_Int32)(FT_Byte)(p)[3]         ) )
+
+#define FT_GET_ULONG_BE( p )                                      \
+          ( (FT_Int32) ( ( (FT_UInt32)(FT_Byte)(p)[0] << 24 ) |   \
+                         ( (FT_UInt32)(FT_Byte)(p)[1] << 16 ) |   \
+                         ( (FT_UInt32)(FT_Byte)(p)[2] <<  8 ) |   \
+                           (FT_UInt32)(FT_Byte)(p)[3]         ) )
+
+#define FT_GET_SHORT_LE( p )                                   \
+          ((FT_Int16)( ( (FT_Int16)(FT_Char)(p)[1] <<  8 ) |   \
+                         (FT_Int16)(FT_Byte)(p)[0]         ) )
+
+#define FT_GET_USHORT_LE( p )                                   \
+          ((FT_Int16)( ( (FT_UInt16)(FT_Byte)(p)[1] <<  8 ) |   \
+                         (FT_UInt16)(FT_Byte)(p)[0]         ) )
+
+#define FT_GET_OFF3_LE( p )                                      \
+          ( (FT_Int32) ( ( (FT_Int32)(FT_Char)(p)[2] << 16 ) |   \
+                         ( (FT_Int32)(FT_Byte)(p)[1] <<  8 ) |   \
+                           (FT_Int32)(FT_Byte)(p)[0]         ) )
+
+#define FT_GET_UOFF3_LE( p )                                      \
+          ( (FT_Int32) ( ( (FT_UInt32)(FT_Byte)(p)[2] << 16 ) |   \
+                         ( (FT_UInt32)(FT_Byte)(p)[1] <<  8 ) |   \
+                           (FT_UInt32)(FT_Byte)(p)[0]         ) )
+
+#define FT_GET_LONG_LE( p )                                      \
+          ( (FT_Int32) ( ( (FT_Int32)(FT_Char)(p)[3] << 24 ) |   \
+                         ( (FT_Int32)(FT_Byte)(p)[2] << 16 ) |   \
+                         ( (FT_Int32)(FT_Byte)(p)[1] <<  8 ) |   \
+                           (FT_Int32)(FT_Byte)(p)[0]         ) )
+
+#define FT_GET_ULONG_LE( p )                                      \
+          ( (FT_Int32) ( ( (FT_UInt32)(FT_Byte)(p)[3] << 24 ) |   \
+                         ( (FT_UInt32)(FT_Byte)(p)[2] << 16 ) |   \
+                         ( (FT_UInt32)(FT_Byte)(p)[1] <<  8 ) |   \
+                           (FT_UInt32)(FT_Byte)(p)[0]         ) )
+
+
+#define NEXT_Char( buffer )          \
+          ( (signed char)*buffer++ )
+
+#define NEXT_Byte( buffer )            \
+          ( (unsigned char)*buffer++ )
+
+#define NEXT_Short( buffer )                                        \
+          ( (short)( buffer += 2, FT_GET_SHORT_BE( buffer - 2 ) ) )
+
+#define NEXT_UShort( buffer )                                                 \
+          ( (unsigned short)( buffer += 2, FT_GET_USHORT_BE( buffer - 2 ) ) )
+
+#define NEXT_Offset( buffer )                                     \
+          ( (long)( buffer += 3, FT_GET_OFF3_BE( buffer - 3 ) ) )
+
+#define NEXT_UOffset( buffer )                                              \
+          ( (unsigned long)( buffer += 3, FT_GET_UOFF3_BE( buffer - 3 ) ) )
+
+#define NEXT_Long( buffer )                                       \
+          ( (long)( buffer += 4, FT_GET_LONG_BE( buffer - 4 ) ) )
+
+#define NEXT_ULong( buffer )                                                \
+          ( (unsigned long)( buffer += 4, FT_GET_ULONG_BE( buffer - 4 ) ) )
+
+
+#define NEXT_ShortLE( buffer )                                      \
+          ( (short)( buffer += 2, FT_GET_SHORT_LE( buffer - 2 ) ) )
+
+#define NEXT_UShortLE( buffer )                                               \
+          ( (unsigned short)( buffer += 2, FT_GET_USHORT_LE( buffer - 2 ) ) )
+
+#define NEXT_OffsetLE( buffer )                                   \
+          ( (long)( buffer += 3, FT_GET_OFF3_LE( buffer - 3 ) ) )
+
+#define NEXT_UOffsetLE( buffer )                                            \
+          ( (unsigned long)( buffer += 3, FT_GET_UOFF3_LE( buffer - 3 ) ) )
+
+
+#define NEXT_LongLE( buffer )                                     \
+          ( (long)( buffer += 4, FT_GET_LONG_LE( buffer - 4 ) ) )
+
+#define NEXT_ULongLE( buffer )                                              \
+          ( (unsigned long)( buffer += 4, FT_GET_ULONG_LE( buffer - 4 ) ) )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Each GET_xxxx() macro uses an implicit `stream' variable.             */
+  /*                                                                       */
+#define FT_GET_MACRO( func, type )        ( (type)func( stream ) )
+
+#define GET_Char()      FT_GET_MACRO( FT_Get_Char, FT_Char )
+#define GET_Byte()      FT_GET_MACRO( FT_Get_Char, FT_Byte )
+#define GET_Short()     FT_GET_MACRO( FT_Get_Short, FT_Short )
+#define GET_UShort()    FT_GET_MACRO( FT_Get_Short, FT_UShort )
+#define GET_Offset()    FT_GET_MACRO( FT_Get_Offset, FT_Long )
+#define GET_UOffset()   FT_GET_MACRO( FT_Get_Offset, FT_ULong )
+#define GET_Long()      FT_GET_MACRO( FT_Get_Long, FT_Long )
+#define GET_ULong()     FT_GET_MACRO( FT_Get_Long, FT_ULong )
+#define GET_Tag4()      FT_GET_MACRO( FT_Get_Long, FT_ULong )
+
+#define GET_ShortLE()   FT_GET_MACRO( FT_Get_ShortLE, FT_Short )
+#define GET_UShortLE()  FT_GET_MACRO( FT_Get_ShortLE, FT_UShort )
+#define GET_LongLE()    FT_GET_MACRO( FT_Get_LongLE, FT_Short )
+#define GET_ULongLE()   FT_GET_MACRO( FT_Get_LongLE, FT_Short )
+
+#define FT_READ_MACRO( func, type, var )        \
+          ( var = (type)func( stream, &error ), \
+            error != FT_Err_Ok )
+
+#define READ_Byte( var )      FT_READ_MACRO( FT_Read_Char, FT_Byte, var )
+#define READ_Char( var )      FT_READ_MACRO( FT_Read_Char, FT_Char, var )
+#define READ_Short( var )     FT_READ_MACRO( FT_Read_Short, FT_Short, var )
+#define READ_UShort( var )    FT_READ_MACRO( FT_Read_Short, FT_UShort, var )
+#define READ_Offset( var )    FT_READ_MACRO( FT_Read_Offset, FT_Long, var )
+#define READ_UOffset( var )   FT_READ_MACRO( FT_Read_Offset, FT_ULong, var )
+#define READ_Long( var )      FT_READ_MACRO( FT_Read_Long, FT_Long, var )
+#define READ_ULong( var )     FT_READ_MACRO( FT_Read_Long, FT_ULong, var )
+
+#define READ_ShortLE( var )   FT_READ_MACRO( FT_Read_ShortLE, FT_Short, var )
+#define READ_UShortLE( var )  FT_READ_MACRO( FT_Read_ShortLE, FT_UShort, var )
+#define READ_LongLE( var )    FT_READ_MACRO( FT_Read_LongLE, FT_Long, var )
+#define READ_ULongLE( var )   FT_READ_MACRO( FT_Read_LongLE, FT_ULong, var )
+
+
+  FT_BASE( void )
+  FT_New_Memory_Stream( FT_Library  library,
+                        FT_Byte*    base,
+                        FT_ULong    size,
+                        FT_Stream   stream );
+
+  FT_BASE( FT_Error )
+  FT_Seek_Stream( FT_Stream  stream,
+                  FT_ULong   pos );
+
+  FT_BASE( FT_Error )
+  FT_Skip_Stream( FT_Stream  stream,
+                  FT_Long    distance );
+
+  FT_BASE( FT_Long )
+  FT_Stream_Pos( FT_Stream  stream );
+
+
+  FT_BASE( FT_Error )
+  FT_Read_Stream( FT_Stream  stream,
+                  FT_Byte*   buffer,
+                  FT_ULong   count );
+
+  FT_BASE( FT_Error )
+  FT_Read_Stream_At( FT_Stream  stream,
+                     FT_ULong   pos,
+                     FT_Byte*   buffer,
+                     FT_ULong   count );
+
+  FT_BASE( FT_Error )
+  FT_Access_Frame( FT_Stream  stream,
+                   FT_ULong   count );
+
+  FT_BASE( void )
+  FT_Forget_Frame( FT_Stream  stream );
+
+  FT_BASE( FT_Error )
+  FT_Extract_Frame( FT_Stream  stream,
+                    FT_ULong   count,
+                    FT_Byte**  pbytes );
+
+  FT_BASE( void )
+  FT_Release_Frame( FT_Stream  stream,
+                    FT_Byte**  pbytes );
+
+  FT_BASE( FT_Char )
+  FT_Get_Char( FT_Stream  stream );
+
+  FT_BASE( FT_Short )
+  FT_Get_Short( FT_Stream  stream );
+
+  FT_BASE( FT_Long )
+  FT_Get_Offset( FT_Stream  stream );
+
+  FT_BASE( FT_Long )
+  FT_Get_Long( FT_Stream  stream );
+
+  FT_BASE( FT_Short )
+  FT_Get_ShortLE( FT_Stream  stream );
+
+  FT_BASE( FT_Long )
+  FT_Get_LongLE( FT_Stream  stream );
+
+
+  FT_BASE( FT_Char )
+  FT_Read_Char( FT_Stream  stream,
+                FT_Error*  error );
+
+  FT_BASE( FT_Short )
+  FT_Read_Short( FT_Stream  stream,
+                 FT_Error*  error );
+
+  FT_BASE( FT_Long )
+  FT_Read_Offset( FT_Stream  stream,
+                  FT_Error*  error );
+
+  FT_BASE( FT_Long )
+  FT_Read_Long( FT_Stream  stream,
+                FT_Error*  error );
+
+  FT_BASE( FT_Short )
+  FT_Read_ShortLE( FT_Stream  stream,
+                   FT_Error*  error );
+
+  FT_BASE( FT_Long )
+  FT_Read_LongLE( FT_Stream  stream,
+                  FT_Error*  error );
+
+  FT_BASE( FT_Error )
+  FT_Read_Fields( FT_Stream              stream,
+                  const FT_Frame_Field*  fields,
+                  void*                  structure );
+
+
+#define USE_Stream( resource, stream )                       \
+          FT_SET_ERROR( FT_Open_Stream( resource, stream ) )
+
+#define DONE_Stream( stream )      \
+          FT_Done_Stream( stream )
+
+
+#define ACCESS_Frame( size )                              \
+          FT_SET_ERROR( FT_Access_Frame( stream, size ) )
+
+#define FORGET_Frame()              \
+          FT_Forget_Frame( stream )
+
+#define EXTRACT_Frame( size, bytes )                              \
+          FT_SET_ERROR( FT_Extract_Frame( stream, size,           \
+                                          (FT_Byte**)&(bytes) ) )
+
+#define RELEASE_Frame( bytes )                            \
+          FT_Release_Frame( stream, (FT_Byte**)&(bytes) )
+
+#define FILE_Seek( position )                                \
+          FT_SET_ERROR( FT_Seek_Stream( stream, position ) )
+
+#define FILE_Skip( distance )                                \
+          FT_SET_ERROR( FT_Skip_Stream( stream, distance ) )
+
+#define FILE_Pos()                \
+          FT_Stream_Pos( stream )
+
+#define FILE_Read( buffer, count )                        \
+          FT_SET_ERROR( FT_Read_Stream( stream,           \
+                                        (FT_Byte*)buffer, \
+                                        count ) )
+
+#define FILE_Read_At( position, buffer, count )              \
+          FT_SET_ERROR( FT_Read_Stream_At( stream,           \
+                                           position,         \
+                                           (FT_Byte*)buffer, \
+                                           count ) )
+
+#define READ_Fields( fields, object )  \
+        ( ( error = FT_Read_Fields( stream, fields, object ) ) != FT_Err_Ok )
+
+
+FT_END_HEADER
+
+#endif /* __FTSTREAM_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/internal.h b/libraries/freetype-2.0.5/include/freetype/internal/internal.h
new file mode 100644 (file)
index 0000000..c2dea4f
--- /dev/null
@@ -0,0 +1,49 @@
+/***************************************************************************/
+/*                                                                         */
+/*  internal.h                                                             */
+/*                                                                         */
+/*    Internal header files (specification only).                          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is automatically included by `ft2build.h'.                  */
+  /* Do not include it manually!                                           */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define FT_INTERNAL_OBJECTS_H           <freetype/internal/ftobjs.h>
+#define FT_INTERNAL_STREAM_H            <freetype/internal/ftstream.h>
+#define FT_INTERNAL_MEMORY_H            <freetype/internal/ftmemory.h>
+#define FT_INTERNAL_EXTENSION_H         <freetype/internal/ftextend.h>
+#define FT_INTERNAL_DEBUG_H             <freetype/internal/ftdebug.h>
+#define FT_INTERNAL_CALC_H              <freetype/internal/ftcalc.h>
+#define FT_INTERNAL_DRIVER_H            <freetype/internal/ftdriver.h>
+#define FT_INTERNAL_EXTEND_H            <freetype/internal/ftextend.h>
+
+#define FT_INTERNAL_SFNT_H              <freetype/internal/sfnt.h>
+
+#define FT_INTERNAL_TRUETYPE_TYPES_H    <freetype/internal/tttypes.h>
+#define FT_INTERNAL_TYPE1_TYPES_H       <freetype/internal/t1types.h>
+#define FT_INTERNAL_CFF_TYPES_H         <freetype/internal/cfftypes.h>
+#define FT_INTERNAL_FNT_TYPES_H         <freetype/internal/fnttypes.h>
+
+#define FT_INTERNAL_POSTSCRIPT_NAMES_H  <freetype/internal/psnames.h>
+#define FT_INTERNAL_POSTSCRIPT_AUX_H    <freetype/internal/psaux.h>
+
+#define FT_INTERNAL_AUTOHINT_H          <freetype/internal/autohint.h>
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/pcftypes.h b/libraries/freetype-2.0.5/include/freetype/internal/pcftypes.h
new file mode 100644 (file)
index 0000000..2ad4ace
--- /dev/null
@@ -0,0 +1,54 @@
+/*  pcftypes.h
+
+  FreeType font driver for pcf fonts
+
+  Copyright (C) 2000-2001 by
+  Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef __PCFTYPES_H__
+#define __PCFTYPES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  typedef struct  PCF_Public_FaceRec_
+  {
+    FT_FaceRec  root;
+
+    char*       charset_encoding;
+    char*       charset_registry;
+
+  } PCF_Public_FaceRec, *PCF_Public_Face;
+
+
+FT_END_HEADER
+
+#endif  /* __PCFTYPES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/psaux.h b/libraries/freetype-2.0.5/include/freetype/internal/psaux.h
new file mode 100644 (file)
index 0000000..1911829
--- /dev/null
@@ -0,0 +1,666 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psaux.h                                                                */
+/*                                                                         */
+/*    Auxiliary functions and data structures related to PostScript fonts  */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __PSAUX_H__
+#define __PSAUX_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                             T1_TABLE                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  typedef struct PS_Table_  PS_Table;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    PS_Table_Funcs                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A set of function pointers to manage PS_Table objects.             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    table_init    :: Used to initialize a table.                       */
+  /*                                                                       */
+  /*    table_done    :: Finalizes resp. destroy a given table.            */
+  /*                                                                       */
+  /*    table_add     :: Adds a new object to a table.                     */
+  /*                                                                       */
+  /*    table_release :: Releases table data, then finalizes it.           */
+  /*                                                                       */
+  typedef struct  PS_Table_Funcs_
+  {
+    FT_Error
+    (*init)( PS_Table*  table,
+             FT_Int     count,
+             FT_Memory  memory );
+
+    void
+    (*done)( PS_Table*  table );
+
+    FT_Error
+    (*add)( PS_Table*  table,
+            FT_Int     index,
+            void*      object,
+            FT_Int     length );
+
+    void
+    (*release)( PS_Table*  table );
+
+  } PS_Table_Funcs;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    PS_Table                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A PS_Table is a simple object used to store an array of objects in */
+  /*    a single memory block.                                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    block     :: The address in memory of the growheap's block.  This  */
+  /*                 can change between two object adds, due to            */
+  /*                 reallocation.                                         */
+  /*                                                                       */
+  /*    cursor    :: The current top of the grow heap within its block.    */
+  /*                                                                       */
+  /*    capacity  :: The current size of the heap block.  Increments by    */
+  /*                 1kByte chunks.                                        */
+  /*                                                                       */
+  /*    max_elems :: The maximum number of elements in table.              */
+  /*                                                                       */
+  /*    num_elems :: The current number of elements in table.              */
+  /*                                                                       */
+  /*    elements  :: A table of element addresses within the block.        */
+  /*                                                                       */
+  /*    lengths   :: A table of element sizes within the block.            */
+  /*                                                                       */
+  /*    memory    :: The object used for memory operations                 */
+  /*                 (alloc/realloc).                                      */
+  /*                                                                       */
+  /*    funcs     :: A table of method pointers for this object.           */
+  /*                                                                       */
+  struct  PS_Table_
+  {
+    FT_Byte*        block;          /* current memory block           */
+    FT_Offset       cursor;         /* current cursor in memory block */
+    FT_Offset       capacity;       /* current size of memory block   */
+    FT_Long         init;
+
+    FT_Int          max_elems;
+    FT_Int          num_elems;
+    FT_Byte**       elements;       /* addresses of table elements */
+    FT_Int*         lengths;        /* lengths of table elements   */
+
+    FT_Memory       memory;
+    PS_Table_Funcs  funcs;
+
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                       T1 FIELDS & TOKENS                      *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  typedef struct T1_Parser_  T1_Parser;
+
+  /* simple enumeration type used to identify token types */
+  typedef enum  T1_Token_Type_
+  {
+    t1_token_none = 0,
+    t1_token_any,
+    t1_token_string,
+    t1_token_array,
+
+    /* do not remove */
+    t1_token_max
+
+  } T1_Token_Type;
+
+
+  /* a simple structure used to identify tokens */
+  typedef struct  T1_Token_
+  {
+    FT_Byte*       start;   /* first character of token in input stream */
+    FT_Byte*       limit;   /* first character after the token          */
+    T1_Token_Type  type;    /* type of token                            */
+
+  } T1_Token;
+
+
+  /* enumeration type used to identify object fields */
+  typedef enum  T1_Field_Type_
+  {
+    t1_field_none = 0,
+    t1_field_bool,
+    t1_field_integer,
+    t1_field_fixed,
+    t1_field_string,
+    t1_field_integer_array,
+    t1_field_fixed_array,
+    t1_field_callback,
+
+    /* do not remove */
+    t1_field_max
+
+  } T1_Field_Type;
+
+  typedef enum  T1_Field_Location_
+  {
+    t1_field_cid_info,
+    t1_field_font_dict,
+    t1_field_font_info,
+    t1_field_private,
+
+    /* do not remove */
+    t1_field_location_max
+
+  } T1_Field_Location;
+
+
+  typedef void
+  (*T1_Field_Parser)( FT_Face     face,
+                      FT_Pointer  parser );
+
+
+  /* structure type used to model object fields */
+  typedef struct  T1_Field_
+  {
+    const char*        ident;        /* field identifier               */
+    T1_Field_Location  location;
+    T1_Field_Type      type;         /* type of field                  */
+    T1_Field_Parser    reader;
+    FT_UInt            offset;       /* offset of field in object      */
+    FT_Byte            size;         /* size of field in bytes         */
+    FT_UInt            array_max;    /* maximal number of elements for */
+                                     /* array                          */
+    FT_UInt            count_offset; /* offset of element count for    */
+                                     /* arrays                         */
+  } T1_Field;
+
+
+#define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname ) \
+          {                                          \
+            _ident, T1CODE, _type,                   \
+            0,                                       \
+            FT_FIELD_OFFSET( _fname ),               \
+            FT_FIELD_SIZE( _fname ),                 \
+            0, 0                                     \
+          },
+
+#define T1_NEW_CALLBACK_FIELD( _ident, _reader ) \
+          {                                      \
+            _ident, T1CODE, t1_field_callback,   \
+            (T1_Field_Parser)_reader,            \
+            0, 0,                                \
+            0, 0                                 \
+          },
+
+#define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max ) \
+          {                                               \
+            _ident, T1CODE, _type,                        \
+            0,                                            \
+            FT_FIELD_OFFSET( _fname ),                    \
+            FT_FIELD_SIZE_DELTA( _fname ),                \
+            _max,                                         \
+            FT_FIELD_OFFSET( num_ ## _fname )             \
+          },
+
+#define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max ) \
+          {                                                \
+            _ident, T1CODE, _type,                         \
+            0,                                             \
+            FT_FIELD_OFFSET( _fname ),                     \
+            FT_FIELD_SIZE_DELTA( _fname ),                 \
+            _max, 0                                        \
+          },
+
+
+#define T1_FIELD_BOOL( _ident, _fname )                           \
+          T1_NEW_SIMPLE_FIELD( _ident, t1_field_bool, _fname )
+
+#define T1_FIELD_NUM( _ident, _fname )                            \
+          T1_NEW_SIMPLE_FIELD( _ident, t1_field_integer, _fname )
+
+#define T1_FIELD_FIXED( _ident, _fname )                          \
+          T1_NEW_SIMPLE_FIELD( _ident, t1_field_fixed, _fname )
+
+#define T1_FIELD_STRING( _ident, _fname )                         \
+          T1_NEW_SIMPLE_FIELD( _ident, t1_field_string, _fname )
+
+#define T1_FIELD_NUM_TABLE( _ident, _fname, _fmax )               \
+          T1_NEW_TABLE_FIELD( _ident, t1_field_integer_array,     \
+                               _fname, _fmax )
+
+#define T1_FIELD_FIXED_TABLE( _ident, _fname, _fmax )             \
+          T1_NEW_TABLE_FIELD( _ident, t1_field_fixed_array,       \
+                               _fname, _fmax )
+
+#define T1_FIELD_NUM_TABLE2( _ident, _fname, _fmax )              \
+          T1_NEW_TABLE_FIELD2( _ident, t1_field_integer_array,    \
+                                _fname, _fmax )
+
+#define T1_FIELD_FIXED_TABLE2( _ident, _fname, _fmax )            \
+          T1_NEW_TABLE_FIELD2( _ident, t1_field_fixed_array,      \
+                                _fname, _fmax )
+
+#define T1_FIELD_CALLBACK( _ident, _name )                        \
+          T1_NEW_CALLBACK_FIELD( _ident, _name )
+
+
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                            T1 PARSER                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  typedef struct  T1_Parser_Funcs_
+  {
+    void
+    (*init)( T1_Parser*  parser,
+             FT_Byte*    base,
+             FT_Byte*    limit,
+             FT_Memory   memory );
+
+    void
+    (*done)( T1_Parser*  parser );
+
+    void
+    (*skip_spaces)( T1_Parser*  parser );
+    void
+    (*skip_alpha)( T1_Parser*  parser );
+
+    FT_Long
+    (*to_int)( T1_Parser*  parser );
+    FT_Fixed
+    (*to_fixed)( T1_Parser*  parser,
+                 FT_Int      power_ten );
+    FT_Int
+    (*to_coord_array)( T1_Parser*  parser,
+                       FT_Int      max_coords,
+                       FT_Short*   coords );
+    FT_Int
+    (*to_fixed_array)( T1_Parser*  parser,
+                       FT_Int      max_values,
+                       FT_Fixed*   values,
+                       FT_Int      power_ten );
+
+    void
+    (*to_token)( T1_Parser*  parser,
+                 T1_Token*   token );
+    void
+    (*to_token_array)( T1_Parser*  parser,
+                       T1_Token*   tokens,
+                       FT_UInt     max_tokens,
+                       FT_Int*     pnum_tokens );
+
+    FT_Error
+    (*load_field)( T1_Parser*       parser,
+                   const T1_Field*  field,
+                   void**           objects,
+                   FT_UInt          max_objects,
+                   FT_ULong*        pflags );
+
+    FT_Error
+    (*load_field_table)( T1_Parser*       parser,
+                         const T1_Field*  field,
+                         void**           objects,
+                         FT_UInt          max_objects,
+                         FT_ULong*        pflags );
+
+  } T1_Parser_Funcs;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_Parser                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A T1_Parser is an object used to parse a Type 1 font very quickly. */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    cursor :: The current position in the text.                        */
+  /*                                                                       */
+  /*    base   :: Start of the processed text.                             */
+  /*                                                                       */
+  /*    limit  :: End of the processed text.                               */
+  /*                                                                       */
+  /*    error  :: The last error returned.                                 */
+  /*                                                                       */
+  /*    memory :: The object used for memory operations (alloc/realloc).   */
+  /*                                                                       */
+  /*    funcs  :: A table of functions for the parser.                     */
+  /*                                                                       */
+  struct T1_Parser_
+  {
+    FT_Byte*         cursor;
+    FT_Byte*         base;
+    FT_Byte*         limit;
+    FT_Error         error;
+    FT_Memory        memory;
+
+    T1_Parser_Funcs  funcs;
+  };
+
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                         T1 BUILDER                            *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  typedef struct T1_Builder_  T1_Builder;
+
+
+  typedef FT_Error
+  (*T1_Builder_Check_Points_Func)( T1_Builder*  builder,
+                                  FT_Int       count );
+
+  typedef void
+  (*T1_Builder_Add_Point_Func)( T1_Builder*  builder,
+                                FT_Pos       x,
+                                FT_Pos       y,
+                                FT_Byte      flag );
+
+  typedef FT_Error
+  (*T1_Builder_Add_Point1_Func)( T1_Builder*  builder,
+                                 FT_Pos       x,
+                                 FT_Pos       y );
+
+  typedef FT_Error
+  (*T1_Builder_Add_Contour_Func)( T1_Builder*  builder );
+
+  typedef FT_Error
+  (*T1_Builder_Start_Point_Func)( T1_Builder*  builder,
+                                  FT_Pos       x,
+                                  FT_Pos       y );
+
+  typedef void
+  (*T1_Builder_Close_Contour_Func)( T1_Builder*  builder );
+
+
+  typedef struct  T1_Builder_Funcs_
+  {
+    void
+    (*init)( T1_Builder*   builder,
+             FT_Face       face,
+             FT_Size       size,
+             FT_GlyphSlot  slot );
+
+    void
+    (*done)( T1_Builder*   builder );
+
+    T1_Builder_Check_Points_Func   check_points;
+    T1_Builder_Add_Point_Func      add_point;
+    T1_Builder_Add_Point1_Func     add_point1;
+    T1_Builder_Add_Contour_Func    add_contour;
+    T1_Builder_Start_Point_Func    start_point;
+    T1_Builder_Close_Contour_Func  close_contour;
+
+  } T1_Builder_Funcs;
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Structure>                                                           */
+  /*    T1_Builder                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*     A structure used during glyph loading to store its outline.       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    memory       :: The current memory object.                         */
+  /*                                                                       */
+  /*    face         :: The current face object.                           */
+  /*                                                                       */
+  /*    glyph        :: The current glyph slot.                            */
+  /*                                                                       */
+  /*    loader       :: XXX                                                */
+  /*                                                                       */
+  /*    base         :: The base glyph outline.                            */
+  /*                                                                       */
+  /*    current      :: The current glyph outline.                         */
+  /*                                                                       */
+  /*    max_points   :: maximum points in builder outline                  */
+  /*                                                                       */
+  /*    max_contours :: Maximal number of contours in builder outline.     */
+  /*                                                                       */
+  /*    last         :: The last point position.                           */
+  /*                                                                       */
+  /*    scale_x      :: The horizontal scale (FUnits to sub-pixels).       */
+  /*                                                                       */
+  /*    scale_y      :: The vertical scale (FUnits to sub-pixels).         */
+  /*                                                                       */
+  /*    pos_x        :: The horizontal translation (if composite glyph).   */
+  /*                                                                       */
+  /*    pos_y        :: The vertical translation (if composite glyph).     */
+  /*                                                                       */
+  /*    left_bearing :: The left side bearing point.                       */
+  /*                                                                       */
+  /*    advance      :: The horizontal advance vector.                     */
+  /*                                                                       */
+  /*    bbox         :: Unused.                                            */
+  /*                                                                       */
+  /*    path_begun   :: A flag which indicates that a new path has begun.  */
+  /*                                                                       */
+  /*    load_points  :: If this flag is not set, no points are loaded.     */
+  /*                                                                       */
+  /*    no_recurse   :: Set but not used.                                  */
+  /*                                                                       */
+  /*    error        :: An error code that is only used to report memory   */
+  /*                    allocation problems.                               */
+  /*                                                                       */
+  /*    metrics_only :: A boolean indicating that we only want to compute  */
+  /*                    the metrics of a given glyph, not load all of its  */
+  /*                    points.                                            */
+  /*                                                                       */
+  /*    funcs        :: An array of function pointers for the builder.     */
+  /*                                                                       */
+  struct  T1_Builder_
+  {
+    FT_Memory         memory;
+    FT_Face           face;
+    FT_GlyphSlot      glyph;
+    FT_GlyphLoader*   loader;
+    FT_Outline*       base;
+    FT_Outline*       current;
+
+    FT_Vector         last;
+
+    FT_Fixed          scale_x;
+    FT_Fixed          scale_y;
+
+    FT_Pos            pos_x;
+    FT_Pos            pos_y;
+
+    FT_Vector         left_bearing;
+    FT_Vector         advance;
+
+    FT_BBox           bbox;          /* bounding box */
+    FT_Bool           path_begun;
+    FT_Bool           load_points;
+    FT_Bool           no_recurse;
+    FT_Bool           shift;
+
+    FT_Error          error;         /* only used for memory errors */
+    FT_Bool           metrics_only;
+
+    T1_Builder_Funcs  funcs;
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                         T1 DECODER                            *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+#if 0
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine   */
+  /* calls during glyph loading.                                           */
+  /*                                                                       */
+#define T1_MAX_SUBRS_CALLS  8
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity.  A     */
+  /* minimum of 16 is required.                                            */
+  /*                                                                       */
+#define T1_MAX_CHARSTRINGS_OPERANDS  32
+
+#endif /* 0 */
+
+
+  typedef struct  T1_Decoder_Zone_
+  {
+    FT_Byte*  cursor;
+    FT_Byte*  base;
+    FT_Byte*  limit;
+
+  } T1_Decoder_Zone;
+
+
+  typedef struct T1_Decoder_        T1_Decoder;
+  typedef struct T1_Decoder_Funcs_  T1_Decoder_Funcs;
+
+
+  typedef FT_Error
+  (*T1_Decoder_Callback)( T1_Decoder*  decoder,
+                          FT_UInt      glyph_index );
+
+
+  struct  T1_Decoder_Funcs_
+  {
+    FT_Error
+    (*init)( T1_Decoder*          decoder,
+             FT_Face              face,
+             FT_Size              size,
+             FT_GlyphSlot         slot,
+             FT_Byte**            glyph_names,
+             T1_Blend*            blend,
+             T1_Decoder_Callback  callback );
+
+    void
+    (*done)( T1_Decoder*  decoder );
+
+    FT_Error
+    (*parse_charstrings)( T1_Decoder*  decoder,
+                          FT_Byte*     base,
+                          FT_UInt      len );
+  };
+
+
+  struct  T1_Decoder_
+  {
+    T1_Builder           builder;
+
+    FT_Long              stack[T1_MAX_CHARSTRINGS_OPERANDS];
+    FT_Long*             top;
+
+    T1_Decoder_Zone      zones[T1_MAX_SUBRS_CALLS + 1];
+    T1_Decoder_Zone*     zone;
+
+    PSNames_Interface*   psnames;      /* for seac */
+    FT_UInt              num_glyphs;
+    FT_Byte**            glyph_names;
+
+    FT_Int               lenIV;        /* internal for sub routine calls */
+    FT_UInt              num_subrs;
+    FT_Byte**            subrs;
+    FT_Int*              subrs_len;    /* array of subrs length (optional) */
+
+    FT_Matrix            font_matrix;
+    FT_Vector            font_offset;
+
+    FT_Int               flex_state;
+    FT_Int               num_flex_vectors;
+    FT_Vector            flex_vectors[7];
+
+    T1_Blend*            blend;       /* for multiple master support */
+
+    T1_Decoder_Callback  parse_callback;
+    T1_Decoder_Funcs     funcs;
+  };
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                        PSAux Module Interface                 *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  typedef struct  PSAux_Interface_
+  {
+    const PS_Table_Funcs*    ps_table_funcs;
+    const T1_Parser_Funcs*   t1_parser_funcs;
+    const T1_Builder_Funcs*  t1_builder_funcs;
+    const T1_Decoder_Funcs*  t1_decoder_funcs;
+
+    void
+    (*t1_decrypt)( FT_Byte*   buffer,
+                   FT_Offset  length,
+                   FT_UShort  seed );
+
+  } PSAux_Interface;
+
+
+FT_END_HEADER
+
+#endif /* __PSAUX_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/psnames.h b/libraries/freetype-2.0.5/include/freetype/internal/psnames.h
new file mode 100644 (file)
index 0000000..71700c1
--- /dev/null
@@ -0,0 +1,232 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psnames.h                                                              */
+/*                                                                         */
+/*    High-level interface for the `PSNames' module (in charge of          */
+/*    various functions related to Postscript glyph names conversion).     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __PSNAMES_H__
+#define __PSNAMES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    PS_Unicode_Value_Func                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to return the Unicode index corresponding to a     */
+  /*    given glyph name.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph_name :: The glyph name.                                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The Unicode character index resp. the non-Unicode value 0xFFFF if  */
+  /*    the glyph name has no known Unicode meaning.                       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function is able to map several different glyph names to the  */
+  /*    same Unicode value, according to the rules defined in the Adobe    */
+  /*    Glyph List table.                                                  */
+  /*                                                                       */
+  /*    This function will not be compiled if the configuration macro      */
+  /*    FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is undefined.                    */
+  /*                                                                       */
+  typedef FT_ULong
+  (*PS_Unicode_Value_Func)( const char*  glyph_name );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    PS_Unicode_Index_Func                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to return the glyph index corresponding to a given */
+  /*    Unicode value.                                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    num_glyphs  :: The number of glyphs in the face.                   */
+  /*                                                                       */
+  /*    glyph_names :: An array of glyph name pointers.                    */
+  /*                                                                       */
+  /*    unicode     :: The Unicode value.                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The glyph index resp. 0xFFFF if no glyph corresponds to this       */
+  /*    Unicode value.                                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function is able to recognize several glyph names per Unicode */
+  /*    value, according to the Adobe Glyph List.                          */
+  /*                                                                       */
+  /*    This function will not be compiled if the configuration macro      */
+  /*    FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is undefined.                    */
+  /*                                                                       */
+  typedef FT_UInt
+  (*PS_Unicode_Index_Func)( FT_UInt       num_glyphs,
+                            const char**  glyph_names,
+                            FT_ULong      unicode );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    PS_Macintosh_Name_Func                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to return the glyph name corresponding to an Apple */
+  /*    glyph name index.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    name_index :: The index of the Mac name.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The glyph name, or 0 if the index is invalid.                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will not be compiled if the configuration macro      */
+  /*    FT_CONFIG_OPTION_POSTSCRIPT_NAMES is undefined.                    */
+  /*                                                                       */
+  typedef const char*
+  (*PS_Macintosh_Name_Func)( FT_UInt  name_index );
+
+
+  typedef const char*
+  (*PS_Adobe_Std_Strings_Func)( FT_UInt  string_index );
+
+
+  typedef struct  PS_UniMap_
+  {
+    FT_UInt  unicode;
+    FT_UInt  glyph_index;
+
+  } PS_UniMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    PS_Unicodes                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple table used to map Unicode values to glyph indices.  It is */
+  /*    built by the PS_Build_Unicodes table according to the glyphs       */
+  /*    present in a font file.                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_codes :: The number of glyphs in the font that match a given   */
+  /*                 Unicode value.                                        */
+  /*                                                                       */
+  /*    unicodes  :: An array of unicode values, sorted in increasing      */
+  /*                 order.                                                */
+  /*                                                                       */
+  /*    gindex    :: An array of glyph indices, corresponding to each      */
+  /*                 Unicode value.                                        */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Use the function PS_Lookup_Unicode() to retrieve the glyph index   */
+  /*    corresponding to a given Unicode character code.                   */
+  /*                                                                       */
+  typedef struct  PS_Unicodes_
+  {
+    FT_UInt     num_maps;
+    PS_UniMap*  maps;
+
+  } PS_Unicodes;
+
+
+  typedef FT_Error
+  (*PS_Build_Unicodes_Func)( FT_Memory     memory,
+                             FT_UInt       num_glyphs,
+                             const char**  glyph_names,
+                             PS_Unicodes*  unicodes );
+
+  typedef FT_UInt
+  (*PS_Lookup_Unicode_Func)( PS_Unicodes*  unicodes,
+                             FT_UInt       unicode );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    PSNames_Interface                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure defines the PSNames interface.                      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    unicode_value         :: A function used to convert a glyph name   */
+  /*                             into a Unicode character code.            */
+  /*                                                                       */
+  /*    build_unicodes        :: A function which builds up the Unicode    */
+  /*                             mapping table.                            */
+  /*                                                                       */
+  /*    lookup_unicode        :: A function used to return the glyph index */
+  /*                             corresponding to a given Unicode          */
+  /*                             character.                                */
+  /*                                                                       */
+  /*    macintosh_name        :: A function used to return the standard    */
+  /*                             Apple glyph Postscript name corresponding */
+  /*                             to a given string index (used by the      */
+  /*                             TrueType `post' table).                   */
+  /*                                                                       */
+  /*    adobe_std_strings     :: A function that returns a pointer to a    */
+  /*                             Adobe Standard String for a given SID.    */
+  /*                                                                       */
+  /*    adobe_std_encoding    :: A table of 256 unsigned shorts that maps  */
+  /*                             character codes in the Adobe Standard     */
+  /*                             Encoding to SIDs.                         */
+  /*                                                                       */
+  /*    adobe_expert_encoding :: A table of 256 unsigned shorts that maps  */
+  /*                             character codes in the Adobe Expert       */
+  /*                             Encoding to SIDs.                         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    `unicode_value' and `unicode_index' will be set to 0 if the        */
+  /*    configuration macro FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is           */
+  /*    undefined.                                                         */
+  /*                                                                       */
+  /*    `macintosh_name' will be set to 0 if the configuration macro       */
+  /*    FT_CONFIG_OPTION_POSTSCRIPT_NAMES is undefined.                    */
+  /*                                                                       */
+  typedef struct  PSNames_Interface_
+  {
+    PS_Unicode_Value_Func      unicode_value;
+    PS_Build_Unicodes_Func     build_unicodes;
+    PS_Lookup_Unicode_Func     lookup_unicode;
+    PS_Macintosh_Name_Func     macintosh_name;
+
+    PS_Adobe_Std_Strings_Func  adobe_std_strings;
+    const unsigned short*      adobe_std_encoding;
+    const unsigned short*      adobe_expert_encoding;
+
+  } PSNames_Interface;
+
+
+FT_END_HEADER
+
+#endif /* __PSNAMES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/sfnt.h b/libraries/freetype-2.0.5/include/freetype/internal/sfnt.h
new file mode 100644 (file)
index 0000000..bfcce5d
--- /dev/null
@@ -0,0 +1,530 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfnt.h                                                                 */
+/*                                                                         */
+/*    High-level `sfnt' driver interface (specification).                  */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __SFNT_H__
+#define __SFNT_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Init_Face_Func                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    First part of the SFNT face object initialization.  This will find */
+  /*    the face in a SFNT file or collection, and load its format tag in  */
+  /*    face->format_tag.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     :: The input stream.                                    */
+  /*                                                                       */
+  /*    face       :: A handle to the target face object.                  */
+  /*                                                                       */
+  /*    face_index :: The index of the TrueType font, if we are opening a  */
+  /*                  collection.                                          */
+  /*                                                                       */
+  /*    num_params :: The number of additional parameters.                 */
+  /*                                                                       */
+  /*    params     :: Optional additional parameters.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be at the font file's origin.               */
+  /*                                                                       */
+  /*    This function recognizes fonts embedded in a `TrueType             */
+  /*    collection'.                                                       */
+  /*                                                                       */
+  /*    Once the format tag has been validated by the font driver, it      */
+  /*    should then call the TT_Load_Face_Func() callback to read the rest */
+  /*    of the SFNT tables in the object.                                  */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Init_Face_Func)( FT_Stream      stream,
+                        TT_Face        face,
+                        FT_Int         face_index,
+                        FT_Int         num_params,
+                        FT_Parameter*  params );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Face_Func                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Second part of the SFNT face object initialization.  This will     */
+  /*    load the common SFNT tables (head, OS/2, maxp, metrics, etc.) in   */
+  /*    the face object.                                                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     :: The input stream.                                    */
+  /*                                                                       */
+  /*    face       :: A handle to the target face object.                  */
+  /*                                                                       */
+  /*    face_index :: The index of the TrueType font, if we are opening a  */
+  /*                  collection.                                          */
+  /*                                                                       */
+  /*    num_params :: The number of additional parameters.                 */
+  /*                                                                       */
+  /*    params     :: Optional additional parameters.                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function must be called after TT_Init_Face_Func().            */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Load_Face_Func)( FT_Stream      stream,
+                        TT_Face        face,
+                        FT_Int         face_index,
+                        FT_Int         num_params,
+                        FT_Parameter*  params );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Done_Face_Func                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A callback used to delete the common SFNT data from a face.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the target face object.                        */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT destroy the face object.                    */
+  /*                                                                       */
+  typedef void
+  (*TT_Done_Face_Func)( TT_Face  face );
+
+
+  typedef FT_Module_Interface
+  (*SFNT_Get_Interface_Func)( FT_Module    module,
+                              const char*  interface );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_SFNT_Header_Func                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the header of a SFNT font file.  Supports collections.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the target face object.                  */
+  /*                                                                       */
+  /*    stream     :: The input stream.                                    */
+  /*                                                                       */
+  /*    face_index :: The index of the TrueType font, if we are opening a  */
+  /*                  collection.                                          */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    sfnt       :: The SFNT header.                                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be at the font file's origin.               */
+  /*                                                                       */
+  /*    This function recognizes fonts embedded in a `TrueType             */
+  /*    collection'.                                                       */
+  /*                                                                       */
+  /*    This function checks that the header is valid by looking at the    */
+  /*    values of `search_range', `entry_selector', and `range_shift'.     */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Load_SFNT_Header_Func)( TT_Face       face,
+                               FT_Stream     stream,
+                               FT_Long       face_index,
+                               SFNT_Header*  sfnt );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Directory_Func                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the table directory into a face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face      :: A handle to the target face object.                   */
+  /*                                                                       */
+  /*    stream    :: The input stream.                                     */
+  /*                                                                       */
+  /*    sfnt      :: The SFNT header.                                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be on the first byte after the 4-byte font  */
+  /*    format tag.  This is the case just after a call to                 */
+  /*    TT_Load_Format_Tag().                                              */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Load_Directory_Func)( TT_Face       face,
+                             FT_Stream     stream,
+                             SFNT_Header*  sfnt );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Any_Func                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads any font table into client memory.                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: The face object to look for.                             */
+  /*                                                                       */
+  /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
+  /*              to access the whole font file, else set this parameter   */
+  /*              to a valid TrueType table tag that you can forge with    */
+  /*              the MAKE_TT_TAG macro.                                   */
+  /*                                                                       */
+  /*    offset :: The starting offset in the table (or the file if         */
+  /*              tag == 0).                                               */
+  /*                                                                       */
+  /*    length :: The address of the decision variable:                    */
+  /*                                                                       */
+  /*                If length == NULL:                                     */
+  /*                  Loads the whole table.  Returns an error if          */
+  /*                  `offset' == 0!                                       */
+  /*                                                                       */
+  /*                If *length == 0:                                       */
+  /*                  Exits immediately; returning the length of the given */
+  /*                  table or of the font file, depending on the value of */
+  /*                  `tag'.                                               */
+  /*                                                                       */
+  /*                If *length != 0:                                       */
+  /*                  Loads the next `length' bytes of table or font,      */
+  /*                  starting at offset `offset' (in table or font too).  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    buffer :: The address of target buffer.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    TrueType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Load_Any_Func)( TT_Face    face,
+                       FT_ULong   tag,
+                       FT_Long    offset,
+                       FT_Byte   *buffer,
+                       FT_ULong*  length );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_SBit_Image_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given glyph sbit image from the font resource.  This also  */
+  /*    returns its metrics.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: The target face object.                             */
+  /*                                                                       */
+  /*    x_ppem      :: The horizontal resolution in points per EM.         */
+  /*                                                                       */
+  /*    y_ppem      :: The vertical resolution in points per EM.           */
+  /*                                                                       */
+  /*    glyph_index :: The current glyph index.                            */
+  /*                                                                       */
+  /*    stream      :: The input stream.                                   */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    amap        :: The target pixmap.                                  */
+  /*                                                                       */
+  /*    ametrics    :: A big sbit metrics structure for the glyph image.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  Returns an error if no     */
+  /*    glyph sbit exists for the index.                                   */
+  /*                                                                       */
+  /*  <Note>                                                               */
+  /*    The `map.buffer' field is always freed before the glyph is loaded. */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Load_SBit_Image_Func)( TT_Face           face,
+                              FT_ULong          strike_index,
+                              FT_UInt           glyph_index,
+                              FT_UInt           load_flags,
+                              FT_Stream         stream,
+                              FT_Bitmap        *amap,
+                              TT_SBit_Metrics  *ametrics );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Set_SBit_Strike_Func                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Selects an sbit strike for given horizontal and vertical ppem      */
+  /*    values.                                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face          :: The target face object.                           */
+  /*                                                                       */
+  /*    x_ppem        :: The horizontal resolution in points per EM.       */
+  /*                                                                       */
+  /*    y_ppem        :: The vertical resolution in points per EM.         */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    astrike_index :: The index of the sbit strike.                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  Returns an error if no     */
+  /*    sbit strike exists for the selected ppem values.                   */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Set_SBit_Strike_Func)( TT_Face    face,
+                              FT_Int     x_ppem,
+                              FT_Int     y_ppem,
+                              FT_ULong  *astrike_index );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Get_PS_Name_Func                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Gets the PostScript glyph name of a glyph.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    index  :: The glyph index.                                         */
+  /*                                                                       */
+  /*    PSname :: The address of a string pointer.  Will be NULL in case   */
+  /*              of error, otherwise it is a pointer to the glyph name.   */
+  /*                                                                       */
+  /*              You must not modify the returned string!                 */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Get_PS_Name_Func)( TT_Face      face,
+                          FT_UInt      index,
+                          FT_String**  PSname );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Metrics_Func                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the horizontal or vertical header in a face object.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the target face object.                    */
+  /*                                                                       */
+  /*    stream   :: The input stream.                                      */
+  /*                                                                       */
+  /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Load_Metrics_Func)( TT_Face    face,
+                           FT_Stream  stream,
+                           FT_Bool    vertical );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_CharMap_Load_Func                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given TrueType character map into memory.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the parent face object.                      */
+  /*                                                                       */
+  /*    stream :: A handle to the current stream object.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    cmap   :: A pointer to a cmap object.                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The function assumes that the stream is already in use (i.e.,      */
+  /*    opened).  In case of error, all partially allocated tables are     */
+  /*    released.                                                          */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_CharMap_Load_Func)( TT_Face        face,
+                           TT_CMapTable*  cmap,
+                           FT_Stream      input );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_CharMap_Free_Func                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a character mapping table.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the parent face object.                        */
+  /*                                                                       */
+  /*    cmap :: A handle to a cmap object.                                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_CharMap_Free_Func)( TT_Face        face,
+                           TT_CMapTable*  cmap );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Table_Func                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given TrueType table.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The function will use `face->goto_table' to seek the stream to     */
+  /*    the start of the table.                                            */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Load_Table_Func)( TT_Face    face,
+                         FT_Stream  stream );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Free_Table_Func                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Frees a given TrueType table.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the target face object.                        */
+  /*                                                                       */
+  typedef void
+  (*TT_Free_Table_Func)( TT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    SFNT_Interface                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure holds pointers to the functions used to load and    */
+  /*    free the basic tables that are required in a `sfnt' font file.     */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    Check the various xxx_Func() descriptions for details.             */
+  /*                                                                       */
+  typedef struct  SFNT_Interface_
+  {
+    TT_Goto_Table_Func        goto_table;
+
+    TT_Init_Face_Func         init_face;
+    TT_Load_Face_Func         load_face;
+    TT_Done_Face_Func         done_face;
+    SFNT_Get_Interface_Func   get_interface;
+
+    TT_Load_Any_Func          load_any;
+    TT_Load_SFNT_Header_Func  load_sfnt_header;
+    TT_Load_Directory_Func    load_directory;
+
+    /* these functions are called by `load_face' but they can also  */
+    /* be called from external modules, if there is a need to do so */
+    TT_Load_Table_Func        load_header;
+    TT_Load_Metrics_Func      load_metrics;
+    TT_Load_Table_Func        load_charmaps;
+    TT_Load_Table_Func        load_max_profile;
+    TT_Load_Table_Func        load_os2;
+    TT_Load_Table_Func        load_psnames;
+
+    TT_Load_Table_Func        load_names;
+    TT_Free_Table_Func        free_names;
+
+    /* optional tables */
+    TT_Load_Table_Func        load_hdmx;
+    TT_Free_Table_Func        free_hdmx;
+
+    TT_Load_Table_Func        load_kerning;
+    TT_Load_Table_Func        load_gasp;
+    TT_Load_Table_Func        load_pclt;
+
+    /* see `ttload.h' */
+    TT_Load_Table_Func        load_bitmap_header;
+
+    /* see `ttsbit.h' */
+    TT_Set_SBit_Strike_Func   set_sbit_strike;
+    TT_Load_Table_Func        load_sbits;
+    TT_Load_SBit_Image_Func   load_sbit_image;
+    TT_Free_Table_Func        free_sbits;
+
+    /* see `ttpost.h' */
+    TT_Get_PS_Name_Func       get_psname;
+    TT_Free_Table_Func        free_psnames;
+
+    /* see `ttcmap.h' */
+    TT_CharMap_Load_Func      load_charmap;
+    TT_CharMap_Free_Func      free_charmap;
+
+  } SFNT_Interface;
+
+
+FT_END_HEADER
+
+#endif /* __SFNT_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/t1types.h b/libraries/freetype-2.0.5/include/freetype/internal/t1types.h
new file mode 100644 (file)
index 0000000..d40e2c4
--- /dev/null
@@ -0,0 +1,196 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1types.h                                                              */
+/*                                                                         */
+/*    Basic Type1/Type2 type definitions and interface (specification      */
+/*    only).                                                               */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __T1TYPES_H__
+#define __T1TYPES_H__
+
+
+#include<ft2build.h>
+#include FT_TYPE1_TABLES_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***              REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS              ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_Encoding                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure modeling a custom encoding.                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_chars  :: The number of character codes in the encoding.       */
+  /*                  Usually 256.                                         */
+  /*                                                                       */
+  /*    code_first :: The lowest valid character code in the encoding.     */
+  /*                                                                       */
+  /*    code_last  :: The highest valid character code in the encoding.    */
+  /*                                                                       */
+  /*    char_index :: An array of corresponding glyph indices.             */
+  /*                                                                       */
+  /*    char_name  :: An array of corresponding glyph names.               */
+  /*                                                                       */
+  typedef struct  T1_Encoding_
+  {
+    FT_Int       num_chars;
+    FT_Int       code_first;
+    FT_Int       code_last;
+
+    FT_UShort*   char_index;
+    FT_String**  char_name;
+
+  } T1_Encoding;
+
+
+  typedef enum  T1_EncodingType_
+  {
+    t1_encoding_none = 0,
+    t1_encoding_array,
+    t1_encoding_standard,
+    t1_encoding_expert
+
+  } T1_EncodingType;
+
+
+  typedef struct  T1_Font_
+  {
+    /* font info dictionary */
+    T1_FontInfo      font_info;
+
+    /* private dictionary */
+    T1_Private       private_dict;
+
+    /* top-level dictionary */
+    FT_String*       font_name;
+
+    T1_EncodingType  encoding_type;
+    T1_Encoding      encoding;
+
+    FT_Byte*         subrs_block;
+    FT_Byte*         charstrings_block;
+    FT_Byte*         glyph_names_block;
+
+    FT_Int           num_subrs;
+    FT_Byte**        subrs;
+    FT_Int*          subrs_len;
+
+    FT_Int           num_glyphs;
+    FT_String**      glyph_names;       /* array of glyph names       */
+    FT_Byte**        charstrings;       /* array of glyph charstrings */
+    FT_Int*          charstrings_len;
+
+    FT_Byte          paint_type;
+    FT_Byte          font_type;
+    FT_Matrix        font_matrix;
+    FT_Vector        font_offset;
+    FT_BBox          font_bbox;
+    FT_Long          font_id;
+
+    FT_Int           stroke_width;
+
+  } T1_Font;
+
+
+  typedef struct  CID_Subrs_
+  {
+    FT_UInt    num_subrs;
+    FT_Byte**  code;
+
+  } CID_Subrs;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***                ORIGINAL T1_FACE CLASS DEFINITION                  ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This structure/class is defined here because it is common to the      */
+  /* following formats: TTF, OpenType-TT, and OpenType-CFF.                */
+  /*                                                                       */
+  /* Note, however, that the classes TT_Size, TT_GlyphSlot, and TT_CharMap */
+  /* are not shared between font drivers, and are thus defined normally in */
+  /* `ttobjs.h'.                                                           */
+  /*                                                                       */
+  /*************************************************************************/
+
+  typedef struct T1_FaceRec_*   T1_Face;
+  typedef struct CID_FaceRec_*  CID_Face;
+
+
+  typedef struct  T1_FaceRec_
+  {
+    FT_FaceRec     root;
+    T1_Font        type1;
+    void*          psnames;
+    void*          psaux;
+    void*          afm_data;
+    FT_CharMapRec  charmaprecs[2];
+    FT_CharMap     charmaps[2];
+    PS_Unicodes    unicode_map;
+
+    /* support for Multiple Masters fonts */
+    T1_Blend*      blend;
+
+  } T1_FaceRec;
+
+
+  typedef struct  CID_FaceRec_
+  {
+    FT_FaceRec  root;
+    void*       psnames;
+    void*       psaux;
+    CID_Info    cid;
+    void*       afm_data;
+    CID_Subrs*  subrs;
+
+  } CID_FaceRec;
+
+
+FT_END_HEADER
+
+#endif /* __T1TYPES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/internal/tttypes.h b/libraries/freetype-2.0.5/include/freetype/internal/tttypes.h
new file mode 100644 (file)
index 0000000..5014e22
--- /dev/null
@@ -0,0 +1,1652 @@
+/***************************************************************************/
+/*                                                                         */
+/*  tttypes.h                                                              */
+/*                                                                         */
+/*    Basic SFNT/TrueType type definitions and interface (specification    */
+/*    only).                                                               */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTTYPES_H__
+#define __TTTYPES_H__
+
+
+#include <ft2build.h>
+#include FT_TRUETYPE_TABLES_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***             REQUIRED TRUETYPE/OPENTYPE TABLES DEFINITIONS         ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TTC_Header                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    TrueType collection header.  This table contains the offsets of    */
+  /*    the font headers of each distinct TrueType face in the file.       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    tag     :: Must be `ttc ' to indicate a TrueType collection.       */
+  /*                                                                       */
+  /*    version :: The version number.                                     */
+  /*                                                                       */
+  /*    count   :: The number of faces in the collection.  The             */
+  /*               specification says this should be an unsigned long, but */
+  /*               we use a signed long since we need the value -1 for     */
+  /*               specific purposes.                                      */
+  /*                                                                       */
+  /*    offsets :: The offsets of the font headers, one per face.          */
+  /*                                                                       */
+  typedef struct  TTC_Header_
+  {
+    FT_ULong   tag;
+    FT_Fixed   version;
+    FT_Long    count;
+    FT_ULong*  offsets;
+
+  } TTC_Header;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    SFNT_Header                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    SFNT file format header.                                           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    format_tag     :: The font format tag.                             */
+  /*                                                                       */
+  /*    num_tables     :: The number of tables in file.                    */
+  /*                                                                       */
+  /*    search_range   :: Must be 16*(max power of 2 <= num_tables).       */
+  /*                                                                       */
+  /*    entry_selector :: Must be log2 of search_range/16.                 */
+  /*                                                                       */
+  /*    range_shift    :: Must be num_tables*16 - search_range.            */
+  /*                                                                       */
+  typedef struct  SFNT_Header_
+  {
+    FT_ULong   format_tag;
+    FT_UShort  num_tables;
+    FT_UShort  search_range;
+    FT_UShort  entry_selector;
+    FT_UShort  range_shift;
+
+  } SFNT_Header;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_TableDir                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure models a TrueType table directory.  It is used to   */
+  /*    access the various tables of the font face.                        */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    version       :: The version number; starts with 0x00010000.       */
+  /*                                                                       */
+  /*    numTables     :: The number of tables.                             */
+  /*                                                                       */
+  /*    searchRange   :: Unused.                                           */
+  /*                                                                       */
+  /*    entrySelector :: Unused.                                           */
+  /*                                                                       */
+  /*    rangeShift    :: Unused.                                           */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This structure is only used during font opening.                   */
+  /*                                                                       */
+  typedef struct  TT_TableDir_
+  {
+    FT_Fixed   version;        /* should be 0x10000 */
+    FT_UShort  numTables;      /* number of tables  */
+
+    FT_UShort  searchRange;    /* These parameters are only used  */
+    FT_UShort  entrySelector;  /* for a dichotomy search in the   */
+    FT_UShort  rangeShift;     /* directory.  We ignore them.     */
+
+  } TT_TableDir;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Table                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure describes a given table of a TrueType font.         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    Tag      :: A four-bytes tag describing the table.                 */
+  /*                                                                       */
+  /*    CheckSum :: The table checksum.  This value can be ignored.        */
+  /*                                                                       */
+  /*    Offset   :: The offset of the table from the start of the TrueType */
+  /*                font in its resource.                                  */
+  /*                                                                       */
+  /*    Length   :: The table length (in bytes).                           */
+  /*                                                                       */
+  typedef struct  TT_Table_
+  {
+    FT_ULong  Tag;        /*        table type */
+    FT_ULong  CheckSum;   /*    table checksum */
+    FT_ULong  Offset;     /* table file offset */
+    FT_ULong  Length;     /*      table length */
+
+  } TT_Table;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_CMapDir                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure describes the directory of the `cmap' table,        */
+  /*    containing the font's character mappings table.                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    tableVersionNumber :: The version number.                          */
+  /*                                                                       */
+  /*    numCMaps           :: The number of charmaps in the font.          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This structure is only used during font loading.                   */
+  /*                                                                       */
+  typedef struct  TT_CMapDir_
+  {
+    FT_UShort  tableVersionNumber;
+    FT_UShort  numCMaps;
+
+  } TT_CMapDir;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_CMapDirEntry                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This structure describes a charmap in a TrueType font.             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    platformID :: An ID used to specify for which platform this        */
+  /*                  charmap is defined (FreeType manages all platforms). */
+  /*                                                                       */
+  /*    encodingID :: A platform-specific ID used to indicate which source */
+  /*                  encoding is used in this charmap.                    */
+  /*                                                                       */
+  /*    offset     :: The offset of the charmap relative to the start of   */
+  /*                  the `cmap' table.                                    */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This structure is only used during font loading.                   */
+  /*                                                                       */
+  typedef struct  TT_CMapDirEntry_
+  {
+    FT_UShort  platformID;
+    FT_UShort  platformEncodingID;
+    FT_Long    offset;
+
+  } TT_CMapDirEntry;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_LongMetrics                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure modeling the long metrics of the `hmtx' and `vmtx'     */
+  /*    TrueType tables.  The values are expressed in font units.          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    advance :: The advance width or height for the glyph.              */
+  /*                                                                       */
+  /*    bearing :: The left-side or top-side bearing for the glyph.        */
+  /*                                                                       */
+  typedef struct  TT_LongMetrics_
+  {
+    FT_UShort  advance;
+    FT_Short   bearing;
+
+  } TT_LongMetrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type> TT_ShortMetrics                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple type to model the short metrics of the `hmtx' and `vmtx'  */
+  /*    tables.                                                            */
+  /*                                                                       */
+  typedef FT_Short  TT_ShortMetrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_NameRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure modeling TrueType name records.  Name records are used */
+  /*    to store important strings like family name, style name,           */
+  /*    copyright, etc. in _localized_ versions (i.e., language, encoding, */
+  /*    etc).                                                              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    platformID   :: The ID of the name's encoding platform.            */
+  /*                                                                       */
+  /*    encodingID   :: The platform-specific ID for the name's encoding.  */
+  /*                                                                       */
+  /*    languageID   :: The platform-specific ID for the name's language.  */
+  /*                                                                       */
+  /*    nameID       :: The ID specifying what kind of name this is.       */
+  /*                                                                       */
+  /*    stringLength :: The length of the string in bytes.                 */
+  /*                                                                       */
+  /*    stringOffset :: The offset to the string in the `name' table.      */
+  /*                                                                       */
+  /*    string       :: A pointer to the string's bytes.  Note that these  */
+  /*                    are usually UTF-16 encoded characters.             */
+  /*                                                                       */
+  typedef struct  TT_NameRec_
+  {
+    FT_UShort  platformID;
+    FT_UShort  encodingID;
+    FT_UShort  languageID;
+    FT_UShort  nameID;
+    FT_UShort  stringLength;
+    FT_UShort  stringOffset;
+
+    /* this last field is not defined in the spec */
+    /* but used by the FreeType engine            */
+
+    FT_Byte*   string;
+
+  } TT_NameRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_NameTable                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure modeling the TrueType name table.                      */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    format         :: The format of the name table.                    */
+  /*                                                                       */
+  /*    numNameRecords :: The number of names in table.                    */
+  /*                                                                       */
+  /*    storageOffset  :: The offset of the name table in the `name'       */
+  /*                      TrueType table.                                  */
+  /*                                                                       */
+  /*    names          :: An array of name records.                        */
+  /*                                                                       */
+  /*    storage        :: The names storage area.                          */
+  /*                                                                       */
+  typedef struct  TT_NameTable_
+  {
+    FT_UShort    format;
+    FT_UShort    numNameRecords;
+    FT_UShort    storageOffset;
+    TT_NameRec*  names;
+    FT_Byte*     storage;
+
+  } TT_NameTable;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***             OPTIONAL TRUETYPE/OPENTYPE TABLES DEFINITIONS         ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_GaspRange                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A tiny structure used to model a gasp range according to the       */
+  /*    TrueType specification.                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    maxPPEM  :: The maximum ppem value to which `gaspFlag' applies.    */
+  /*                                                                       */
+  /*    gaspFlag :: A flag describing the grid-fitting and anti-aliasing   */
+  /*                modes to be used.                                      */
+  /*                                                                       */
+  typedef struct  TT_GaspRange_
+  {
+    FT_UShort  maxPPEM;
+    FT_UShort  gaspFlag;
+
+  } TT_GaspRange;
+
+
+#define TT_GASP_GRIDFIT  0x01
+#define TT_GASP_DOGRAY   0x02
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Gasp                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure modeling the TrueType `gasp' table used to specify     */
+  /*    grid-fitting and anti-aliasing behaviour.                          */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    version    :: The version number.                                  */
+  /*                                                                       */
+  /*    numRanges  :: The number of gasp ranges in table.                  */
+  /*                                                                       */
+  /*    gaspRanges :: An array of gasp ranges.                             */
+  /*                                                                       */
+  typedef struct  TT_Gasp_
+  {
+    FT_UShort      version;
+    FT_UShort      numRanges;
+    TT_GaspRange*  gaspRanges;
+
+  } TT_Gasp;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_HdmxRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A small structure used to model the pre-computed widths of a given */
+  /*    size.  They are found in the `hdmx' table.                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ppem      :: The pixels per EM value at which these metrics apply. */
+  /*                                                                       */
+  /*    max_width :: The maximum advance width for this metric.            */
+  /*                                                                       */
+  /*    widths    :: An array of widths.  Note: These are 8-bit bytes.     */
+  /*                                                                       */
+  typedef struct  TT_HdmxRec_
+  {
+    FT_Byte   ppem;
+    FT_Byte   max_width;
+    FT_Byte*  widths;
+
+  } TT_HdmxRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Hdmx                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model the `hdmx' table, which contains         */
+  /*    pre-computed widths for a set of given sizes/dimensions.           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    version     :: The version number.                                 */
+  /*                                                                       */
+  /*    num_records :: The number of hdmx records.                         */
+  /*                                                                       */
+  /*    records     :: An array of hdmx records.                           */
+  /*                                                                       */
+  typedef struct  TT_Hdmx_
+  {
+    FT_UShort    version;
+    FT_Short     num_records;
+    TT_HdmxRec*  records;
+
+  } TT_Hdmx;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Kern_0_Pair                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a kerning pair for the kerning table     */
+  /*    format 0.  The engine now loads this table if it finds one in the  */
+  /*    font file.                                                         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    left  :: The index of the left glyph in pair.                      */
+  /*                                                                       */
+  /*    right :: The index of the right glyph in pair.                     */
+  /*                                                                       */
+  /*    value :: The kerning distance.  A positive value spaces the        */
+  /*             glyphs, a negative one makes them closer.                 */
+  /*                                                                       */
+  typedef struct  TT_Kern_0_Pair_
+  {
+    FT_UShort  left;   /* index of left  glyph in pair */
+    FT_UShort  right;  /* index of right glyph in pair */
+    FT_FWord   value;  /* kerning value                */
+
+  } TT_Kern_0_Pair;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***                    EMBEDDED BITMAPS SUPPORT                       ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Metrics                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to hold the big metrics of a given glyph bitmap   */
+  /*    in a TrueType or OpenType font.  These are usually found in the    */
+  /*    `EBDT' (Microsoft) or `bloc' (Apple) table.                        */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    height       :: The glyph height in pixels.                        */
+  /*                                                                       */
+  /*    width        :: The glyph width in pixels.                         */
+  /*                                                                       */
+  /*    horiBearingX :: The horizontal left bearing.                       */
+  /*                                                                       */
+  /*    horiBearingY :: The horizontal top bearing.                        */
+  /*                                                                       */
+  /*    horiAdvance  :: The horizontal advance.                            */
+  /*                                                                       */
+  /*    vertBearingX :: The vertical left bearing.                         */
+  /*                                                                       */
+  /*    vertBearingY :: The vertical top bearing.                          */
+  /*                                                                       */
+  /*    vertAdvance  :: The vertical advance.                              */
+  /*                                                                       */
+  typedef struct  TT_SBit_Metrics_
+  {
+    FT_Byte  height;
+    FT_Byte  width;
+
+    FT_Char  horiBearingX;
+    FT_Char  horiBearingY;
+    FT_Byte  horiAdvance;
+
+    FT_Char  vertBearingX;
+    FT_Char  vertBearingY;
+    FT_Byte  vertAdvance;
+
+  } TT_SBit_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Small_Metrics                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to hold the small metrics of a given glyph bitmap */
+  /*    in a TrueType or OpenType font.  These are usually found in the    */
+  /*    `EBDT' (Microsoft) or the `bdat' (Apple) table.                    */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    height   :: The glyph height in pixels.                            */
+  /*                                                                       */
+  /*    width    :: The glyph width in pixels.                             */
+  /*                                                                       */
+  /*    bearingX :: The left-side bearing.                                 */
+  /*                                                                       */
+  /*    bearingY :: The top-side bearing.                                  */
+  /*                                                                       */
+  /*    advance  :: The advance width or height.                           */
+  /*                                                                       */
+  typedef struct  TT_SBit_Small_Metrics_
+  {
+    FT_Byte  height;
+    FT_Byte  width;
+
+    FT_Char  bearingX;
+    FT_Char  bearingY;
+    FT_Byte  advance;
+
+  } TT_SBit_Small_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Line_Metrics                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to describe the text line metrics of a given      */
+  /*    bitmap strike, for either a horizontal or vertical layout.         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    ascender                :: The ascender in pixels.                 */
+  /*                                                                       */
+  /*    descender               :: The descender in pixels.                */
+  /*                                                                       */
+  /*    max_width               :: The maximum glyph width in pixels.      */
+  /*                                                                       */
+  /*    caret_slope_enumerator  :: Rise of the caret slope, typically set  */
+  /*                               to 1 for non-italic fonts.              */
+  /*                                                                       */
+  /*    caret_slope_denominator :: Rise of the caret slope, typically set  */
+  /*                               to 0 for non-italic fonts.              */
+  /*                                                                       */
+  /*    caret_offset            :: Offset in pixels to move the caret for  */
+  /*                               proper positioning.                     */
+  /*                                                                       */
+  /*    min_origin_SB           :: Minimum of horiBearingX (resp.          */
+  /*                               vertBearingY).                          */
+  /*    min_advance_SB          :: Minimum of                              */
+  /*                                                                       */
+  /*                                 horizontal advance -                  */
+  /*                                   ( horiBearingX + width )            */
+  /*                                                                       */
+  /*                               resp.                                   */
+  /*                                                                       */
+  /*                                 vertical advance -                    */
+  /*                                   ( vertBearingY + height )           */
+  /*                                                                       */
+  /*    max_before_BL           :: Maximum of horiBearingY (resp.          */
+  /*                               vertBearingY).                          */
+  /*                                                                       */
+  /*    min_after_BL            :: Minimum of                              */
+  /*                                                                       */
+  /*                                 horiBearingY - height                 */
+  /*                                                                       */
+  /*                               resp.                                   */
+  /*                                                                       */
+  /*                                 vertBearingX - width                  */
+  /*                                                                       */
+  /*    pads                    :: Unused (to make the size of the record  */
+  /*                               a multiple of 32 bits.                  */
+  /*                                                                       */
+  typedef struct  TT_SBit_Line_Metrics_
+  {
+    FT_Char  ascender;
+    FT_Char  descender;
+    FT_Byte  max_width;
+    FT_Char  caret_slope_numerator;
+    FT_Char  caret_slope_denominator;
+    FT_Char  caret_offset;
+    FT_Char  min_origin_SB;
+    FT_Char  min_advance_SB;
+    FT_Char  max_before_BL;
+    FT_Char  min_after_BL;
+    FT_Char  pads[2];
+
+  } TT_SBit_Line_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Range                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A TrueType/OpenType subIndexTable as defined in the `EBLC'         */
+  /*    (Microsoft) or `bloc' (Apple) tables.                              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    first_glyph   :: The first glyph index in the range.               */
+  /*                                                                       */
+  /*    last_glyph    :: The last glyph index in the range.                */
+  /*                                                                       */
+  /*    index_format  :: The format of index table.  Valid values are 1    */
+  /*                     to 5.                                             */
+  /*                                                                       */
+  /*    image_format  :: The format of `EBDT' image data.                  */
+  /*                                                                       */
+  /*    image_offset  :: The offset to image data in `EBDT'.               */
+  /*                                                                       */
+  /*    image_size    :: For index formats 2 and 5.  This is the size in   */
+  /*                     bytes of each glyph bitmap.                       */
+  /*                                                                       */
+  /*    big_metrics   :: For index formats 2 and 5.  This is the big       */
+  /*                     metrics for each glyph bitmap.                    */
+  /*                                                                       */
+  /*    num_glyphs    :: For index formats 4 and 5.  This is the number of */
+  /*                     glyphs in the code array.                         */
+  /*                                                                       */
+  /*    glyph_offsets :: For index formats 1 and 3.                        */
+  /*                                                                       */
+  /*    glyph_codes   :: For index formats 4 and 5.                        */
+  /*                                                                       */
+  /*    table_offset  :: The offset of the index table in the `EBLC'       */
+  /*                     table.  Only used during strike loading.          */
+  /*                                                                       */
+  typedef struct  TT_SBit_Range
+  {
+    FT_UShort        first_glyph;
+    FT_UShort        last_glyph;
+
+    FT_UShort        index_format;
+    FT_UShort        image_format;
+    FT_ULong         image_offset;
+
+    FT_ULong         image_size;
+    TT_SBit_Metrics  metrics;
+    FT_ULong         num_glyphs;
+
+    FT_ULong*        glyph_offsets;
+    FT_UShort*       glyph_codes;
+
+    FT_ULong         table_offset;
+
+  } TT_SBit_Range;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Strike                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used describe a given bitmap strike in the `EBLC'      */
+  /*    (Microsoft) or `bloc' (Apple) tables.                              */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*   num_index_ranges :: The number of index ranges.                     */
+  /*                                                                       */
+  /*   index_ranges     :: An array of glyph index ranges.                 */
+  /*                                                                       */
+  /*   color_ref        :: Unused.  `color_ref' is put in for future       */
+  /*                       enhancements, but these fields are already      */
+  /*                       in use by other platforms (e.g. Newton).        */
+  /*                       For details, please see                         */
+  /*                                                                       */
+  /*                         http://fonts.apple.com/                       */
+  /*                                TTRefMan/RM06/Chap6bloc.html           */
+  /*                                                                       */
+  /*   hori             :: The line metrics for horizontal layouts.        */
+  /*                                                                       */
+  /*   vert             :: The line metrics for vertical layouts.          */
+  /*                                                                       */
+  /*   start_glyph      :: The lowest glyph index for this strike.         */
+  /*                                                                       */
+  /*   end_glyph        :: The highest glyph index for this strike.        */
+  /*                                                                       */
+  /*   x_ppem           :: The number of horizontal pixels per EM.         */
+  /*                                                                       */
+  /*   y_ppem           :: The number of vertical pixels per EM.           */
+  /*                                                                       */
+  /*   bit_depth        :: The bit depth.  Valid values are 1, 2, 4,       */
+  /*                       and 8.                                          */
+  /*                                                                       */
+  /*   flags            :: Is this a vertical or horizontal strike?  For   */
+  /*                       details, please see                             */
+  /*                                                                       */
+  /*                         http://fonts.apple.com/                       */
+  /*                                TTRefMan/RM06/Chap6bloc.html           */
+  /*                                                                       */
+  typedef struct  TT_SBit_Strike_
+  {
+    FT_Int                num_ranges;
+    TT_SBit_Range*        sbit_ranges;
+    FT_ULong              ranges_offset;
+
+    FT_ULong              color_ref;
+
+    TT_SBit_Line_Metrics  hori;
+    TT_SBit_Line_Metrics  vert;
+
+    FT_UShort             start_glyph;
+    FT_UShort             end_glyph;
+
+    FT_Byte               x_ppem;
+    FT_Byte               y_ppem;
+
+    FT_Byte               bit_depth;
+    FT_Char               flags;
+
+  } TT_SBit_Strike;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Component                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A simple structure to describe a compound sbit element.            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    glyph_code :: The element's glyph index.                           */
+  /*                                                                       */
+  /*    x_offset   :: The element's left bearing.                          */
+  /*                                                                       */
+  /*    y_offset   :: The element's top bearing.                           */
+  /*                                                                       */
+  typedef struct  TT_SBit_Component_
+  {
+    FT_UShort  glyph_code;
+    FT_Char    x_offset;
+    FT_Char    y_offset;
+
+  } TT_SBit_Component;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_SBit_Scale                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used describe a given bitmap scaling table, as defined */
+  /*    in the `EBSC' table.                                               */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    hori              :: The horizontal line metrics.                  */
+  /*                                                                       */
+  /*    vert              :: The vertical line metrics.                    */
+  /*                                                                       */
+  /*    x_ppem            :: The number of horizontal pixels per EM.       */
+  /*                                                                       */
+  /*    y_ppem            :: The number of vertical pixels per EM.         */
+  /*                                                                       */
+  /*    x_ppem_substitute :: Substitution x_ppem value.                    */
+  /*                                                                       */
+  /*    y_ppem_substitute :: Substitution y_ppem value.                    */
+  /*                                                                       */
+  typedef struct  TT_SBit_Scale_
+  {
+    TT_SBit_Line_Metrics  hori;
+    TT_SBit_Line_Metrics  vert;
+
+    FT_Byte               x_ppem;
+    FT_Byte               y_ppem;
+
+    FT_Byte               x_ppem_substitute;
+    FT_Byte               y_ppem_substitute;
+
+  } TT_SBit_Scale;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***                  POSTSCRIPT GLYPH NAMES SUPPORT                   ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Post_20                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Postscript names sub-table, format 2.0.  Stores the PS name of     */
+  /*    each glyph in the font face.                                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_glyphs    :: The number of named glyphs in the table.          */
+  /*                                                                       */
+  /*    num_names     :: The number of PS names stored in the table.       */
+  /*                                                                       */
+  /*    glyph_indices :: The indices of the glyphs in the names arrays.    */
+  /*                                                                       */
+  /*    glyph_names   :: The PS names not in Mac Encoding.                 */
+  /*                                                                       */
+  typedef struct  TT_Post_20_
+  {
+    FT_UShort   num_glyphs;
+    FT_UShort   num_names;
+    FT_UShort*  glyph_indices;
+    FT_Char**   glyph_names;
+
+  } TT_Post_20;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Post_25                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Postscript names sub-table, format 2.5.  Stores the PS name of     */
+  /*    each glyph in the font face.                                       */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    num_glyphs :: The number of glyphs in the table.                   */
+  /*                                                                       */
+  /*    offsets    :: An array of signed offsets in a normal Mac           */
+  /*                  Postscript name encoding.                            */
+  /*                                                                       */
+  typedef struct  TT_Post_25_
+  {
+    FT_UShort  num_glyphs;
+    FT_Char*   offsets;
+
+  } TT_Post_25;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Post_Names                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Postscript names table, either format 2.0 or 2.5.                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    loaded    :: A flag to indicate whether the PS names are loaded.   */
+  /*                                                                       */
+  /*    format_20 :: The sub-table used for format 2.0.                    */
+  /*                                                                       */
+  /*    format_25 :: The sub-table used for format 2.5.                    */
+  /*                                                                       */
+  typedef struct  TT_Post_Names_
+  {
+    FT_Bool       loaded;
+
+    union
+    {
+      TT_Post_20  format_20;
+      TT_Post_25  format_25;
+
+    } names;
+
+  } TT_Post_Names;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***                  TRUETYPE CHARMAPS SUPPORT                        ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /* format 0 */
+
+  typedef struct  TT_CMap0_
+  {
+    FT_ULong  language;       /* for Mac fonts (originally ushort) */
+
+    FT_Byte*  glyphIdArray;
+
+  } TT_CMap0;
+
+
+  /* format 2 */
+
+  typedef struct  TT_CMap2SubHeader_
+  {
+    FT_UShort  firstCode;      /* first valid low byte         */
+    FT_UShort  entryCount;     /* number of valid low bytes    */
+    FT_Short   idDelta;        /* delta value to glyphIndex    */
+    FT_UShort  idRangeOffset;  /* offset from here to 1st code */
+
+  } TT_CMap2SubHeader;
+
+
+  typedef struct  TT_CMap2_
+  {
+    FT_ULong            language;     /* for Mac fonts (originally ushort) */
+
+    FT_UShort*          subHeaderKeys;
+    /* high byte mapping table            */
+    /* value = subHeader index * 8        */
+
+    TT_CMap2SubHeader*  subHeaders;
+    FT_UShort*          glyphIdArray;
+    FT_UShort           numGlyphId;   /* control value */
+
+  } TT_CMap2;
+
+
+  /* format 4 */
+
+  typedef struct  TT_CMap4Segment_
+  {
+    FT_UShort  endCount;
+    FT_UShort  startCount;
+    FT_Short   idDelta;
+    FT_UShort  idRangeOffset;
+
+  } TT_CMap4Segment;
+
+
+  typedef struct  TT_CMap4_
+  {
+    FT_ULong          language;       /* for Mac fonts (originally ushort) */
+
+    FT_UShort         segCountX2;     /* number of segments * 2            */
+    FT_UShort         searchRange;    /* these parameters can be used      */
+    FT_UShort         entrySelector;  /* for a binary search               */
+    FT_UShort         rangeShift;
+
+    TT_CMap4Segment*  segments;
+    FT_UShort*        glyphIdArray;
+    FT_UShort         numGlyphId;    /* control value */
+
+    TT_CMap4Segment*  last_segment;  /* last used segment; this is a small  */
+                                     /* cache to potentially increase speed */
+  } TT_CMap4;
+
+
+  /* format 6 */
+
+  typedef struct  TT_CMap6_
+  {
+    FT_ULong    language;       /* for Mac fonts (originally ushort)     */
+
+    FT_UShort   firstCode;      /* first character code of subrange      */
+    FT_UShort   entryCount;     /* number of character codes in subrange */
+
+    FT_UShort*  glyphIdArray;
+
+  } TT_CMap6;
+
+
+  /* auxiliary table for format 8 and 12 */
+
+  typedef struct  TT_CMapGroup_
+  {
+    FT_ULong  startCharCode;
+    FT_ULong  endCharCode;
+    FT_ULong  startGlyphID;
+
+  } TT_CMapGroup;
+
+
+  /* FreeType handles format 8 and 12 identically.  It is not necessary to
+     cover mixed 16bit and 32bit codes since FreeType always uses FT_ULong
+     for input character codes -- converting Unicode surrogates to 32bit
+     character codes must be done by the application.                      */
+
+  typedef struct  TT_CMap8_12_
+  {
+    FT_ULong       language;        /* for Mac fonts */
+
+    FT_ULong       nGroups;
+    TT_CMapGroup*  groups;
+
+    TT_CMapGroup*  last_group;      /* last used group; this is a small    */
+                                    /* cache to potentially increase speed */
+  } TT_CMap8_12;
+
+
+  /* format 10 */
+
+  typedef struct  TT_CMap10_
+  {
+    FT_ULong    language;           /* for Mac fonts */
+
+    FT_ULong    startCharCode;      /* first character covered */
+    FT_ULong    numChars;           /* number of characters covered */
+
+    FT_UShort*  glyphs;
+
+  } TT_CMap10;
+
+
+  typedef struct TT_CMapTable_  TT_CMapTable;
+
+
+  typedef FT_UInt
+  (*TT_CharMap_Func)( TT_CMapTable*  charmap,
+                      FT_ULong       char_code );
+
+
+  /* charmap table */
+  struct  TT_CMapTable_
+  {
+    FT_UShort  platformID;
+    FT_UShort  platformEncodingID;
+    FT_UShort  format;
+    FT_ULong   length;          /* must be ulong for formats 8, 10, and 12 */
+
+    FT_Bool    loaded;
+    FT_ULong   offset;
+
+    union
+    {
+      TT_CMap0     cmap0;
+      TT_CMap2     cmap2;
+      TT_CMap4     cmap4;
+      TT_CMap6     cmap6;
+      TT_CMap8_12  cmap8_12;
+      TT_CMap10    cmap10;
+    } c;
+
+    TT_CharMap_Func  get_index;
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_CharMapRec                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The TrueType character map object type.                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root :: The parent character map structure.                        */
+  /*                                                                       */
+  /*    cmap :: The used character map.                                    */
+  /*                                                                       */
+  typedef struct  TT_CharMapRec_
+  {
+    FT_CharMapRec  root;
+    TT_CMapTable   cmap;
+
+  } TT_CharMapRec;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /***                  ORIGINAL TT_FACE CLASS DEFINITION                ***/
+  /***                                                                   ***/
+  /***                                                                   ***/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This structure/class is defined here because it is common to the      */
+  /* following formats: TTF, OpenType-TT, and OpenType-CFF.                */
+  /*                                                                       */
+  /* Note, however, that the classes TT_Size, TT_GlyphSlot, and TT_CharMap */
+  /* are not shared between font drivers, and are thus defined normally in */
+  /* `ttobjs.h'.                                                           */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_Face                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType face/font object.  A TT_Face encapsulates   */
+  /*    the resolution and scaling independent parts of a TrueType font    */
+  /*    resource.                                                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The TT_Face structure is also used as a `parent class' for the     */
+  /*    OpenType-CFF class (T2_Face).                                      */
+  /*                                                                       */
+  typedef struct TT_FaceRec_*  TT_Face;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_CharMap                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType character mapping object.                   */
+  /*                                                                       */
+  typedef struct TT_CharMapRec_*  TT_CharMap;
+
+
+  /* a function type used for the truetype bytecode interpreter hooks */
+  typedef FT_Error
+  (*TT_Interpreter)( void*  exec_context );
+
+  /* forward declaration */
+  typedef struct TT_Loader_  TT_Loader;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Goto_Table_Func                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Seeks a stream to the start of a given TrueType table.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /*    tag    :: A 4-byte tag used to name the table.                     */
+  /*                                                                       */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    length :: The length of the table in bytes.  Set to 0 if not       */
+  /*              needed.                                                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be at the font file's origin.               */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Goto_Table_Func)( TT_Face    face,
+                         FT_ULong   tag,
+                         FT_Stream  stream,
+                         FT_ULong*  length );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Access_Glyph_Frame_Func                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Seeks a stream to the start of a given glyph element, and opens a  */
+  /*    frame for it.                                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    loader      :: The current TrueType glyph loader object.           */
+  /*                                                                       */
+  /*    glyph index :: The index of the glyph to access.                   */
+  /*                                                                       */
+  /*    offset      :: The offset of the glyph according to the            */
+  /*                   `locations' table.                                  */
+  /*                                                                       */
+  /*    byte_count  :: The size of the frame in bytes.                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function is normally equivalent to FILE_Seek(offset)          */
+  /*    followed by ACCESS_Frame(byte_count) with the loader's stream, but */
+  /*    alternative formats (e.g. compressed ones) might use something     */
+  /*    different.                                                         */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Access_Glyph_Frame_Func)( TT_Loader*  loader,
+                                 FT_UInt     glyph_index,
+                                 FT_ULong    offset,
+                                 FT_UInt     byte_count );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Load_Glyph_Element_Func                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Reads one glyph element (its header, a simple glyph, or a          */
+  /*    composite) from the loader's current stream frame.                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    loader :: The current TrueType glyph loader object.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  typedef FT_Error
+  (*TT_Load_Glyph_Element_Func)( TT_Loader*  loader );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <FuncType>                                                            */
+  /*    TT_Forget_Glyph_Frame_Func                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Closes the current loader stream frame for the glyph.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    loader :: The current TrueType glyph loader object.                */
+  /*                                                                       */
+  typedef void
+  (*TT_Forget_Glyph_Frame_Func)( TT_Loader*  loader );
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                         TrueType Face Type                            */
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Face                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The TrueType face class.  These objects model the resolution and   */
+  /*    point-size independent data found in a TrueType font file.         */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root                 :: The base FT_Face structure, managed by the */
+  /*                            base layer.                                */
+  /*                                                                       */
+  /*    ttc_header           :: The TrueType collection header, used when  */
+  /*                            the file is a `ttc' rather than a `ttf'.   */
+  /*                            For ordinary font files, the field         */
+  /*                            `ttc_header.count' is set to 0.            */
+  /*                                                                       */
+  /*    format_tag           :: The font format tag.                       */
+  /*                                                                       */
+  /*    num_tables           :: The number of TrueType tables in this font */
+  /*                            file.                                      */
+  /*                                                                       */
+  /*    dir_tables           :: The directory of TrueType tables for this  */
+  /*                            font file.                                 */
+  /*                                                                       */
+  /*    header               :: The font's font header (`head' table).     */
+  /*                            Read on font opening.                      */
+  /*                                                                       */
+  /*    horizontal           :: The font's horizontal header (`hhea'       */
+  /*                            table).  This field also contains the      */
+  /*                            associated horizontal metrics table        */
+  /*                            (`hmtx').                                  */
+  /*                                                                       */
+  /*    max_profile          :: The font's maximum profile table.  Read on */
+  /*                            font opening.  Note that some maximum      */
+  /*                            values cannot be taken directly from this  */
+  /*                            table.  We thus define additional fields   */
+  /*                            below to hold the computed maxima.         */
+  /*                                                                       */
+  /*    max_components       :: The maximum number of glyph components     */
+  /*                            required to load any composite glyph from  */
+  /*                            this font.  Used to size the load stack.   */
+  /*                                                                       */
+  /*    vertical_info        :: A boolean which is set when the font file  */
+  /*                            contains vertical metrics.  If not, the    */
+  /*                            value of the `vertical' field is           */
+  /*                            undefined.                                 */
+  /*                                                                       */
+  /*    vertical             :: The font's vertical header (`vhea' table). */
+  /*                            This field also contains the associated    */
+  /*                            vertical metrics table (`vmtx'), if found. */
+  /*                            IMPORTANT: The contents of this field is   */
+  /*                            undefined if the `verticalInfo' field is   */
+  /*                            unset.                                     */
+  /*                                                                       */
+  /*    num_names            :: The number of name records within this     */
+  /*                            TrueType font.                             */
+  /*                                                                       */
+  /*    name_table           :: The table of name records (`name').        */
+  /*                                                                       */
+  /*    os2                  :: The font's OS/2 table (`OS/2').            */
+  /*                                                                       */
+  /*    postscript           :: The font's PostScript table (`post'        */
+  /*                            table).  The PostScript glyph names are    */
+  /*                            not loaded by the driver on face opening.  */
+  /*                            See the `ttpost' module for more details.  */
+  /*                                                                       */
+  /*    num_charmaps         :: The number of character mappings in the    */
+  /*                            font.                                      */
+  /*                                                                       */
+  /*    charmaps             :: The array of charmap objects for this font */
+  /*                            file.  Note that this field is a typeless  */
+  /*                            pointer.  The Reason is that the format of */
+  /*                            charmaps varies with the underlying font   */
+  /*                            format and cannot be determined here.      */
+  /*                                                                       */
+  /*    goto_table           :: A function called by each TrueType table   */
+  /*                            loader to position a stream's cursor to    */
+  /*                            the start of a given table according to    */
+  /*                            its tag.  It defaults to TT_Goto_Face but  */
+  /*                            can be different for strange formats (e.g. */
+  /*                            Type 42).                                  */
+  /*                                                                       */
+  /*    access_glyph_frame   :: XXX                                        */
+  /*                                                                       */
+  /*    read_glyph_header    :: XXX                                        */
+  /*                                                                       */
+  /*    read_simple_glyph    :: XXX                                        */
+  /*                                                                       */
+  /*    read_composite_glyph :: XXX                                        */
+  /*                                                                       */
+  /*    forget_glyph_frame   :: XXX                                        */
+  /*                                                                       */
+  /*    sfnt                 :: A pointer to the SFNT `driver' interface.  */
+  /*                                                                       */
+  /*    psnames              :: A pointer to the `PSNames' module          */
+  /*                            interface.                                 */
+  /*                                                                       */
+  /*    hdmx                 :: The face's horizontal device metrics       */
+  /*                            (`hdmx' table).  This table is optional in */
+  /*                            TrueType/OpenType fonts.                   */
+  /*                                                                       */
+  /*    gasp                 :: The grid-fitting and scaling properties    */
+  /*                            table (`gasp').  This table is optional in */
+  /*                            TrueType/OpenType fonts.                   */
+  /*                                                                       */
+  /*    pclt                 :: XXX                                        */
+  /*                                                                       */
+  /*    num_sbit_strikes     :: The number of sbit strikes, i.e., bitmap   */
+  /*                            sizes, embedded in this font.              */
+  /*                                                                       */
+  /*    sbit_strikes         :: An array of sbit strikes embedded in this  */
+  /*                            font.  This table is optional in a         */
+  /*                            TrueType/OpenType font.                    */
+  /*                                                                       */
+  /*    num_sbit_scales      :: The number of sbit scales for this font.   */
+  /*                                                                       */
+  /*    sbit_scales          :: Array of sbit scales embedded in this      */
+  /*                            font.  This table is optional in a         */
+  /*                            TrueType/OpenType font.                    */
+  /*                                                                       */
+  /*    postscript_names     :: A table used to store the Postscript names */
+  /*                            of  the glyphs for this font.  See the     */
+  /*                            file  `ttconfig.h' for comments on the     */
+  /*                            TT_CONFIG_OPTION_POSTSCRIPT_NAMES option.  */
+  /*                                                                       */
+  /*    num_locations        :: The number of glyph locations in this      */
+  /*                            TrueType file.  This should be             */
+  /*                            identical to the number of glyphs.         */
+  /*                            Ignored for Type 2 fonts.                  */
+  /*                                                                       */
+  /*    glyph_locations      :: An array of longs.  These are offsets to   */
+  /*                            glyph data within the `glyf' table.        */
+  /*                            Ignored for Type 2 font faces.             */
+  /*                                                                       */
+  /*    font_program_size    :: Size in bytecodes of the face's font       */
+  /*                            program.  0 if none defined.  Ignored for  */
+  /*                            Type 2 fonts.                              */
+  /*                                                                       */
+  /*    font_program         :: The face's font program (bytecode stream)  */
+  /*                            executed at load time, also used during    */
+  /*                            glyph rendering.  Comes from the `fpgm'    */
+  /*                            table.  Ignored for Type 2 font fonts.     */
+  /*                                                                       */
+  /*    cvt_program_size     :: The size in bytecodes of the face's cvt    */
+  /*                            program.  Ignored for Type 2 fonts.        */
+  /*                                                                       */
+  /*    cvt_program          :: The face's cvt program (bytecode stream)   */
+  /*                            executed each time an instance/size is     */
+  /*                            changed/reset.  Comes from the `prep'      */
+  /*                            table.  Ignored for Type 2 fonts.          */
+  /*                                                                       */
+  /*    cvt_size             :: Size of the control value table (in        */
+  /*                            entries).   Ignored for Type 2 fonts.      */
+  /*                                                                       */
+  /*    cvt                  :: The face's original control value table.   */
+  /*                            Coordinates are expressed in unscaled font */
+  /*                            units.  Comes from the `cvt ' table.       */
+  /*                            Ignored for Type 2 fonts.                  */
+  /*                                                                       */
+  /*    num_kern_pairs       :: The number of kerning pairs present in the */
+  /*                            font file.  The engine only loads the      */
+  /*                            first horizontal format 0 kern table it    */
+  /*                            finds in the font file.  You should use    */
+  /*                            the `ttxkern' structures if you want to    */
+  /*                            access other kerning tables.  Ignored      */
+  /*                            for Type 2 fonts.                          */
+  /*                                                                       */
+  /*    kern_table_index     :: The index of the kerning table in the font */
+  /*                            kerning directory.  Only used by the       */
+  /*                            ttxkern extension to avoid data            */
+  /*                            duplication.  Ignored for Type 2 fonts.    */
+  /*                                                                       */
+  /*    interpreter          :: A pointer to the TrueType bytecode         */
+  /*                            interpreters field is also used to hook    */
+  /*                            the debugger in `ttdebug'.                 */
+  /*                                                                       */
+  /*    extra                :: XXX                                        */
+  /*                                                                       */
+  typedef struct  TT_FaceRec_
+  {
+    FT_FaceRec         root;
+
+    TTC_Header         ttc_header;
+
+    FT_ULong           format_tag;
+    FT_UShort          num_tables;
+    TT_Table*          dir_tables;
+
+    TT_Header          header;       /* TrueType header table          */
+    TT_HoriHeader      horizontal;   /* TrueType horizontal header     */
+
+    TT_MaxProfile      max_profile;
+    FT_ULong           max_components;
+
+    FT_Bool            vertical_info;
+    TT_VertHeader      vertical;     /* TT Vertical header, if present */
+
+    FT_UShort          num_names;    /* number of name records  */
+    TT_NameTable       name_table;   /* name table              */
+
+    TT_OS2             os2;          /* TrueType OS/2 table            */
+    TT_Postscript      postscript;   /* TrueType Postscript table      */
+
+    FT_Int             num_charmaps;
+    TT_CharMap         charmaps;     /* array of TT_CharMapRec */
+
+    TT_Goto_Table_Func          goto_table;
+
+    TT_Access_Glyph_Frame_Func  access_glyph_frame;
+    TT_Load_Glyph_Element_Func  read_glyph_header;
+    TT_Load_Glyph_Element_Func  read_simple_glyph;
+    TT_Load_Glyph_Element_Func  read_composite_glyph;
+    TT_Forget_Glyph_Frame_Func  forget_glyph_frame;
+
+    /* a typeless pointer to the SFNT_Interface table used to load     */
+    /* the basic TrueType tables in the face object                    */
+    void*              sfnt;
+
+    /* a typeless pointer to the PSNames_Interface table used to       */
+    /* handle glyph names <-> unicode & Mac values                     */
+    void*              psnames;
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* Optional TrueType/OpenType tables                                   */
+    /*                                                                     */
+    /***********************************************************************/
+
+    /* horizontal device metrics */
+    TT_Hdmx            hdmx;
+
+    /* grid-fitting and scaling table */
+    TT_Gasp            gasp;                 /* the `gasp' table */
+
+    /* PCL 5 table */
+    TT_PCLT            pclt;
+
+    /* embedded bitmaps support */
+    FT_Int             num_sbit_strikes;
+    TT_SBit_Strike*    sbit_strikes;
+
+    FT_Int             num_sbit_scales;
+    TT_SBit_Scale*     sbit_scales;
+
+    /* postscript names table */
+    TT_Post_Names      postscript_names;
+
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* TrueType-specific fields (ignored by the OTF-Type2 driver)          */
+    /*                                                                     */
+    /***********************************************************************/
+
+    /* the glyph locations */
+    FT_UShort          num_locations;
+    FT_Long*           glyph_locations;
+
+    /* the font program, if any */
+    FT_ULong           font_program_size;
+    FT_Byte*           font_program;
+
+    /* the cvt program, if any */
+    FT_ULong           cvt_program_size;
+    FT_Byte*           cvt_program;
+
+    /* the original, unscaled, control value table */
+    FT_ULong           cvt_size;
+    FT_Short*          cvt;
+
+    /* the format 0 kerning table, if any */
+    FT_Int             num_kern_pairs;
+    FT_Int             kern_table_index;
+    TT_Kern_0_Pair*    kern_pairs;
+
+    /* A pointer to the bytecode interpreter to use.  This is also */
+    /* used to hook the debugger for the `ttdebug' utility.        */
+    TT_Interpreter     interpreter;
+
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* Other tables or fields. This is used by derivative formats like     */
+    /* OpenType.                                                           */
+    /*                                                                     */
+    /***********************************************************************/
+
+    FT_Generic      extra;
+
+  } TT_FaceRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  <Struct>                                                             */
+  /*     TT_GlyphZone                                                      */
+  /*                                                                       */
+  /*  <Description>                                                        */
+  /*     A glyph zone is used to load, scale and hint glyph outline        */
+  /*     coordinates.                                                      */
+  /*                                                                       */
+  /*  <Fields>                                                             */
+  /*     memory       :: A handle to the memory manager.                   */
+  /*                                                                       */
+  /*     max_points   :: The maximal size in points of the zone.           */
+  /*                                                                       */
+  /*     max_contours :: Max size in links contours of thez one.           */
+  /*                                                                       */
+  /*     n_points     :: The current number of points in the zone.         */
+  /*                                                                       */
+  /*     n_contours   :: The current number of contours in the zone.       */
+  /*                                                                       */
+  /*     org          :: The original glyph coordinates (font              */
+  /*                     units/scaled).                                    */
+  /*                                                                       */
+  /*     cur          :: The current glyph coordinates (scaled/hinted).    */
+  /*                                                                       */
+  /*     tags         :: The point control tags.                           */
+  /*                                                                       */
+  /*     contours     :: The contours end points.                          */
+  /*                                                                       */
+  typedef struct  TT_GlyphZone_
+  {
+    FT_Memory   memory;
+    FT_UShort   max_points;
+    FT_UShort   max_contours;
+    FT_UShort   n_points;   /* number of points in zone    */
+    FT_Short    n_contours; /* number of contours          */
+
+    FT_Vector*  org;        /* original point coordinates  */
+    FT_Vector*  cur;        /* current point coordinates   */
+
+    FT_Byte*    tags;       /* current touch flags         */
+    FT_UShort*  contours;   /* contour end points          */
+
+  } TT_GlyphZone;
+
+
+  /* handle to execution context */
+  typedef struct TT_ExecContextRec_*  TT_ExecContext;
+
+  /* glyph loader structure */
+  struct  TT_Loader_
+  {
+    FT_Face          face;
+    FT_Size          size;
+    FT_GlyphSlot     glyph;
+    FT_GlyphLoader*  gloader;
+
+    FT_ULong         load_flags;
+    FT_UInt          glyph_index;
+
+    FT_Stream        stream;
+    FT_Int           byte_len;
+
+    FT_Short         n_contours;
+    FT_BBox          bbox;
+    FT_Int           left_bearing;
+    FT_Int           advance;
+    FT_Int           linear;
+    FT_Bool          linear_def;
+    FT_Bool          preserve_pps;
+    FT_Vector        pp1;
+    FT_Vector        pp2;
+
+    FT_ULong         glyf_offset;
+
+    /* the zone where we load our glyphs */
+    TT_GlyphZone     base;
+    TT_GlyphZone     zone;
+
+    TT_ExecContext   exec;
+    FT_Byte*         instructions;
+    FT_ULong         ins_pos;
+
+    /* for possible extensibility in other formats */
+    void*            other;
+
+  };
+
+
+FT_END_HEADER
+
+#endif /* __TTTYPES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/t1tables.h b/libraries/freetype-2.0.5/include/freetype/t1tables.h
new file mode 100644 (file)
index 0000000..9c32b92
--- /dev/null
@@ -0,0 +1,263 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1tables.h                                                             */
+/*                                                                         */
+/*    Basic Type 1/Type 2 tables definitions and interface (specification  */
+/*    only).                                                               */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __T1TABLES_H__
+#define __T1TABLES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    type1_tables                                                       */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    Type 1 Tables                                                      */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    Type 1 (PostScript) specific font tables.                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This section contains the definition of Type 1-specific tables,    */
+  /*    including structures related to other PostScript font formats.     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* Note that we separate font data in T1_FontInfo and T1_Private */
+  /* structures in order to support Multiple Master fonts.         */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_FontInfo                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a Type1/Type2 FontInfo dictionary.  Note */
+  /*    that for Multiple Master fonts, each instance has its own          */
+  /*    FontInfo.                                                          */
+  /*                                                                       */
+  typedef struct  T1_FontInfo
+  {
+    FT_String*  version;
+    FT_String*  notice;
+    FT_String*  full_name;
+    FT_String*  family_name;
+    FT_String*  weight;
+    FT_Long     italic_angle;
+    FT_Bool     is_fixed_pitch;
+    FT_Short    underline_position;
+    FT_UShort   underline_thickness;
+
+  } T1_FontInfo;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_Private                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a Type1/Type2 FontInfo dictionary.  Note */
+  /*    that for Multiple Master fonts, each instance has its own Private  */
+  /*    dict.                                                              */
+  /*                                                                       */
+  typedef struct  T1_Private
+  {
+    FT_Int     unique_id;
+    FT_Int     lenIV;
+
+    FT_Byte    num_blue_values;
+    FT_Byte    num_other_blues;
+    FT_Byte    num_family_blues;
+    FT_Byte    num_family_other_blues;
+
+    FT_Short   blue_values[14];
+    FT_Short   other_blues[10];
+
+    FT_Short   family_blues      [14];
+    FT_Short   family_other_blues[10];
+
+    FT_Fixed   blue_scale;
+    FT_Int     blue_shift;
+    FT_Int     blue_fuzz;
+
+    FT_UShort  standard_width[1];
+    FT_UShort  standard_height[1];
+
+    FT_Byte    num_snap_widths;
+    FT_Byte    num_snap_heights;
+    FT_Bool    force_bold;
+    FT_Bool    round_stem_up;
+
+    FT_Short   snap_widths [13];  /* including std width  */
+    FT_Short   snap_heights[13];  /* including std height */
+
+    FT_Long    language_group;
+    FT_Long    password;
+
+    FT_Short   min_feature[2];
+
+  } T1_Private;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Enum>                                                                */
+  /*    T1_Blend_Flags                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A set of flags used to indicate which fields are present in a      */
+  /*    given blen dictionary (font info or private).  Used to support     */
+  /*    Multiple Masters fonts.                                            */
+  /*                                                                       */
+  typedef enum
+  {
+    /*# required fields in a FontInfo blend dictionary */
+    t1_blend_underline_position = 0,
+    t1_blend_underline_thickness,
+    t1_blend_italic_angle,
+
+    /*# required fields in a Private blend dictionary */
+    t1_blend_blue_values,
+    t1_blend_other_blues,
+    t1_blend_standard_width,
+    t1_blend_standard_height,
+    t1_blend_stem_snap_widths,
+    t1_blend_stem_snap_heights,
+    t1_blend_blue_scale,
+    t1_blend_blue_shift,
+    t1_blend_family_blues,
+    t1_blend_family_other_blues,
+    t1_blend_force_bold,
+
+    /*# never remove */
+    t1_blend_max
+
+  } T1_Blend_Flags;
+
+
+  /* maximum number of Multiple Masters designs, as defined in the spec */
+#define T1_MAX_MM_DESIGNS     16
+
+  /* maximum number of Multiple Masters axes, as defined in the spec */
+#define T1_MAX_MM_AXIS         4
+
+  /* maximum number of elements in a design map */
+#define T1_MAX_MM_MAP_POINTS  20
+
+
+  /* this structure is used to store the BlendDesignMap entry for an axis */
+  typedef struct  T1_DesignMap_
+  {
+    FT_Byte    num_points;
+    FT_Fixed*  design_points;
+    FT_Fixed*  blend_points;
+
+  } T1_DesignMap;
+
+
+  typedef struct  T1_Blend_
+  {
+    FT_UInt       num_designs;
+    FT_UInt       num_axis;
+
+    FT_String*    axis_names[T1_MAX_MM_AXIS];
+    FT_Fixed*     design_pos[T1_MAX_MM_DESIGNS];
+    T1_DesignMap  design_map[T1_MAX_MM_AXIS];
+
+    FT_Fixed*     weight_vector;
+    FT_Fixed*     default_weight_vector;
+
+    T1_FontInfo*  font_infos[T1_MAX_MM_DESIGNS + 1];
+    T1_Private*   privates  [T1_MAX_MM_DESIGNS + 1];
+
+    FT_ULong      blend_bitflags;
+
+  } T1_Blend;
+
+
+  typedef struct  CID_FontDict_
+  {
+    T1_Private  private_dict;
+
+    FT_UInt     len_buildchar;
+    FT_Fixed    forcebold_threshold;
+    FT_Pos      stroke_width;
+    FT_Fixed    expansion_factor;
+
+    FT_Byte     paint_type;
+    FT_Byte     font_type;
+    FT_Matrix   font_matrix;
+    FT_Vector   font_offset;
+
+    FT_UInt     num_subrs;
+    FT_ULong    subrmap_offset;
+    FT_Int      sd_bytes;
+
+  } CID_FontDict;
+
+
+  typedef struct  CID_Info_
+  {
+    FT_String*     cid_font_name;
+    FT_Fixed       cid_version;
+    FT_Int         cid_font_type;
+
+    FT_String*     registry;
+    FT_String*     ordering;
+    FT_Int         supplement;
+
+    T1_FontInfo    font_info;
+    FT_BBox        font_bbox;
+    FT_ULong       uid_base;
+
+    FT_Int         num_xuid;
+    FT_ULong       xuid[16];
+
+
+    FT_ULong       cidmap_offset;
+    FT_Int         fd_bytes;
+    FT_Int         gd_bytes;
+    FT_ULong       cid_count;
+
+    FT_Int         num_dicts;
+    CID_FontDict*  font_dicts;
+
+    FT_ULong       data_offset;
+
+  } CID_Info;
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __T1TABLES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/ttnameid.h b/libraries/freetype-2.0.5/include/freetype/ttnameid.h
new file mode 100644 (file)
index 0000000..10ea50d
--- /dev/null
@@ -0,0 +1,814 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttnameid.h                                                             */
+/*                                                                         */
+/*    TrueType name ID definitions (specification only).                   */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTNAMEID_H__
+#define __TTNAMEID_H__
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values for the `platform' identifier code in the name        */
+  /* records of the TTF `name' table.                                      */
+  /*                                                                       */
+#define TT_PLATFORM_APPLE_UNICODE  0
+#define TT_PLATFORM_MACINTOSH      1
+#define TT_PLATFORM_ISO            2 /* deprecated */
+#define TT_PLATFORM_MICROSOFT      3
+#define TT_PLATFORM_CUSTOM         4
+
+  /* artificial values defined ad-hoc by FreeType */
+#define TT_PLATFORM_ADOBE          7
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the platform specific encoding identifier field in */
+  /* the name records of the TTF `name' table if the `platform' identifier */
+  /* code is TT_PLATFORM_APPLE_UNICODE.                                    */
+  /*                                                                       */
+#define TT_APPLE_ID_DEFAULT      0 /* Unicode 1.0 */
+#define TT_APPLE_ID_UNICODE_1_1  1 /* specify Hangul at U+34xx */
+#define TT_APPLE_ID_ISO_10646    2 /* deprecated */
+#define TT_APPLE_ID_UNICODE_2_0  3 /* or later */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the platform specific encoding identifier field in */
+  /* the name records of the TTF `name' table if the `platform' identifier */
+  /* code is TT_PLATFORM_MACINTOSH.                                        */
+  /*                                                                       */
+#define TT_MAC_ID_ROMAN                 0
+#define TT_MAC_ID_JAPANESE              1
+#define TT_MAC_ID_TRADITIONAL_CHINESE   2
+#define TT_MAC_ID_KOREAN                3
+#define TT_MAC_ID_ARABIC                4
+#define TT_MAC_ID_HEBREW                5
+#define TT_MAC_ID_GREEK                 6
+#define TT_MAC_ID_RUSSIAN               7
+#define TT_MAC_ID_RSYMBOL               8
+#define TT_MAC_ID_DEVANAGARI            9
+#define TT_MAC_ID_GURMUKHI             10
+#define TT_MAC_ID_GUJARATI             11
+#define TT_MAC_ID_ORIYA                12
+#define TT_MAC_ID_BENGALI              13
+#define TT_MAC_ID_TAMIL                14
+#define TT_MAC_ID_TELUGU               15
+#define TT_MAC_ID_KANNADA              16
+#define TT_MAC_ID_MALAYALAM            17
+#define TT_MAC_ID_SINHALESE            18
+#define TT_MAC_ID_BURMESE              19
+#define TT_MAC_ID_KHMER                20
+#define TT_MAC_ID_THAI                 21
+#define TT_MAC_ID_LAOTIAN              22
+#define TT_MAC_ID_GEORGIAN             23
+#define TT_MAC_ID_ARMENIAN             24
+#define TT_MAC_ID_MALDIVIAN            25
+#define TT_MAC_ID_SIMPLIFIED_CHINESE   25
+#define TT_MAC_ID_TIBETAN              26
+#define TT_MAC_ID_MONGOLIAN            27
+#define TT_MAC_ID_GEEZ                 28
+#define TT_MAC_ID_SLAVIC               29
+#define TT_MAC_ID_VIETNAMESE           30
+#define TT_MAC_ID_SINDHI               31
+#define TT_MAC_ID_UNINTERP             32
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the platform specific encoding identifier field in */
+  /* the name records of the TTF `name' table if the `platform' identifier */
+  /* code is TT_PLATFORM_ISO.                                              */
+  /*                                                                       */
+  /* This use is now deprecated.                                           */
+  /*                                                                       */
+#define TT_ISO_ID_7BIT_ASCII  0
+#define TT_ISO_ID_10646       1
+#define TT_ISO_ID_8859_1      2
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* possible values of the platform specific encoding identifier field in */
+  /* the name records of the TTF `name' table if the `platform' identifier */
+  /* code is TT_PLATFORM_MICROSOFT.                                        */
+  /*                                                                       */
+#define TT_MS_ID_SYMBOL_CS    0
+#define TT_MS_ID_UNICODE_CS   1
+#define TT_MS_ID_SJIS         2
+#define TT_MS_ID_GB2312       3
+#define TT_MS_ID_BIG_5        4
+#define TT_MS_ID_WANSUNG      5
+#define TT_MS_ID_JOHAB        6
+#define TT_MS_ID_UCS_4       10
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* possible values of the platform specific encoding identifier field in */
+  /* the name records of the TTF `name' table if the `platform' identifier */
+  /* code is TT_PLATFORM_ADOBE.                                            */
+  /*                                                                       */
+  /* These are artificial values defined ad-hoc by FreeType.               */
+  /*                                                                       */
+#define TT_ADOBE_ID_STANDARD  0
+#define TT_ADOBE_ID_EXPERT    1
+#define TT_ADOBE_ID_CUSTOM    2
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the language identifier field in the name records  */
+  /* of the TTF `name' table if the `platform' identifier code is          */
+  /* TT_PLATFORM_MACINTOSH.                                                */
+  /*                                                                       */
+  /* The canonical source for the Apple assigned Language ID's is at       */
+  /*                                                                       */
+  /*   http://fonts.apple.com/TTRefMan/RM06/Chap6name.html                 */
+  /*                                                                       */
+#define TT_MAC_LANGID_ENGLISH                       0
+#define TT_MAC_LANGID_FRENCH                        1
+#define TT_MAC_LANGID_GERMAN                        2
+#define TT_MAC_LANGID_ITALIAN                       3
+#define TT_MAC_LANGID_DUTCH                         4
+#define TT_MAC_LANGID_SWEDISH                       5
+#define TT_MAC_LANGID_SPANISH                       6
+#define TT_MAC_LANGID_DANISH                        7
+#define TT_MAC_LANGID_PORTUGUESE                    8
+#define TT_MAC_LANGID_NORWEGIAN                     9
+#define TT_MAC_LANGID_HEBREW                       10
+#define TT_MAC_LANGID_JAPANESE                     11
+#define TT_MAC_LANGID_ARABIC                       12
+#define TT_MAC_LANGID_FINNISH                      13
+#define TT_MAC_LANGID_GREEK                        14
+#define TT_MAC_LANGID_ICELANDIC                    15
+#define TT_MAC_LANGID_MALTESE                      16
+#define TT_MAC_LANGID_TURKISH                      17
+#define TT_MAC_LANGID_CROATIAN                     18
+#define TT_MAC_LANGID_CHINESE_TRADITIONAL          19
+#define TT_MAC_LANGID_URDU                         20
+#define TT_MAC_LANGID_HINDI                        21
+#define TT_MAC_LANGID_THAI                         22
+#define TT_MAC_LANGID_KOREAN                       23
+#define TT_MAC_LANGID_LITHUANIAN                   24
+#define TT_MAC_LANGID_POLISH                       25
+#define TT_MAC_LANGID_HUNGARIAN                    26
+#define TT_MAC_LANGID_ESTONIAN                     27
+#define TT_MAC_LANGID_LETTISH                      28
+#define TT_MAC_LANGID_SAAMISK                      29
+#define TT_MAC_LANGID_FAEROESE                     30
+#define TT_MAC_LANGID_FARSI                        31
+#define TT_MAC_LANGID_RUSSIAN                      32
+#define TT_MAC_LANGID_CHINESE_SIMPLIFIED           33
+#define TT_MAC_LANGID_FLEMISH                      34
+#define TT_MAC_LANGID_IRISH                        35
+#define TT_MAC_LANGID_ALBANIAN                     36
+#define TT_MAC_LANGID_ROMANIAN                     37
+#define TT_MAC_LANGID_CZECH                        38
+#define TT_MAC_LANGID_SLOVAK                       39
+#define TT_MAC_LANGID_SLOVENIAN                    40
+#define TT_MAC_LANGID_YIDDISH                      41
+#define TT_MAC_LANGID_SERBIAN                      42
+#define TT_MAC_LANGID_MACEDONIAN                   43
+#define TT_MAC_LANGID_BULGARIAN                    44
+#define TT_MAC_LANGID_UKRAINIAN                    45
+#define TT_MAC_LANGID_BYELORUSSIAN                 46
+#define TT_MAC_LANGID_UZBEK                        47
+#define TT_MAC_LANGID_KAZAKH                       48
+#define TT_MAC_LANGID_AZERBAIJANI                  49
+#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT  49
+#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT    50
+#define TT_MAC_LANGID_ARMENIAN                     51
+#define TT_MAC_LANGID_GEORGIAN                     52
+#define TT_MAC_LANGID_MOLDAVIAN                    53
+#define TT_MAC_LANGID_KIRGHIZ                      54
+#define TT_MAC_LANGID_TAJIKI                       55
+#define TT_MAC_LANGID_TURKMEN                      56
+#define TT_MAC_LANGID_MONGOLIAN                    57
+#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT   57
+#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT    58
+#define TT_MAC_LANGID_PASHTO                       59
+#define TT_MAC_LANGID_KURDISH                      60
+#define TT_MAC_LANGID_KASHMIRI                     61
+#define TT_MAC_LANGID_SINDHI                       62
+#define TT_MAC_LANGID_TIBETAN                      63
+#define TT_MAC_LANGID_NEPALI                       64
+#define TT_MAC_LANGID_SANSKRIT                     65
+#define TT_MAC_LANGID_MARATHI                      66
+#define TT_MAC_LANGID_BENGALI                      67
+#define TT_MAC_LANGID_ASSAMESE                     68
+#define TT_MAC_LANGID_GUJARATI                     69
+#define TT_MAC_LANGID_PUNJABI                      70
+#define TT_MAC_LANGID_ORIYA                        71
+#define TT_MAC_LANGID_MALAYALAM                    72
+#define TT_MAC_LANGID_KANNADA                      73
+#define TT_MAC_LANGID_TAMIL                        74
+#define TT_MAC_LANGID_TELUGU                       75
+#define TT_MAC_LANGID_SINHALESE                    76
+#define TT_MAC_LANGID_BURMESE                      77
+#define TT_MAC_LANGID_KHMER                        78
+#define TT_MAC_LANGID_LAO                          79
+#define TT_MAC_LANGID_VIETNAMESE                   80
+#define TT_MAC_LANGID_INDONESIAN                   81
+#define TT_MAC_LANGID_TAGALOG                      82
+#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT           83
+#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT          84
+#define TT_MAC_LANGID_AMHARIC                      85
+#define TT_MAC_LANGID_TIGRINYA                     86
+#define TT_MAC_LANGID_GALLA                        87
+#define TT_MAC_LANGID_SOMALI                       88
+#define TT_MAC_LANGID_SWAHILI                      89
+#define TT_MAC_LANGID_RUANDA                       90
+#define TT_MAC_LANGID_RUNDI                        91
+#define TT_MAC_LANGID_CHEWA                        92
+#define TT_MAC_LANGID_MALAGASY                     93
+#define TT_MAC_LANGID_ESPERANTO                    94
+#define TT_MAC_LANGID_WELSH                       128
+#define TT_MAC_LANGID_BASQUE                      129
+#define TT_MAC_LANGID_CATALAN                     130
+#define TT_MAC_LANGID_LATIN                       131
+#define TT_MAC_LANGID_QUECHUA                     132
+#define TT_MAC_LANGID_GUARANI                     133
+#define TT_MAC_LANGID_AYMARA                      134
+#define TT_MAC_LANGID_TATAR                       135
+#define TT_MAC_LANGID_UIGHUR                      136
+#define TT_MAC_LANGID_DZONGKHA                    137
+#define TT_MAC_LANGID_JAVANESE                    138
+#define TT_MAC_LANGID_SUNDANESE                   139
+
+
+#if 0  /* these seem to be errors that have been dropped */
+
+#define TT_MAC_LANGID_SCOTTISH_GAELIC             140
+#define TT_MAC_LANGID_IRISH_GAELIC                141
+
+#endif
+
+
+  /* The following codes are new as of 2000-03-10 */
+#define TT_MAC_LANGID_GALICIAN                    140
+#define TT_MAC_LANGID_AFRIKAANS                   141
+#define TT_MAC_LANGID_BRETON                      142
+#define TT_MAC_LANGID_INUKTITUT                   143
+#define TT_MAC_LANGID_SCOTTISH_GAELIC             144
+#define TT_MAC_LANGID_MANX_GAELIC                 145
+#define TT_MAC_LANGID_IRISH_GAELIC                146
+#define TT_MAC_LANGID_TONGAN                      147
+#define TT_MAC_LANGID_GREEK_POLYTONIC             148
+#define TT_MAC_LANGID_GREELANDIC                  149
+#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT    150
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the language identifier field in the name records  */
+  /* of the TTF `name' table if the `platform' identifier code is          */
+  /* TT_PLATFORM_MICROSOFT.                                                */
+  /*                                                                       */
+  /* The canonical source for the MS assigned LCID's is at                 */
+  /*                                                                       */
+  /*   http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt              */
+  /*                                                                       */
+#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA               0x0401
+#define TT_MS_LANGID_ARABIC_IRAQ                       0x0801
+#define TT_MS_LANGID_ARABIC_EGYPT                      0x0c01
+#define TT_MS_LANGID_ARABIC_LIBYA                      0x1001
+#define TT_MS_LANGID_ARABIC_ALGERIA                    0x1401
+#define TT_MS_LANGID_ARABIC_MOROCCO                    0x1801
+#define TT_MS_LANGID_ARABIC_TUNISIA                    0x1c01
+#define TT_MS_LANGID_ARABIC_OMAN                       0x2001
+#define TT_MS_LANGID_ARABIC_YEMEN                      0x2401
+#define TT_MS_LANGID_ARABIC_SYRIA                      0x2801
+#define TT_MS_LANGID_ARABIC_JORDAN                     0x2c01
+#define TT_MS_LANGID_ARABIC_LEBANON                    0x3001
+#define TT_MS_LANGID_ARABIC_KUWAIT                     0x3401
+#define TT_MS_LANGID_ARABIC_UAE                        0x3801
+#define TT_MS_LANGID_ARABIC_BAHRAIN                    0x3c01
+#define TT_MS_LANGID_ARABIC_QATAR                      0x4001
+#define TT_MS_LANGID_BULGARIAN_BULGARIA                0x0402
+#define TT_MS_LANGID_CATALAN_SPAIN                     0x0403
+#define TT_MS_LANGID_CHINESE_TAIWAN                    0x0404
+#define TT_MS_LANGID_CHINESE_PRC                       0x0804
+#define TT_MS_LANGID_CHINESE_HONG_KONG                 0x0c04
+#define TT_MS_LANGID_CHINESE_SINGAPORE                 0x1004
+
+#if 1  /* this used to be this value (and it still is in many places) */
+#define TT_MS_LANGID_CHINESE_MACAU                     0x1404
+#else  /* but beware, Microsoft may change its mind...
+          the most recent Word reference has the following:  :-( */
+#define TT_MS_LANGID_CHINESE_MACAU          TT_MS_LANGID_CHINESE_HONG_KONG
+#endif
+
+#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC              0x0405
+#define TT_MS_LANGID_DANISH_DENMARK                    0x0406
+#define TT_MS_LANGID_GERMAN_GERMANY                    0x0407
+#define TT_MS_LANGID_GERMAN_SWITZERLAND                0x0807
+#define TT_MS_LANGID_GERMAN_AUSTRIA                    0x0c07
+#define TT_MS_LANGID_GERMAN_LUXEMBOURG                 0x1007
+#define TT_MS_LANGID_GERMAN_LIECHTENSTEI               0x1407
+#define TT_MS_LANGID_GREEK_GREECE                      0x0408
+#define TT_MS_LANGID_ENGLISH_UNITED_STATES             0x0409
+#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM            0x0809
+#define TT_MS_LANGID_ENGLISH_AUSTRALIA                 0x0c09
+#define TT_MS_LANGID_ENGLISH_CANADA                    0x1009
+#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND               0x1409
+#define TT_MS_LANGID_ENGLISH_IRELAND                   0x1809
+#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA              0x1c09
+#define TT_MS_LANGID_ENGLISH_JAMAICA                   0x2009
+#define TT_MS_LANGID_ENGLISH_CARIBBEAN                 0x2409
+#define TT_MS_LANGID_ENGLISH_BELIZE                    0x2809
+#define TT_MS_LANGID_ENGLISH_TRINIDAD                  0x2c09
+#define TT_MS_LANGID_ENGLISH_ZIMBABWE                  0x3009
+#define TT_MS_LANGID_ENGLISH_PHILIPPINES               0x3409
+#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT    0x040a
+#define TT_MS_LANGID_SPANISH_MEXICO                    0x080a
+#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT  0x0c0a
+#define TT_MS_LANGID_SPANISH_GUATEMALA                 0x100a
+#define TT_MS_LANGID_SPANISH_COSTA_RICA                0x140a
+#define TT_MS_LANGID_SPANISH_PANAMA                    0x180a
+#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC        0x1c0a
+#define TT_MS_LANGID_SPANISH_VENEZUELA                 0x200a
+#define TT_MS_LANGID_SPANISH_COLOMBIA                  0x240a
+#define TT_MS_LANGID_SPANISH_PERU                      0x280a
+#define TT_MS_LANGID_SPANISH_ARGENTINA                 0x2c0a
+#define TT_MS_LANGID_SPANISH_ECUADOR                   0x300a
+#define TT_MS_LANGID_SPANISH_CHILE                     0x340a
+#define TT_MS_LANGID_SPANISH_URUGUAY                   0x380a
+#define TT_MS_LANGID_SPANISH_PARAGUAY                  0x3c0a
+#define TT_MS_LANGID_SPANISH_BOLIVIA                   0x400a
+#define TT_MS_LANGID_SPANISH_EL_SALVADOR               0x440a
+#define TT_MS_LANGID_SPANISH_HONDURAS                  0x480a
+#define TT_MS_LANGID_SPANISH_NICARAGUA                 0x4c0a
+#define TT_MS_LANGID_SPANISH_PUERTO_RICO               0x500a
+#define TT_MS_LANGID_FINNISH_FINLAND                   0x040b
+#define TT_MS_LANGID_FRENCH_FRANCE                     0x040c
+#define TT_MS_LANGID_FRENCH_BELGIUM                    0x080c
+#define TT_MS_LANGID_FRENCH_CANADA                     0x0c0c
+#define TT_MS_LANGID_FRENCH_SWITZERLAND                0x100c
+#define TT_MS_LANGID_FRENCH_LUXEMBOURG                 0x140c
+#define TT_MS_LANGID_FRENCH_MONACO                     0x180c
+#define TT_MS_LANGID_HEBREW_ISRAEL                     0x040d
+#define TT_MS_LANGID_HUNGARIAN_HUNGARY                 0x040e
+#define TT_MS_LANGID_ICELANDIC_ICELAND                 0x040f
+#define TT_MS_LANGID_ITALIAN_ITALY                     0x0410
+#define TT_MS_LANGID_ITALIAN_SWITZERLAND               0x0810
+#define TT_MS_LANGID_JAPANESE_JAPAN                    0x0411
+#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA     0x0412
+#define TT_MS_LANGID_KOREAN_JOHAB_KOREA                0x0812
+#define TT_MS_LANGID_DUTCH_NETHERLANDS                 0x0413
+#define TT_MS_LANGID_DUTCH_BELGIUM                     0x0813
+#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL           0x0414
+#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK          0x0814
+#define TT_MS_LANGID_POLISH_POLAND                     0x0415
+#define TT_MS_LANGID_PORTUGUESE_BRAZIL                 0x0416
+#define TT_MS_LANGID_PORTUGUESE_PORTUGAL               0x0816
+#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND        0x0417
+#define TT_MS_LANGID_ROMANIAN_ROMANIA                  0x0418
+#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA                0x0818
+#define TT_MS_LANGID_RUSSIAN_RUSSIA                    0x0419
+#define TT_MS_LANGID_RUSSIAN_MOLDAVIA                  0x0819
+#define TT_MS_LANGID_CROATIAN_CROATIA                  0x041a
+#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN              0x081a
+#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC           0x0c1a
+#define TT_MS_LANGID_SLOVAK_SLOVAKIA                   0x041b
+#define TT_MS_LANGID_ALBANIAN_ALBANIA                  0x041c
+#define TT_MS_LANGID_SWEDISH_SWEDEN                    0x041d
+#define TT_MS_LANGID_SWEDISH_FINLAND                   0x081d
+#define TT_MS_LANGID_THAI_THAILAND                     0x041e
+#define TT_MS_LANGID_TURKISH_TURKEY                    0x041f
+#define TT_MS_LANGID_URDU_PAKISTAN                     0x0420
+#define TT_MS_LANGID_INDONESIAN_INDONESIA              0x0421
+#define TT_MS_LANGID_UKRAINIAN_UKRAINE                 0x0422
+#define TT_MS_LANGID_BELARUSIAN_BELARUS                0x0423
+#define TT_MS_LANGID_SLOVENE_SLOVENIA                  0x0424
+#define TT_MS_LANGID_ESTONIAN_ESTONIA                  0x0425
+#define TT_MS_LANGID_LATVIAN_LATVIA                    0x0426
+#define TT_MS_LANGID_LITHUANIAN_LITHUANIA              0x0427
+#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA      0x0827
+
+#if 0  /* this seems to be an error that have been dropped */
+#define TT_MS_LANGID_MAORI_NEW_ZEALAND                 0x0428
+#endif
+
+#define TT_MS_LANGID_FARSI_IRAN                        0x0429
+#define TT_MS_LANGID_VIETNAMESE_VIET_NAM               0x042a
+#define TT_MS_LANGID_ARMENIAN_ARMENIA                  0x042b
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN            0x042c
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC         0x082c
+#define TT_MS_LANGID_BASQUE_SPAIN                      0x042d
+#define TT_MS_LANGID_SORBIAN_GERMANY                   0x042e
+#define TT_MS_LANGID_MACEDONIAN_MACEDONIA              0x042f
+#define TT_MS_LANGID_SUTU_SOUTH_AFRICA                 0x0430
+#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA               0x0431
+#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA               0x0432
+#define TT_MS_LANGID_VENDA_SOUTH_AFRICA                0x0433
+#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA                0x0434
+#define TT_MS_LANGID_ZULU_SOUTH_AFRICA                 0x0435
+#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA            0x0436
+#define TT_MS_LANGID_GEORGIAN_GEORGIA                  0x0437
+#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS           0x0438
+#define TT_MS_LANGID_HINDI_INDIA                       0x0439
+#define TT_MS_LANGID_MALTESE_MALTA                     0x043a
+#define TT_MS_LANGID_SAAMI_LAPONIA                     0x043b
+
+#if 0  /* this seems to be a previous invertion */
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND              0x043c
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM    0x083c
+#else
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM    0x083c
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND              0x043c
+#endif
+
+#define TT_MS_LANGID_MALAY_MALAYSIA                    0x043e
+#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM           0x083e
+#define TT_MS_LANGID_KAZAK_KAZAKSTAN                   0x043f
+#define TT_MS_LANGID_SWAHILI_KENYA                     0x0441
+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN            0x0443
+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC         0x0843
+#define TT_MS_LANGID_TATAR_TATARSTAN                   0x0444
+#define TT_MS_LANGID_BENGALI_INDIA                     0x0445
+#define TT_MS_LANGID_PUNJABI_INDIA                     0x0446
+#define TT_MS_LANGID_GUJARATI_INDIA                    0x0447
+#define TT_MS_LANGID_ORIYA_INDIA                       0x0448
+#define TT_MS_LANGID_TAMIL_INDIA                       0x0449
+#define TT_MS_LANGID_TELUGU_INDIA                      0x044a
+#define TT_MS_LANGID_KANNADA_INDIA                     0x044b
+#define TT_MS_LANGID_MALAYALAM_INDIA                   0x044c
+#define TT_MS_LANGID_ASSAMESE_INDIA                    0x044d
+#define TT_MS_LANGID_MARATHI_INDIA                     0x044e
+#define TT_MS_LANGID_SANSKRIT_INDIA                    0x044f
+#define TT_MS_LANGID_KONKANI_INDIA                     0x0457
+
+/* new as of 2001-01-01 */
+#define TT_MS_LANGID_ARABIC_GENERAL                    0x0001
+#define TT_MS_LANGID_CHINESE_GENERAL                   0x0004
+#define TT_MS_LANGID_ENGLISH_GENERAL                   0x0009
+#define TT_MS_LANGID_FRENCH_WEST_INDIES                0x1c0c
+#define TT_MS_LANGID_FRENCH_REUNION                    0x200c
+#define TT_MS_LANGID_FRENCH_CONGO                      0x240c
+ /* which was formerly: */
+#define TT_MS_LANGID_FRENCH_ZAIRE           TT_MS_LANGID_FRENCH_CONGO
+
+#define TT_MS_LANGID_FRENCH_SENEGAL                    0x280c
+#define TT_MS_LANGID_FRENCH_CAMEROON                   0x2c0c
+#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE              0x300c
+#define TT_MS_LANGID_FRENCH_MALI                       0x340c
+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA        0x101a
+#define TT_MS_LANGID_URDU_INDIA                        0x0820
+#define TT_MS_LANGID_TAJIK_TAJIKISTAN                  0x0428
+#define TT_MS_LANGID_YIDDISH_GERMANY                   0x043d
+#define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN               0x0440
+ /* alias declared in Windows 2000 */
+#define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \
+                                          TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN
+
+#define TT_MS_LANGID_TURKMEN_TURKMENISTAN              0x0442
+#define TT_MS_LANGID_MONGOLIAN_MONGOLIA                0x0450
+#define TT_MS_LANGID_TIBETAN_BHUTAN                    0x0451
+#define TT_MS_LANGID_WELSH_WALES                       0x0452
+#define TT_MS_LANGID_KHMER_CAMBODIA                    0x0453
+#define TT_MS_LANGID_LAO_LAOS                          0x0454
+#define TT_MS_LANGID_BURMESE_MYANMAR                   0x0455
+#define TT_MS_LANGID_GALICIAN_SPAIN                    0x0456
+#define TT_MS_LANGID_MANIPURI_INDIA                    0x0458
+#define TT_MS_LANGID_SINDHI_INDIA                      0x0459
+#define TT_MS_LANGID_KASHMIRI_PAKISTAN                 0x0460
+#define TT_MS_LANGID_KASHMIRI_INDIA                    0x0860
+#define TT_MS_LANGID_NEPALI_NEPAL                      0x0461
+#define TT_MS_LANGID_NEPALI_INDIA                      0x0861
+#define TT_MS_LANGID_FRISIAN_NETHERLANDS               0x0462
+
+/* new as of 2001-03-01 (from Office Xp) */
+#define TT_MS_LANGID_SYRIAC_SYRIA                      0x045a
+#define TT_MS_LANGID_SINHALESE_SRI_LANKA               0x045b
+#define TT_MS_LANGID_PASHTO_AFGHANISTAN                0x0463
+#define TT_MS_LANGID_ENGLISH_HONG_KONG                 0x3c09
+#define TT_MS_LANGID_ENGLISH_INDIA                     0x4009
+#define TT_MS_LANGID_ENGLISH_MALAYSIA                  0x4409
+#define TT_MS_LANGID_ENGLISH_SINGAPORE                 0x4809
+#define TT_MS_LANGID_CHEROKEE_UNITED_STATES            0x045c
+#define TT_MS_LANGID_INUKTITUT_CANADA                  0x045d
+#define TT_MS_LANGID_AMHARIC_ETHIOPIA                  0x045e
+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO                 0x045f
+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN           0x085f
+#define TT_MS_LANGID_FILIPINO_PHILIPPINES              0x0464
+#define TT_MS_LANGID_DHIVEHI_MALDIVES                  0x0465
+ /* alias declared in Windows 2000 */
+#define TT_MS_LANGID_DIVEHI_MALDIVES      TT_MS_LANGID_DHIVEHI_MALDIVES
+ /* language codes from 0x0466 to 0x0471 are unknown. */
+#define TT_MS_LANGID_OROMO_ETHIOPIA                    0x0472
+#define TT_MS_LANGID_TIGRIGNA_ETHIOPIA                 0x0473
+#define TT_MS_LANGID_TIGRIGNA_ERYTHREA                 0x0873
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Possible values of the `name' identifier field in the name records of */
+  /* the TTF `name' table.  These values are platform independent.         */
+  /*                                                                       */
+#define TT_NAME_ID_COPYRIGHT            0
+#define TT_NAME_ID_FONT_FAMILY          1
+#define TT_NAME_ID_FONT_SUBFAMILY       2
+#define TT_NAME_ID_UNIQUE_ID            3
+#define TT_NAME_ID_FULL_NAME            4
+#define TT_NAME_ID_VERSION_STRING       5
+#define TT_NAME_ID_PS_NAME              6
+#define TT_NAME_ID_TRADEMARK            7
+
+/* the following values are from the OpenType spec */
+#define TT_NAME_ID_MANUFACTURER         8
+#define TT_NAME_ID_DESIGNER             9
+#define TT_NAME_ID_DESCRIPTION          10
+#define TT_NAME_ID_VENDOR_URL           11
+#define TT_NAME_ID_DESIGNER_URL         12
+#define TT_NAME_ID_LICENSE              13
+#define TT_NAME_ID_LICENSE_URL          14
+/* number 15 is reserved */
+#define TT_NAME_ID_PREFERRED_FAMILY     16
+#define TT_NAME_ID_PREFERRED_SUBFAMILY  17
+#define TT_NAME_ID_MAC_FULL_NAME        18
+
+/* The following code is new as of 2000-01-21 */
+#define TT_NAME_ID_SAMPLE_TEXT          19
+
+/* This is new in OpenType 1.3 */
+#define TT_NAME_ID_CID_FINDFONT_NAME    20
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table.     */
+  /*                                                                       */
+  /* Updated 02-Jul-2000.                                                  */
+  /*                                                                       */
+
+  /* General Scripts Area */
+
+  /* Bit  0   Basic Latin */
+#define TT_UCR_BASIC_LATIN                     (1L <<  0) /* U+0020-U+007E */
+  /* Bit  1   C1 Controls and Latin-1 Supplement */
+#define TT_UCR_LATIN1_SUPPLEMENT               (1L <<  1) /* U+0080-U+00FF */
+  /* Bit  2   Latin Extended-A */
+#define TT_UCR_LATIN_EXTENDED_A                (1L <<  2) /* U+0100-U+017F */
+  /* Bit  3   Latin Extended-B */
+#define TT_UCR_LATIN_EXTENDED_B                (1L <<  3) /* U+0180-U+024F */
+  /* Bit  4   IPA Extensions */
+#define TT_UCR_IPA_EXTENSIONS                  (1L <<  4) /* U+0250-U+02AF */
+  /* Bit  5   Spacing Modifier Letters */
+#define TT_UCR_SPACING_MODIFIER                (1L <<  5) /* U+02B0-U+02FF */
+  /* Bit  6   Combining Diacritical Marks */
+#define TT_UCR_COMBINING_DIACRITICS            (1L <<  6) /* U+0300-U+036F */
+  /* Bit  7   Greek and Coptic */
+#define TT_UCR_GREEK                           (1L <<  7) /* U+0370-U+03FF */
+  /* Bit  8 is reserved (was: Greek Symbols and Coptic) */
+  /* Bit  9   Cyrillic */
+#define TT_UCR_CYRILLIC                        (1L <<  9) /* U+0400-U+04FF */
+  /* Bit 10   Armenian */
+#define TT_UCR_ARMENIAN                        (1L << 10) /* U+0530-U+058F */
+  /* Bit 11   Hebrew */
+#define TT_UCR_HEBREW                          (1L << 11) /* U+0590-U+05FF */
+  /* Bit 12 is reserved (was: Hebrew Extended) */
+  /* Bit 13   Arabic */
+#define TT_UCR_ARABIC                          (1L << 13) /* U+0600-U+06FF */
+  /* Bit 14 is reserved (was: Arabic Extended) */
+  /* Bit 15   Devanagari */
+#define TT_UCR_DEVANAGARI                      (1L << 15) /* U+0900-U+097F */
+  /* Bit 16   Bengali */
+#define TT_UCR_BENGALI                         (1L << 16) /* U+0980-U+09FF */
+  /* Bit 17   Gurmukhi */
+#define TT_UCR_GURMUKHI                        (1L << 17) /* U+0A00-U+0A7F */
+  /* Bit 18   Gujarati */
+#define TT_UCR_GUJARATI                        (1L << 18) /* U+0A80-U+0AFF */
+  /* Bit 19   Oriya */
+#define TT_UCR_ORIYA                           (1L << 19) /* U+0B00-U+0B7F */
+  /* Bit 20   Tamil */
+#define TT_UCR_TAMIL                           (1L << 20) /* U+0B80-U+0BFF */
+  /* Bit 21   Telugu */
+#define TT_UCR_TELUGU                          (1L << 21) /* U+0C00-U+0C7F */
+  /* Bit 22   Kannada */
+#define TT_UCR_KANNADA                         (1L << 22) /* U+0C80-U+0CFF */
+  /* Bit 23   Malayalam */
+#define TT_UCR_MALAYALAM                       (1L << 23) /* U+0D00-U+0D7F */
+  /* Bit 24   Thai */
+#define TT_UCR_THAI                            (1L << 24) /* U+0E00-U+0E7F */
+  /* Bit 25   Lao */
+#define TT_UCR_LAO                             (1L << 25) /* U+0E80-U+0EFF */
+  /* Bit 26   Georgian */
+#define TT_UCR_GEORGIAN                        (1L << 26) /* U+10A0-U+10FF */
+  /* Bit 27 is reserved (was Georgian Extended) */
+  /* Bit 28   Hangul Jamo */
+#define TT_UCR_HANGUL_JAMO                     (1L << 28) /* U+1100-U+11FF */
+  /* Bit 29   Latin Extended Additional */
+#define TT_UCR_LATIN_EXTENDED_ADDITIONAL       (1L << 29) /* U+1E00-U+1EFF */
+  /* Bit 30   Greek Extended */
+#define TT_UCR_GREEK_EXTENDED                  (1L << 30) /* U+1F00-U+1FFF */
+
+  /* Symbols Area */
+
+  /* Bit 31   General Punctuation */
+#define TT_UCR_GENERAL_PUNCTUATION             (1L << 31) /* U+2000-U+206F */
+  /* Bit 32   Superscripts And Subscripts */
+#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS         (1L <<  0) /* U+2070-U+209F */
+  /* Bit 33   Currency Symbols */
+#define TT_UCR_CURRENCY_SYMBOLS                (1L <<  1) /* U+20A0-U+20CF */
+  /* Bit 34   Combining Diacritical Marks For Symbols */
+#define TT_UCR_COMBINING_DIACRITICS_SYMB       (1L <<  2) /* U+20D0-U+20FF */
+  /* Bit 35   Letterlike Symbols */
+#define TT_UCR_LETTERLIKE_SYMBOLS              (1L <<  3) /* U+2100-U+214F */
+  /* Bit 36   Number Forms */
+#define TT_UCR_NUMBER_FORMS                    (1L <<  4) /* U+2150-U+218F */
+  /* Bit 37   Arrows */
+#define TT_UCR_ARROWS                          (1L <<  5) /* U+2190-U+21FF */
+  /* Bit 38   Mathematical Operators */
+#define TT_UCR_MATHEMATICAL_OPERATORS          (1L <<  6) /* U+2200-U+22FF */
+  /* Bit 39 Miscellaneous Technical */
+#define TT_UCR_MISCELLANEOUS_TECHNICAL         (1L <<  7) /* U+2300-U+23FF */
+  /* Bit 40   Control Pictures */
+#define TT_UCR_CONTROL_PICTURES                (1L <<  8) /* U+2400-U+243F */
+  /* Bit 41   Optical Character Recognition */
+#define TT_UCR_OCR                             (1L <<  9) /* U+2440-U+245F */
+  /* Bit 42   Enclosed Alphanumerics */
+#define TT_UCR_ENCLOSED_ALPHANUMERICS          (1L << 10) /* U+2460-U+24FF */
+  /* Bit 43   Box Drawing */
+#define TT_UCR_BOX_DRAWING                     (1L << 11) /* U+2500-U+257F */
+  /* Bit 44   Block Elements */
+#define TT_UCR_BLOCK_ELEMENTS                  (1L << 12) /* U+2580-U+259F */
+  /* Bit 45   Geometric Shapes */
+#define TT_UCR_GEOMETRIC_SHAPES                (1L << 13) /* U+25A0-U+25FF */
+  /* Bit 46   Miscellaneous Symbols */
+#define TT_UCR_MISCELLANEOUS_SYMBOLS           (1L << 14) /* U+2600-U+26FF */
+  /* Bit 47   Dingbats */
+#define TT_UCR_DINGBATS                        (1L << 15) /* U+2700-U+27BF */
+
+  /* CJK Phonetics and Symbols Area */
+
+  /* Bit 48   CJK Symbols and Punctuation */
+#define TT_UCR_CJK_SYMBOLS                     (1L << 16) /* U+3000-U+303F */
+  /* Bit 49   Hiragana */
+#define TT_UCR_HIRAGANA                        (1L << 17) /* U+3040-U+309F */
+  /* Bit 50   Katakana */
+#define TT_UCR_KATAKANA                        (1L << 18) /* U+30A0-U+30FF */
+  /* Bit 51   Bopomofo          + */
+  /*          Bopomofo Extended   */
+#define TT_UCR_BOPOMOFO                        (1L << 19) /* U+3100-U+312F */
+                                                          /* U+31A0-U+31BF */
+  /* Bit 52   Hangul Compatibility Jamo */
+#define TT_UCR_HANGUL_COMPATIBILITY_JAMO       (1L << 20) /* U+3130-U+318F */
+  /* Bit 53   Kanbun */
+#define TT_UCR_CJK_MISC                        (1L << 21) /* U+3190-U+319F */
+#define TT_UCR_KANBUN  TT_UCR_CJK_MISC
+  /* Bit 54   Enclosed CJK Letters and Months */
+#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS     (1L << 22) /* U+3200-U+32FF */
+  /* Bit 55   CJK Compatibility */
+#define TT_UCR_CJK_COMPATIBILITY               (1L << 23) /* U+3300-U+33FF */
+
+  /* Hangul Syllables Area */
+
+  /* Bit 56   Hangul */
+#define TT_UCR_HANGUL                          (1L << 24) /* U+AC00-U+D7A3 */
+
+  /* Surrogates Area */
+
+  /* Bit 57   High Surrogates             + */
+  /*          High Private Use Surrogates + */
+  /*          Low Surrogates                */
+#define TT_UCR_SURROGATES                      (1L << 25) /* U+D800-U+DB7F */
+                                                          /* U+DB80-U+DBFF */
+                                                          /* U+DC00-U+DFFF */
+  /* Bit 58 is reserved for Unicode SubRanges */
+
+  /* CJK Ideographs Area */
+
+  /* Bit 59   CJK Unified Ideographs             + */
+  /*          CJK Radicals Supplement            + */
+  /*          Kangxi Radicals                    + */
+  /*          Ideographic Description Characters + */
+  /*          CJK Unified Ideographs Extension A   */
+#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS          (1L << 27) /* U+4E00-U+9FFF */
+                                                          /* U+2E80-U+2EFF */
+                                                          /* U+2F00-U+2FDF */
+                                                          /* U+2FF0-U+2FFF */
+                                                          /* U+3400-U+4DB5 */
+
+  /* Private Use Area */
+
+  /* Bit 60   Private Use */
+#define TT_UCR_PRIVATE_USE                     (1L << 28) /* U+E000-U+F8FF */
+
+  /* Compatibility Area and Specials */
+
+  /* Bit 61   CJK Compatibility Ideographs */
+#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS    (1L << 29) /* U+F900-U+FAFF */
+  /* Bit 62   Alphabetic Presentation Forms */
+#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS   (1L << 30) /* U+FB00-U+FB4F */
+  /* Bit 63   Arabic Presentation Forms-A */
+#define TT_UCR_ARABIC_PRESENTATIONS_A          (1L << 31) /* U+FB50-U+FDFF */
+  /* Bit 64   Combining Half Marks */
+#define TT_UCR_COMBINING_HALF_MARKS            (1L <<  0) /* U+FE20-U+FE2F */
+  /* Bit 65   CJK Compatibility Forms */
+#define TT_UCR_CJK_COMPATIBILITY_FORMS         (1L <<  1) /* U+FE30-U+FE4F */
+  /* Bit 66   Small Form Variants */
+#define TT_UCR_SMALL_FORM_VARIANTS             (1L <<  2) /* U+FE50-U+FE6F */
+  /* Bit 67   Arabic Presentation Forms-B */
+#define TT_UCR_ARABIC_PRESENTATIONS_B          (1L <<  3) /* U+FE70-U+FEFE */
+  /* Bit 68   Halfwidth and Fullwidth Forms */
+#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS       (1L <<  4) /* U+FF00-U+FFEF */
+  /* Bit 69   Specials */
+#define TT_UCR_SPECIALS                        (1L <<  5) /* U+FFF0-U+FFFD */
+  /* Bit 70   Tibetan */
+#define TT_UCR_TIBETAN                         (1L <<  6) /* U+0F00-U+0FFF */
+  /* Bit 71   Syriac */
+#define TT_UCR_SYRIAC                          (1L <<  7) /* U+0700-U+074F */
+  /* Bit 72   Thaana */
+#define TT_UCR_THAANA                          (1L <<  8) /* U+0780-U+07BF */
+  /* Bit 73   Sinhala */
+#define TT_UCR_SINHALA                         (1L <<  9) /* U+0D80-U+0DFF */
+  /* Bit 74   Myanmar */
+#define TT_UCR_MYANMAR                         (1L << 10) /* U+1000-U+109F */
+  /* Bit 75   Ethiopic */
+#define TT_UCR_ETHIOPIC                        (1L << 11) /* U+1200-U+137F */
+  /* Bit 76   Cherokee */
+#define TT_UCR_CHEROKEE                        (1L << 12) /* U+13A0-U+13FF */
+  /* Bit 77   Unified Canadian Aboriginal Syllabics */
+#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS   (1L << 13) /* U+1400-U+167F */
+  /* Bit 78   Ogham */
+#define TT_UCR_OGHAM                           (1L << 14) /* U+1680-U+169F */
+  /* Bit 79   Runic */
+#define TT_UCR_RUNIC                           (1L << 15) /* U+16A0-U+16FF */
+  /* Bit 80   Khmer */
+#define TT_UCR_KHMER                           (1L << 16) /* U+1780-U+17FF */
+  /* Bit 81   Mongolian */
+#define TT_UCR_MONGOLIAN                       (1L << 17) /* U+1800-U+18AF */
+  /* Bit 82   Braille Patterns */
+#define TT_UCR_BRAILLE                         (1L << 18) /* U+2800-U+28FF */
+  /* Bit 83   Yi Syllables + */
+  /*          Yi Radicals    */
+#define TT_UCR_YI                              (1L << 19) /* U+A000-U+A48F */
+                                                          /* U+A490-U+A4CF */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Some compilers have a very limited length of identifiers.             */
+  /*                                                                       */
+#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ )
+#define HAVE_LIMIT_ON_IDENTS
+#endif
+
+
+#ifndef HAVE_LIMIT_ON_IDENTS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Here some alias #defines in order to be clearer.                      */
+  /*                                                                       */
+  /* These are not always #defined to stay within the 31 character limit   */
+  /* which some compilers have.                                            */
+  /*                                                                       */
+  /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern  */
+  /* Borland compilers (read: from BC++ 3.1 on) can increase this limit.   */
+  /* If you get a warning with such a compiler, use the -i40 switch.       */
+  /*                                                                       */
+#define TT_UCR_ARABIC_PRESENTATION_FORMS_A      \
+         TT_UCR_ARABIC_PRESENTATIONS_A
+#define TT_UCR_ARABIC_PRESENTATION_FORMS_B      \
+         TT_UCR_ARABIC_PRESENTATIONS_B
+
+#define TT_UCR_COMBINING_DIACRITICAL_MARKS      \
+         TT_UCR_COMBINING_DIACRITICS
+#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \
+         TT_UCR_COMBINING_DIACRITICS_SYMB
+
+
+#endif /* !HAVE_LIMIT_ON_IDENTS */
+
+
+FT_END_HEADER
+
+#endif /* __TTNAMEID_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/tttables.h b/libraries/freetype-2.0.5/include/freetype/tttables.h
new file mode 100644 (file)
index 0000000..d638a21
--- /dev/null
@@ -0,0 +1,605 @@
+/***************************************************************************/
+/*                                                                         */
+/*  tttables.h                                                             */
+/*                                                                         */
+/*    Basic SFNT/TrueType tables definitions and interface                 */
+/*    (specification only).                                                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTTABLES_H__
+#define __TTTABLES_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    truetype_tables                                                    */
+  /*                                                                       */
+  /* <Title>                                                               */
+  /*    TrueType Tables                                                    */
+  /*                                                                       */
+  /* <Abstract>                                                            */
+  /*    TrueType-specific table types and functions.                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This section contains the definition of TrueType-specific tables   */
+  /*    as well as some routines used to access and process them.          */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Header                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType font header table.  All       */
+  /*    fields follow the TrueType specification.                          */
+  /*                                                                       */
+  typedef struct  TT_Header_
+  {
+    FT_Fixed   Table_Version;
+    FT_Fixed   Font_Revision;
+
+    FT_Long    CheckSum_Adjust;
+    FT_Long    Magic_Number;
+
+    FT_UShort  Flags;
+    FT_UShort  Units_Per_EM;
+
+    FT_Long    Created [2];
+    FT_Long    Modified[2];
+
+    FT_Short   xMin;
+    FT_Short   yMin;
+    FT_Short   xMax;
+    FT_Short   yMax;
+
+    FT_UShort  Mac_Style;
+    FT_UShort  Lowest_Rec_PPEM;
+
+    FT_Short   Font_Direction;
+    FT_Short   Index_To_Loc_Format;
+    FT_Short   Glyph_Data_Format;
+
+  } TT_Header;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_HoriHeader                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType horizontal header, the `hhea' */
+  /*    table, as well as the corresponding horizontal metrics table,      */
+  /*    i.e., the `hmtx' table.                                            */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    Version                :: The table version.                       */
+  /*                                                                       */
+  /*    Ascender               :: The font's ascender, i.e., the distance  */
+  /*                              from the baseline to the top-most of all */
+  /*                              glyph points found in the font.          */
+  /*                                                                       */
+  /*                              This value is invalid in many fonts, as  */
+  /*                              it is usually set by the font designer,  */
+  /*                              and often reflects only a portion of the */
+  /*                              glyphs found in the font (maybe ASCII).  */
+  /*                                                                       */
+  /*                              You should use the `sTypoAscender' field */
+  /*                              of the OS/2 table instead if you want    */
+  /*                              the correct one.                         */
+  /*                                                                       */
+  /*    Descender              :: The font's descender, i.e., the distance */
+  /*                              from the baseline to the bottom-most of  */
+  /*                              all glyph points found in the font.  It  */
+  /*                              is negative.                             */
+  /*                                                                       */
+  /*                              This value is invalid in many fonts, as  */
+  /*                              it is usually set by the font designer,  */
+  /*                              and often reflects only a portion of the */
+  /*                              glyphs found in the font (maybe ASCII).  */
+  /*                                                                       */
+  /*                              You should use the `sTypoDescender'      */
+  /*                              field of the OS/2 table instead if you   */
+  /*                              want the correct one.                    */
+  /*                                                                       */
+  /*    Line_Gap               :: The font's line gap, i.e., the distance  */
+  /*                              to add to the ascender and descender to  */
+  /*                              get the BTB, i.e., the                   */
+  /*                              baseline-to-baseline distance for the    */
+  /*                              font.                                    */
+  /*                                                                       */
+  /*    advance_Width_Max      :: This field is the maximum of all advance */
+  /*                              widths found in the font.  It can be     */
+  /*                              used to compute the maximum width of an  */
+  /*                              arbitrary string of text.                */
+  /*                                                                       */
+  /*    min_Left_Side_Bearing  :: The minimum left side bearing of all     */
+  /*                              glyphs within the font.                  */
+  /*                                                                       */
+  /*    min_Right_Side_Bearing :: The minimum right side bearing of all    */
+  /*                              glyphs within the font.                  */
+  /*                                                                       */
+  /*    xMax_Extent            :: The maximum horizontal extent (i.e., the */
+  /*                              `width' of a glyph's bounding box) for   */
+  /*                              all glyphs in the font.                  */
+  /*                                                                       */
+  /*    caret_Slope_Rise       :: The rise coefficient of the cursor's     */
+  /*                              slope of the cursor (slope=rise/run).    */
+  /*                                                                       */
+  /*    caret_Slope_Run        :: The run coefficient of the cursor's      */
+  /*                              slope.                                   */
+  /*                                                                       */
+  /*    Reserved               :: 10 reserved bytes.                       */
+  /*                                                                       */
+  /*    metric_Data_Format     :: Always 0.                                */
+  /*                                                                       */
+  /*    number_Of_HMetrics     :: Number of HMetrics entries in the `hmtx' */
+  /*                              table -- this value can be smaller than  */
+  /*                              the total number of glyphs in the font.  */
+  /*                                                                       */
+  /*    long_metrics           :: A pointer into the `hmtx' table.         */
+  /*                                                                       */
+  /*    short_metrics          :: A pointer into the `hmtx' table.         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should   */
+  /*               be identical except for the names of their fields which */
+  /*               are different.                                          */
+  /*                                                                       */
+  /*               This ensures that a single function in the `ttload'     */
+  /*               module is able to read both the horizontal and vertical */
+  /*               headers.                                                */
+  /*                                                                       */
+  typedef struct  TT_HoriHeader_
+  {
+    FT_Fixed   Version;
+    FT_Short   Ascender;
+    FT_Short   Descender;
+    FT_Short   Line_Gap;
+
+    FT_UShort  advance_Width_Max;      /* advance width maximum */
+
+    FT_Short   min_Left_Side_Bearing;  /* minimum left-sb       */
+    FT_Short   min_Right_Side_Bearing; /* minimum right-sb      */
+    FT_Short   xMax_Extent;            /* xmax extents          */
+    FT_Short   caret_Slope_Rise;
+    FT_Short   caret_Slope_Run;
+    FT_Short   caret_Offset;
+
+    FT_Short   Reserved[4];
+
+    FT_Short   metric_Data_Format;
+    FT_UShort  number_Of_HMetrics;
+
+    /* The following fields are not defined by the TrueType specification */
+    /* but they are used to connect the metrics header to the relevant    */
+    /* `HMTX' table.                                                      */
+
+    void*      long_metrics;
+    void*      short_metrics;
+
+  } TT_HoriHeader;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_VertHeader                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType vertical header, the `vhea'   */
+  /*    table, as well as the corresponding vertical metrics table, i.e.,  */
+  /*    the `vmtx' table.                                                  */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    Version                 :: The table version.                      */
+  /*                                                                       */
+  /*    Ascender                :: The font's ascender, i.e., the distance */
+  /*                               from the baseline to the top-most of    */
+  /*                               all glyph points found in the font.     */
+  /*                                                                       */
+  /*                               This value is invalid in many fonts, as */
+  /*                               it is usually set by the font designer, */
+  /*                               and often reflects only a portion of    */
+  /*                               the glyphs found in the font (maybe     */
+  /*                               ASCII).                                 */
+  /*                                                                       */
+  /*                               You should use the `sTypoAscender'      */
+  /*                               field of the OS/2 table instead if you  */
+  /*                               want the correct one.                   */
+  /*                                                                       */
+  /*    Descender               :: The font's descender, i.e., the         */
+  /*                               distance from the baseline to the       */
+  /*                               bottom-most of all glyph points found   */
+  /*                               in the font.  It is negative.           */
+  /*                                                                       */
+  /*                               This value is invalid in many fonts, as */
+  /*                               it is usually set by the font designer, */
+  /*                               and often reflects only a portion of    */
+  /*                               the glyphs found in the font (maybe     */
+  /*                               ASCII).                                 */
+  /*                                                                       */
+  /*                               You should use the `sTypoDescender'     */
+  /*                               field of the OS/2 table instead if you  */
+  /*                               want the correct one.                   */
+  /*                                                                       */
+  /*    Line_Gap                :: The font's line gap, i.e., the distance */
+  /*                               to add to the ascender and descender to */
+  /*                               get the BTB, i.e., the                  */
+  /*                               baseline-to-baseline distance for the   */
+  /*                               font.                                   */
+  /*                                                                       */
+  /*    advance_Height_Max      :: This field is the maximum of all        */
+  /*                               advance heights found in the font.  It  */
+  /*                               can be used to compute the maximum      */
+  /*                               height of an arbitrary string of text.  */
+  /*                                                                       */
+  /*    min_Top_Side_Bearing    :: The minimum top side bearing of all     */
+  /*                               glyphs within the font.                 */
+  /*                                                                       */
+  /*    min_Bottom_Side_Bearing :: The minimum bottom side bearing of all  */
+  /*                               glyphs within the font.                 */
+  /*                                                                       */
+  /*    yMax_Extent             :: The maximum vertical extent (i.e., the  */
+  /*                               `height' of a glyph's bounding box) for */
+  /*                               all glyphs in the font.                 */
+  /*                                                                       */
+  /*    caret_Slope_Rise        :: The rise coefficient of the cursor's    */
+  /*                               slope of the cursor (slope=rise/run).   */
+  /*                                                                       */
+  /*    caret_Slope_Run         :: The run coefficient of the cursor's     */
+  /*                               slope.                                  */
+  /*                                                                       */
+  /*    caret_Offset            :: The cursor's offset for slanted fonts.  */
+  /*                               This value is `reserved' in vmtx        */
+  /*                               version 1.0.                            */
+  /*                                                                       */
+  /*    Reserved                :: 8 reserved bytes.                       */
+  /*                                                                       */
+  /*    metric_Data_Format      :: Always 0.                               */
+  /*                                                                       */
+  /*    number_Of_HMetrics      :: Number of VMetrics entries in the       */
+  /*                               `vmtx' table -- this value can be       */
+  /*                               smaller than the total number of glyphs */
+  /*                               in the font.                            */
+  /*                                                                       */
+  /*    long_metrics           :: A pointer into the `vmtx' table.         */
+  /*                                                                       */
+  /*    short_metrics          :: A pointer into the `vmtx' table.         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should   */
+  /*               be identical except for the names of their fields which */
+  /*               are different.                                          */
+  /*                                                                       */
+  /*               This ensures that a single function in the `ttload'     */
+  /*               module is able to read both the horizontal and vertical */
+  /*               headers.                                                */
+  /*                                                                       */
+  typedef struct  TT_VertHeader_
+  {
+    FT_Fixed   Version;
+    FT_Short   Ascender;
+    FT_Short   Descender;
+    FT_Short   Line_Gap;
+
+    FT_UShort  advance_Height_Max;      /* advance height maximum */
+
+    FT_Short   min_Top_Side_Bearing;    /* minimum left-sb or top-sb       */
+    FT_Short   min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb   */
+    FT_Short   yMax_Extent;             /* xmax or ymax extents            */
+    FT_Short   caret_Slope_Rise;
+    FT_Short   caret_Slope_Run;
+    FT_Short   caret_Offset;
+
+    FT_Short   Reserved[4];
+
+    FT_Short   metric_Data_Format;
+    FT_UShort  number_Of_VMetrics;
+
+    /* The following fields are not defined by the TrueType specification */
+    /* but they're used to connect the metrics header to the relevant     */
+    /* `HMTX' or `VMTX' table.                                            */
+
+    void*      long_metrics;
+    void*      short_metrics;
+
+  } TT_VertHeader;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_OS2                                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType OS/2 table. This is the long  */
+  /*    table version.  All fields comply to the TrueType specification.   */
+  /*                                                                       */
+  /*    Note that we now support old Mac fonts which do not include an     */
+  /*    OS/2 table.  In this case, the `version' field is always set to    */
+  /*    0xFFFF.                                                            */
+  /*                                                                       */
+  typedef struct  TT_OS2_
+  {
+    FT_UShort  version;                /* 0x0001 - more or 0xFFFF */
+    FT_Short   xAvgCharWidth;
+    FT_UShort  usWeightClass;
+    FT_UShort  usWidthClass;
+    FT_Short   fsType;
+    FT_Short   ySubscriptXSize;
+    FT_Short   ySubscriptYSize;
+    FT_Short   ySubscriptXOffset;
+    FT_Short   ySubscriptYOffset;
+    FT_Short   ySuperscriptXSize;
+    FT_Short   ySuperscriptYSize;
+    FT_Short   ySuperscriptXOffset;
+    FT_Short   ySuperscriptYOffset;
+    FT_Short   yStrikeoutSize;
+    FT_Short   yStrikeoutPosition;
+    FT_Short   sFamilyClass;
+
+    FT_Byte    panose[10];
+
+    FT_ULong   ulUnicodeRange1;        /* Bits 0-31   */
+    FT_ULong   ulUnicodeRange2;        /* Bits 32-63  */
+    FT_ULong   ulUnicodeRange3;        /* Bits 64-95  */
+    FT_ULong   ulUnicodeRange4;        /* Bits 96-127 */
+
+    FT_Char    achVendID[4];
+
+    FT_UShort  fsSelection;
+    FT_UShort  usFirstCharIndex;
+    FT_UShort  usLastCharIndex;
+    FT_Short   sTypoAscender;
+    FT_Short   sTypoDescender;
+    FT_Short   sTypoLineGap;
+    FT_UShort  usWinAscent;
+    FT_UShort  usWinDescent;
+
+    /* only version 1 tables: */
+
+    FT_ULong   ulCodePageRange1;       /* Bits 0-31   */
+    FT_ULong   ulCodePageRange2;       /* Bits 32-63  */
+
+    /* only version 2 tables: */
+
+    FT_Short   sxHeight;
+    FT_Short   sCapHeight;
+    FT_UShort  usDefaultChar;
+    FT_UShort  usBreakChar;
+    FT_UShort  usMaxContext;
+
+  } TT_OS2;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_Postscript                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType Postscript table.  All fields */
+  /*    comply to the TrueType table.  This structure does not reference   */
+  /*    the Postscript glyph names, which can be nevertheless accessed     */
+  /*    with the `ttpost' module.                                          */
+  /*                                                                       */
+  typedef struct  TT_Postscript_
+  {
+    FT_Fixed  FormatType;
+    FT_Fixed  italicAngle;
+    FT_Short  underlinePosition;
+    FT_Short  underlineThickness;
+    FT_ULong  isFixedPitch;
+    FT_ULong  minMemType42;
+    FT_ULong  maxMemType42;
+    FT_ULong  minMemType1;
+    FT_ULong  maxMemType1;
+
+    /* Glyph names follow in the file, but we don't   */
+    /* load them by default.  See the ttpost.c file.  */
+
+  } TT_Postscript;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_PCLT                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A structure used to model a TrueType PCLT table.  All fields       */
+  /*    comply to the TrueType table.                                      */
+  /*                                                                       */
+  typedef struct  TT_PCLT_
+  {
+    FT_Fixed   Version;
+    FT_ULong   FontNumber;
+    FT_UShort  Pitch;
+    FT_UShort  xHeight;
+    FT_UShort  Style;
+    FT_UShort  TypeFamily;
+    FT_UShort  CapHeight;
+    FT_UShort  SymbolSet;
+    FT_Char    TypeFace[16];
+    FT_Char    CharacterComplement[8];
+    FT_Char    FileName[6];
+    FT_Char    StrokeWeight;
+    FT_Char    WidthType;
+    FT_Byte    SerifStyle;
+    FT_Byte    Reserved;
+
+  } TT_PCLT;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_MaxProfile                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The maximum profile is a table containing many max values which    */
+  /*    can be used to pre-allocate arrays.  This ensures that no memory   */
+  /*    allocation occurs during a glyph load.                             */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    version               :: The version number.                       */
+  /*                                                                       */
+  /*    numGlyphs             :: The number of glyphs in this TrueType     */
+  /*                             font.                                     */
+  /*                                                                       */
+  /*    maxPoints             :: The maximum number of points in a         */
+  /*                             non-composite TrueType glyph.  See also   */
+  /*                             the structure element                     */
+  /*                             `maxCompositePoints'.                     */
+  /*                                                                       */
+  /*    maxContours           :: The maximum number of contours in a       */
+  /*                             non-composite TrueType glyph.  See also   */
+  /*                             the structure element                     */
+  /*                             `maxCompositeContours'.                   */
+  /*                                                                       */
+  /*    maxCompositePoints    :: The maximum number of points in a         */
+  /*                             composite TrueType glyph.  See also the   */
+  /*                             structure element `maxPoints'.            */
+  /*                                                                       */
+  /*    maxCompositeContours  :: The maximum number of contours in a       */
+  /*                             composite TrueType glyph.  See also the   */
+  /*                             structure element `maxContours'.          */
+  /*                                                                       */
+  /*    maxZones              :: The maximum number of zones used for      */
+  /*                             glyph hinting.                            */
+  /*                                                                       */
+  /*    maxTwilightPoints     :: The maximum number of points in the       */
+  /*                             twilight zone used for glyph hinting.     */
+  /*                                                                       */
+  /*    maxStorage            :: The maximum number of elements in the     */
+  /*                             storage area used for glyph hinting.      */
+  /*                                                                       */
+  /*    maxFunctionDefs       :: The maximum number of function            */
+  /*                             definitions in the TrueType bytecode for  */
+  /*                             this font.                                */
+  /*                                                                       */
+  /*    maxInstructionDefs    :: The maximum number of instruction         */
+  /*                             definitions in the TrueType bytecode for  */
+  /*                             this font.                                */
+  /*                                                                       */
+  /*    maxStackElements      :: The maximum number of stack elements used */
+  /*                             during bytecode interpretation.           */
+  /*                                                                       */
+  /*    maxSizeOfInstructions :: The maximum number of TrueType opcodes    */
+  /*                             used for glyph hinting.                   */
+  /*                                                                       */
+  /*    maxComponentElements  :: An obscure value related to composite     */
+  /*                             glyphs definitions.                       */
+  /*                                                                       */
+  /*    maxComponentDepth     :: An obscure value related to composite     */
+  /*                             glyphs definitions.  Probably the maximum */
+  /*                             number of simple glyphs in a composite.   */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This structure is only used during font loading.                   */
+  /*                                                                       */
+  typedef struct  TT_MaxProfile_
+  {
+    FT_Fixed   version;
+    FT_UShort  numGlyphs;
+    FT_UShort  maxPoints;
+    FT_UShort  maxContours;
+    FT_UShort  maxCompositePoints;
+    FT_UShort  maxCompositeContours;
+    FT_UShort  maxZones;
+    FT_UShort  maxTwilightPoints;
+    FT_UShort  maxStorage;
+    FT_UShort  maxFunctionDefs;
+    FT_UShort  maxInstructionDefs;
+    FT_UShort  maxStackElements;
+    FT_UShort  maxSizeOfInstructions;
+    FT_UShort  maxComponentElements;
+    FT_UShort  maxComponentDepth;
+
+  } TT_MaxProfile;
+
+
+  /* */
+
+  typedef enum
+  {
+    ft_sfnt_head = 0,
+    ft_sfnt_maxp = 1,
+    ft_sfnt_os2  = 2,
+    ft_sfnt_hhea = 3,
+    ft_sfnt_vhea = 4,
+    ft_sfnt_post = 5,
+    ft_sfnt_pclt = 6,
+
+    sfnt_max   /* don't remove */
+
+  } FT_Sfnt_Tag;
+
+
+  /* internal use only */
+  typedef void*
+  (*FT_Get_Sfnt_Table_Func)( FT_Face      face,
+                             FT_Sfnt_Tag  tag );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FT_Get_Sfnt_Table                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns a pointer to a given SFNT table within a face.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the source.                                    */
+  /*                                                                       */
+  /*    tag  :: The index of the SFNT table.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A type-less pointer to the table.  This will be 0 in case of       */
+  /*    error, or if the corresponding table was not found *OR* loaded     */
+  /*    from the file.                                                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The table is owned by the face object and disappears with it.      */
+  /*                                                                       */
+  /*    This function is only useful to access SFNT tables that are loaded */
+  /*    by the sfnt/truetype/opentype drivers.  See FT_Sfnt_Tag for a      */
+  /*    list.                                                              */
+  /*                                                                       */
+  FT_EXPORT( void* )
+  FT_Get_Sfnt_Table( FT_Face      face,
+                     FT_Sfnt_Tag  tag );
+
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* __TTTABLES_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/freetype/tttags.h b/libraries/freetype-2.0.5/include/freetype/tttags.h
new file mode 100644 (file)
index 0000000..df09f2a
--- /dev/null
@@ -0,0 +1,74 @@
+/***************************************************************************/
+/*                                                                         */
+/*  tttags.h                                                               */
+/*                                                                         */
+/*    Tags for TrueType tables (specification only).                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTAGS_H__
+#define __TTAGS_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+#define TTAG_cmap  FT_MAKE_TAG( 'c', 'm', 'a', 'p' )
+#define TTAG_cvt   FT_MAKE_TAG( 'c', 'v', 't', ' ' )
+#define TTAG_CFF   FT_MAKE_TAG( 'C', 'F', 'F', ' ' )
+#define TTAG_DSIG  FT_MAKE_TAG( 'D', 'S', 'I', 'G' )
+#define TTAG_bhed  FT_MAKE_TAG( 'b', 'h', 'e', 'd' )
+#define TTAG_bdat  FT_MAKE_TAG( 'b', 'd', 'a', 't' )
+#define TTAG_bloc  FT_MAKE_TAG( 'b', 'l', 'o', 'c' )
+#define TTAG_EBDT  FT_MAKE_TAG( 'E', 'B', 'D', 'T' )
+#define TTAG_EBLC  FT_MAKE_TAG( 'E', 'B', 'L', 'C' )
+#define TTAG_EBSC  FT_MAKE_TAG( 'E', 'B', 'S', 'C' )
+#define TTAG_fpgm  FT_MAKE_TAG( 'f', 'p', 'g', 'm' )
+#define TTAG_fvar  FT_MAKE_TAG( 'f', 'v', 'a', 'r' )
+#define TTAG_gasp  FT_MAKE_TAG( 'g', 'a', 's', 'p' )
+#define TTAG_glyf  FT_MAKE_TAG( 'g', 'l', 'y', 'f' )
+#define TTAG_GSUB  FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
+#define TTAG_hdmx  FT_MAKE_TAG( 'h', 'd', 'm', 'x' )
+#define TTAG_head  FT_MAKE_TAG( 'h', 'e', 'a', 'd' )
+#define TTAG_hhea  FT_MAKE_TAG( 'h', 'h', 'e', 'a' )
+#define TTAG_hmtx  FT_MAKE_TAG( 'h', 'm', 't', 'x' )
+#define TTAG_kern  FT_MAKE_TAG( 'k', 'e', 'r', 'n' )
+#define TTAG_loca  FT_MAKE_TAG( 'l', 'o', 'c', 'a' )
+#define TTAG_LTSH  FT_MAKE_TAG( 'L', 'T', 'S', 'H' )
+#define TTAG_maxp  FT_MAKE_TAG( 'm', 'a', 'x', 'p' )
+#define TTAG_MMSD  FT_MAKE_TAG( 'M', 'M', 'S', 'D' )
+#define TTAG_MMFX  FT_MAKE_TAG( 'M', 'M', 'F', 'X' )
+#define TTAG_name  FT_MAKE_TAG( 'n', 'a', 'm', 'e' )
+#define TTAG_OS2   FT_MAKE_TAG( 'O', 'S', '/', '2' )
+#define TTAG_OTTO  FT_MAKE_TAG( 'O', 'T', 'T', 'O' )
+#define TTAG_PCLT  FT_MAKE_TAG( 'P', 'C', 'L', 'T' )
+#define TTAG_post  FT_MAKE_TAG( 'p', 'o', 's', 't' )
+#define TTAG_prep  FT_MAKE_TAG( 'p', 'r', 'e', 'p' )
+#define TTAG_true  FT_MAKE_TAG( 't', 'r', 'u', 'e' )
+#define TTAG_ttc   FT_MAKE_TAG( 't', 't', 'c', ' ' )
+#define TTAG_ttcf  FT_MAKE_TAG( 't', 't', 'c', 'f' )
+#define TTAG_VDMX  FT_MAKE_TAG( 'V', 'D', 'M', 'X' )
+#define TTAG_vhea  FT_MAKE_TAG( 'v', 'h', 'e', 'a' )
+#define TTAG_vmtx  FT_MAKE_TAG( 'v', 'm', 't', 'x' )
+
+
+FT_END_HEADER
+
+#endif /* __TTAGS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ft2build.h b/libraries/freetype-2.0.5/include/ft2build.h
new file mode 100644 (file)
index 0000000..2ecfdea
--- /dev/null
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ft2build.h                                                             */
+/*                                                                         */
+/*    FreeType 2 build and setup macros.                                   */
+/*    (Generic version)                                                    */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file corresponds to the default "ft2build.h" file for            */
+  /* FreeType 2.  It uses the "freetype" include root.                     */
+  /*                                                                       */
+  /* Note that specific platforms might use a different configuration.     */
+  /* See builds/unix/ft2unix.h for an example.                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FT2_BUILD_GENERIC_H__
+#define __FT2_BUILD_GENERIC_H__
+
+#include <freetype/config/ftheader.h>
+
+#endif /* __FT2_BUILD_GENERIC_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ftcerror.h b/libraries/freetype-2.0.5/include/ftcerror.h
new file mode 100644 (file)
index 0000000..5998d42
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcerror.h                                                             */
+/*                                                                         */
+/*    Caching sub-system error codes (specification only).                 */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the caching sub-system error enumeration  */
+  /* constants.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __FTCERROR_H__
+#define __FTCERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  FTC_Err_
+#define FT_ERR_BASE    FT_Mod_Err_Cache
+
+#include FT_ERRORS_H
+
+#endif /* __FTCERROR_H__ */
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ftgrays.h b/libraries/freetype-2.0.5/include/ftgrays.h
new file mode 100644 (file)
index 0000000..2d40954
--- /dev/null
@@ -0,0 +1,57 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftgrays.h                                                              */
+/*                                                                         */
+/*    FreeType smooth renderer declaration                                 */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTGRAYS_H__
+#define __FTGRAYS_H__
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+#ifdef _STANDALONE_
+#include "ftimage.h"
+#else
+#include <ft2build.h>
+#include FT_IMAGE_H
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* To make ftgrays.h independent from configuration files we check       */
+  /* whether FT_EXPORT_VAR has been defined already.                       */
+  /*                                                                       */
+  /* On some systems and compilers (Win32 mostly), an extra keyword is     */
+  /* necessary to compile the library as a DLL.                            */
+  /*                                                                       */
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR( x )  extern  x
+#endif
+
+  FT_EXPORT_VAR( const FT_Raster_Funcs )  ft_grays_raster;
+
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif /* __FTGRAYS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ftraster.h b/libraries/freetype-2.0.5/include/ftraster.h
new file mode 100644 (file)
index 0000000..80fe46d
--- /dev/null
@@ -0,0 +1,46 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftraster.h                                                             */
+/*                                                                         */
+/*    The FreeType glyph rasterizer (specification).                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used        */
+/*  modified and distributed under the terms of the FreeType project       */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTRASTER_H__
+#define __FTRASTER_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_IMAGE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Uncomment the following line if you are using ftraster.c as a         */
+  /* standalone module, fully independent of FreeType.                     */
+  /*                                                                       */
+/* #define _STANDALONE_ */
+
+  FT_EXPORT_VAR( const FT_Raster_Funcs )  ft_standard_raster;
+
+
+FT_END_HEADER
+
+#endif /* __FTRASTER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ftrend1.h b/libraries/freetype-2.0.5/include/ftrend1.h
new file mode 100644 (file)
index 0000000..76e9a5f
--- /dev/null
@@ -0,0 +1,44 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftrend1.h                                                              */
+/*                                                                         */
+/*    The FreeType glyph rasterizer interface (specification).             */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTREND1_H__
+#define __FTREND1_H__
+
+
+#include <ft2build.h>
+#include FT_RENDER_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_EXPORT_VAR( const FT_Renderer_Class )  ft_raster1_renderer_class;
+
+  /* this renderer is _NOT_ part of the default modules, you'll need */
+  /* to register it by hand in your application.  It should only be  */
+  /* used for backwards-compatibility with FT 1.x anyway.            */
+  /*                                                                 */
+  FT_EXPORT_VAR( const FT_Renderer_Class )  ft_raster5_renderer_class;
+
+
+FT_END_HEADER
+
+#endif /* __FTREND1_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ftsmerrs.h b/libraries/freetype-2.0.5/include/ftsmerrs.h
new file mode 100644 (file)
index 0000000..0c2a2ec
--- /dev/null
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsmerrs.h                                                             */
+/*                                                                         */
+/*    smooth renderer error codes (specification only).                    */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the smooth renderer error enumeration     */
+  /* constants.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __FTSMERRS_H__
+#define __FTSMERRS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  Smooth_Err_
+#define FT_ERR_BASE    FT_Mod_Err_Smooth
+
+#include FT_ERRORS_H
+
+#endif /* __FTSMERRS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ftsmooth.h b/libraries/freetype-2.0.5/include/ftsmooth.h
new file mode 100644 (file)
index 0000000..ec01121
--- /dev/null
@@ -0,0 +1,44 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftsmooth.h                                                             */
+/*                                                                         */
+/*    Anti-aliasing renderer interface (specification).                    */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTSMOOTH_H__
+#define __FTSMOOTH_H__
+
+
+#include <ft2build.h>
+#include FT_RENDER_H
+
+
+FT_BEGIN_HEADER
+
+
+#ifndef FT_CONFIG_OPTION_NO_STD_RASTER
+  FT_EXPORT_VAR( const FT_Renderer_Class )  ft_std_renderer_class;
+#endif
+
+#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER
+  FT_EXPORT_VAR( const FT_Renderer_Class )  ft_smooth_renderer_class;
+#endif
+
+
+FT_END_HEADER
+
+#endif /* __FTSMOOTH_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/pcf.h b/libraries/freetype-2.0.5/include/pcf.h
new file mode 100644 (file)
index 0000000..3941b6a
--- /dev/null
@@ -0,0 +1,239 @@
+/*  pcf.h
+
+  FreeType font driver for pcf fonts
+
+  Copyright (C) 2000-2001 by
+  Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef __PCF_H__
+#define __PCF_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+  typedef struct  PCF_TableRec_
+  {
+    FT_ULong  type;
+    FT_ULong  format;
+    FT_ULong  size;
+    FT_ULong  offset;
+
+  } PCF_TableRec, *PCF_Table;
+
+
+  typedef struct  PCF_TocRec_
+  {
+    FT_ULong   version;
+    FT_ULong   count;
+    PCF_Table  tables;
+
+  } PCF_TocRec, *PCF_Toc;
+
+
+  typedef struct  PCF_ParseProperty_
+  {
+    FT_Long  name;
+    FT_Byte  isString;
+    FT_Long  value;
+
+  } PCF_ParsePropertyRec, *PCF_ParseProperty;
+
+
+  typedef struct  PCF_Property_
+  {
+    FT_String*  name;
+    FT_Byte     isString;
+
+    union
+    {
+      FT_String*  atom;
+      FT_Long     integer;
+      FT_ULong    cardinal;
+
+    } value;
+
+  } PCF_PropertyRec, *PCF_Property;
+
+
+  typedef struct  PCF_Compressed_Metric_
+  {
+    FT_Byte  leftSideBearing;
+    FT_Byte  rightSideBearing;
+    FT_Byte  characterWidth;
+    FT_Byte  ascent;
+    FT_Byte  descent;
+
+  } PCF_Compressed_MetricRec, *PCF_Compressed_Metric;
+
+
+  typedef struct  PCF_Metric_
+  {
+    FT_Short  leftSideBearing;
+    FT_Short  rightSideBearing;
+    FT_Short  characterWidth;
+    FT_Short  ascent;
+    FT_Short  descent;
+    FT_Short  attributes;
+    FT_ULong  bits;
+
+  } PCF_MetricRec, *PCF_Metric;
+
+
+  typedef struct  PCF_AccelRec_
+  {
+    FT_Byte        noOverlap;
+    FT_Byte        constantMetrics;
+    FT_Byte        terminalFont;
+    FT_Byte        constantWidth;
+    FT_Byte        inkInside;
+    FT_Byte        inkMetrics;
+    FT_Byte        drawDirection;
+    FT_Long        fontAscent;
+    FT_Long        fontDescent;
+    FT_Long        maxOverlap;
+    PCF_MetricRec  minbounds;
+    PCF_MetricRec  maxbounds;
+    PCF_MetricRec  ink_minbounds;
+    PCF_MetricRec  ink_maxbounds;
+
+  } PCF_AccelRec, *PCF_Accel;
+
+
+  typedef struct  PCD_Encoding_
+  {
+    FT_Long   enc;
+    FT_Short  glyph;
+
+  } PCF_EncodingRec, *PCF_Encoding;
+
+
+  typedef struct  PCF_FaceRec_
+  {
+    FT_FaceRec     root;
+
+    char*          charset_encoding;
+    char*          charset_registry;
+
+    PCF_TocRec     toc;
+    PCF_AccelRec   accel;
+
+    int            nprops;
+    PCF_Property   properties;
+
+    FT_Long        nmetrics;
+    PCF_Metric     metrics;
+    FT_Long        nencodings;
+    PCF_Encoding   encodings;
+
+    FT_Short       defaultChar;
+
+    FT_ULong       bitmapsFormat;
+
+    FT_CharMap     charmap_handle;
+    FT_CharMapRec  charmap;  /* a single charmap per face */
+
+  } PCF_FaceRec, *PCF_Face;
+
+
+  /* XXX hack */
+  FT_LOCAL FT_Error
+  PCF_Done_Face( PCF_Face  face );
+
+
+  /* macros for pcf font format */
+
+#define LSBFirst  0
+#define MSBFirst  1
+
+#define PCF_FILE_VERSION        ( ( 'p' << 24 ) | \
+                                  ( 'c' << 16 ) | \
+                                  ( 'f' <<  8 ) | 1 )
+#define PCF_FORMAT_MASK         0xFFFFFF00L
+
+#define PCF_DEFAULT_FORMAT      0x00000000L
+#define PCF_INKBOUNDS           0x00000200L
+#define PCF_ACCEL_W_INKBOUNDS   0x00000100L
+#define PCF_COMPRESSED_METRICS  0x00000100L
+
+#define PCF_FORMAT_MATCH( a, b ) \
+          ( ( (a) & PCF_FORMAT_MASK ) == ( (b) & PCF_FORMAT_MASK ) )
+
+#define PCF_GLYPH_PAD_MASK  ( 3 << 0 )
+#define PCF_BYTE_MASK       ( 1 << 2 )
+#define PCF_BIT_MASK        ( 1 << 3 )
+#define PCF_SCAN_UNIT_MASK  ( 3 << 4 )
+
+#define PCF_BYTE_ORDER( f ) \
+          ( ( (f) & PCF_BYTE_MASK ) ? MSBFirst : LSBFirst )
+#define PCF_BIT_ORDER( f ) \
+          ( ( (f) & PCF_BIT_MASK ) ? MSBFirst : LSBFirst )
+#define PCF_GLYPH_PAD_INDEX( f ) \
+          ( (f) & PCF_GLYPH_PAD_MASK )
+#define PCF_GLYPH_PAD( f ) \
+          ( 1 << PCF_GLYPH_PAD_INDEX( f ) )
+#define PCF_SCAN_UNIT_INDEX( f ) \
+          ( ( (f) & PCF_SCAN_UNIT_MASK ) >> 4 )
+#define PCF_SCAN_UNIT( f ) \
+          ( 1 << PCF_SCAN_UNIT_INDEX( f ) )
+#define PCF_FORMAT_BITS( f )             \
+          ( (f) & ( PCF_GLYPH_PAD_MASK | \
+                    PCF_BYTE_MASK      | \
+                    PCF_BIT_MASK       | \
+                    PCF_SCAN_UNIT_MASK ) )
+
+#define PCF_SIZE_TO_INDEX( s )  ( (s) == 4 ? 2 : (s) == 2 ? 1 : 0 )
+#define PCF_INDEX_TO_SIZE( b )  ( 1 << b )
+
+#define PCF_FORMAT( bit, byte, glyph, scan )          \
+          ( ( PCF_SIZE_TO_INDEX( scan )      << 4 ) | \
+            ( ( (bit)  == MSBFirst ? 1 : 0 ) << 3 ) | \
+            ( ( (byte) == MSBFirst ? 1 : 0 ) << 2 ) | \
+            ( PCF_SIZE_TO_INDEX( glyph )     << 0 ) )
+
+#define PCF_PROPERTIES        ( 1 << 0 )
+#define PCF_ACCELERATORS      ( 1 << 1 )
+#define PCF_METRICS           ( 1 << 2 )
+#define PCF_BITMAPS           ( 1 << 3 )
+#define PCF_INK_METRICS       ( 1 << 4 )
+#define PCF_BDF_ENCODINGS     ( 1 << 5 )
+#define PCF_SWIDTHS           ( 1 << 6 )
+#define PCF_GLYPH_NAMES       ( 1 << 7 )
+#define PCF_BDF_ACCELERATORS  ( 1 << 8 )
+
+#define GLYPHPADOPTIONS  4 /* I'm not sure about this */
+
+  FT_LOCAL FT_Error
+  pcf_load_font( FT_Stream,
+                 PCF_Face );
+
+
+FT_END_HEADER
+
+#endif /* __PCF_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/pcfdriver.h b/libraries/freetype-2.0.5/include/pcfdriver.h
new file mode 100644 (file)
index 0000000..c59990a
--- /dev/null
@@ -0,0 +1,44 @@
+/*  pcfdriver.h
+
+    FreeType font driver for pcf fonts
+
+  Copyright 2000-2001 by
+  Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef __PCFDRIVER_H__
+#define __PCFDRIVER_H__
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+FT_BEGIN_HEADER
+
+  FT_EXPORT_VAR( const FT_Driver_Class )  pcf_driver_class;
+
+FT_END_HEADER
+
+
+#endif /* __PCFDRIVER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/pcferror.h b/libraries/freetype-2.0.5/include/pcferror.h
new file mode 100644 (file)
index 0000000..d75c067
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/*                                                                         */
+/*  pcferror.h                                                             */
+/*                                                                         */
+/*    PCF error codes (specification only).                                */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the PCF error enumeration constants.      */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __PCFERROR_H__
+#define __PCFERROR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  PCF_Err_
+#define FT_ERR_BASE    FT_Mod_Err_PCF
+
+#include FT_ERRORS_H
+
+#endif /* __PCFERROR_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/pcfutil.h b/libraries/freetype-2.0.5/include/pcfutil.h
new file mode 100644 (file)
index 0000000..32dd1ea
--- /dev/null
@@ -0,0 +1,58 @@
+/*  pcfutil.h
+
+    FreeType font driver for pcf fonts
+
+  Copyright 2000-2001 by
+  Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#ifndef __PCFUTIL_H__
+#define __PCFUTIL_H__
+
+
+#include <ft2build.h>
+
+
+  void
+  BitOrderInvert( unsigned char*  buf,
+                  int             nbytes);
+
+  void
+  TwoByteSwap( unsigned char*  buf,
+               int             nbytes);
+
+  void
+  FourByteSwap( unsigned char*  buf,
+                int             nbytes);
+
+  int
+  RepadBitmap( char*           pSrc,
+               char*           pDst,
+               unsigned int    srcPad,
+               unsigned int    dstPad,
+               int             width,
+               int             height);
+
+#endif /* __PCFUTIL_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/psauxerr.h b/libraries/freetype-2.0.5/include/psauxerr.h
new file mode 100644 (file)
index 0000000..d0baa3c
--- /dev/null
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psauxerr.h                                                             */
+/*                                                                         */
+/*    PS auxiliary module error codes (specification only).                */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the PS auxiliary module error enumeration */
+  /* constants.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __PSAUXERR_H__
+#define __PSAUXERR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  PSaux_Err_
+#define FT_ERR_BASE    FT_Mod_Err_PSaux
+
+#include FT_ERRORS_H
+
+#endif /* __PSAUXERR_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/psauxmod.h b/libraries/freetype-2.0.5/include/psauxmod.h
new file mode 100644 (file)
index 0000000..92ac056
--- /dev/null
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psauxmod.h                                                             */
+/*                                                                         */
+/*    FreeType auxiliary PostScript module implementation (specification). */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __PSAUXMOD_H__
+#define __PSAUXMOD_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_EXPORT_VAR( const FT_Module_Class )  psaux_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __PSAUXMOD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/psmodule.h b/libraries/freetype-2.0.5/include/psmodule.h
new file mode 100644 (file)
index 0000000..232fdfb
--- /dev/null
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psmodule.h                                                             */
+/*                                                                         */
+/*    High-level PSNames module interface (specification).                 */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __PSMODULE_H__
+#define __PSMODULE_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_EXPORT_VAR( const FT_Module_Class )  psnames_module_class;
+
+
+FT_END_HEADER
+
+#endif /* __PSMODULE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/psnamerr.h b/libraries/freetype-2.0.5/include/psnamerr.h
new file mode 100644 (file)
index 0000000..ae1541d
--- /dev/null
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psnamerr.h                                                             */
+/*                                                                         */
+/*    PS names module error codes (specification only).                    */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the PS names module error enumeration     */
+  /* constants.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __PSNAMERR_H__
+#define __PSNAMERR_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  PSnames_Err_
+#define FT_ERR_BASE    FT_Mod_Err_PSnames
+
+#include FT_ERRORS_H
+
+#endif /* __PSNAMERR_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/psobjs.h b/libraries/freetype-2.0.5/include/psobjs.h
new file mode 100644 (file)
index 0000000..a3ae8f8
--- /dev/null
@@ -0,0 +1,203 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psobjs.h                                                               */
+/*                                                                         */
+/*    Auxiliary functions for PostScript fonts (specification).            */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __PSOBJS_H__
+#define __PSOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                             T1_TABLE                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_TABLE
+  const PS_Table_Funcs  ps_table_funcs;
+
+  FT_CALLBACK_TABLE
+  const T1_Parser_Funcs  t1_parser_funcs;
+
+  FT_CALLBACK_TABLE
+  const T1_Builder_Funcs  t1_builder_funcs;
+
+
+  FT_LOCAL FT_Error
+  PS_Table_New( PS_Table*  table,
+                FT_Int     count,
+                FT_Memory  memory );
+
+  FT_LOCAL FT_Error
+  PS_Table_Add( PS_Table*  table,
+                FT_Int     index,
+                void*      object,
+                FT_Int     length );
+
+  FT_LOCAL void
+  PS_Table_Done( PS_Table*  table );
+
+
+  FT_LOCAL void
+  PS_Table_Release( PS_Table*  table );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                            T1 PARSER                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_LOCAL void
+  T1_Skip_Spaces( T1_Parser*  parser );
+
+  FT_LOCAL void
+  T1_Skip_Alpha( T1_Parser*  parser );
+
+  FT_LOCAL void
+  T1_ToToken( T1_Parser*  parser,
+              T1_Token*   token );
+
+  FT_LOCAL void
+  T1_ToTokenArray( T1_Parser*  parser,
+                   T1_Token*   tokens,
+                   FT_UInt     max_tokens,
+                   FT_Int*     pnum_tokens );
+
+  FT_LOCAL FT_Error
+  T1_Load_Field( T1_Parser*       parser,
+                 const T1_Field*  field,
+                 void**           objects,
+                 FT_UInt          max_objects,
+                 FT_ULong*        pflags );
+
+  FT_LOCAL FT_Error
+  T1_Load_Field_Table( T1_Parser*       parser,
+                       const T1_Field*  field,
+                       void**           objects,
+                       FT_UInt          max_objects,
+                       FT_ULong*        pflags );
+
+  FT_LOCAL FT_Long
+  T1_ToInt( T1_Parser*  parser );
+
+
+  FT_LOCAL FT_Fixed
+  T1_ToFixed( T1_Parser*  parser,
+              FT_Int      power_ten );
+
+
+  FT_LOCAL FT_Int
+  T1_ToCoordArray( T1_Parser*  parser,
+                   FT_Int      max_coords,
+                   FT_Short*   coords );
+
+  FT_LOCAL FT_Int
+  T1_ToFixedArray( T1_Parser*  parser,
+                   FT_Int      max_values,
+                   FT_Fixed*   values,
+                   FT_Int      power_ten );
+
+
+  FT_LOCAL void
+  T1_Init_Parser( T1_Parser*  parser,
+                  FT_Byte*    base,
+                  FT_Byte*    limit,
+                  FT_Memory   memory );
+
+  FT_LOCAL void
+  T1_Done_Parser( T1_Parser*  parser );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                            T1 BUILDER                         *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  FT_LOCAL void
+  T1_Builder_Init( T1_Builder*   builder,
+                   FT_Face       face,
+                   FT_Size       size,
+                   FT_GlyphSlot  glyph );
+
+  FT_LOCAL void
+  T1_Builder_Done( T1_Builder*  builder );
+
+  FT_LOCAL FT_Error
+  T1_Builder_Check_Points( T1_Builder*  builder,
+                           FT_Int       count );
+
+  FT_LOCAL void
+  T1_Builder_Add_Point( T1_Builder*  builder,
+                        FT_Pos       x,
+                        FT_Pos       y,
+                        FT_Byte      flag );
+
+  FT_LOCAL FT_Error
+  T1_Builder_Add_Point1( T1_Builder*  builder,
+                         FT_Pos       x,
+                         FT_Pos       y );
+
+  FT_LOCAL FT_Error
+  T1_Builder_Add_Contour( T1_Builder*  builder );
+
+
+  FT_LOCAL FT_Error
+  T1_Builder_Start_Point( T1_Builder*  builder,
+                          FT_Pos       x,
+                          FT_Pos       y );
+
+
+  FT_LOCAL void
+  T1_Builder_Close_Contour( T1_Builder*  builder );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                            OTHER                              *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  FT_LOCAL void
+  T1_Decrypt( FT_Byte*   buffer,
+              FT_Offset  length,
+              FT_UShort  seed );
+
+
+FT_END_HEADER
+
+#endif /* __PSOBJS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/pstables.h b/libraries/freetype-2.0.5/include/pstables.h
new file mode 100644 (file)
index 0000000..3db8fe7
--- /dev/null
@@ -0,0 +1,2968 @@
+/***************************************************************************/
+/*                                                                         */
+/*  c:\david\source\freetype\freetype2\src\psnames\pstables.h              */
+/*                                                                         */
+/*    PostScript glyph names (specification only).                         */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /* this file has been generated automatically -- do not edit! */
+
+
+  static const char* const  ps_glyph_names[] =
+  {
+    ".notdef",
+    ".null",
+    "nonmarkingreturn",
+    "nonbreakingspace",
+    "apple",
+    ".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",
+    "exclamdown",
+    "cent",
+    "sterling",
+    "fraction",
+    "yen",
+    "florin",
+    "section",
+    "currency",
+    "quotesingle",
+    "quotedblleft",
+    "guillemotleft",
+    "guilsinglleft",
+    "guilsinglright",
+    "fi",
+    "fl",
+    "endash",
+    "dagger",
+    "daggerdbl",
+    "periodcentered",
+    "paragraph",
+    "bullet",
+    "quotesinglbase",
+    "quotedblbase",
+    "quotedblright",
+    "guillemotright",
+    "ellipsis",
+    "perthousand",
+    "questiondown",
+    "grave",
+    "acute",
+    "circumflex",
+    "tilde",
+    "macron",
+    "breve",
+    "dotaccent",
+    "dieresis",
+    "ring",
+    "cedilla",
+    "hungarumlaut",
+    "ogonek",
+    "caron",
+    "emdash",
+    "AE",
+    "ordfeminine",
+    "Lslash",
+    "Oslash",
+    "OE",
+    "ordmasculine",
+    "ae",
+    "dotlessi",
+    "lslash",
+    "oslash",
+    "oe",
+    "germandbls",
+    "onesuperior",
+    "logicalnot",
+    "mu",
+    "trademark",
+    "Eth",
+    "onehalf",
+    "plusminus",
+    "Thorn",
+    "onequarter",
+    "divide",
+    "brokenbar",
+    "degree",
+    "thorn",
+    "threequarters",
+    "twosuperior",
+    "registered",
+    "minus",
+    "eth",
+    "multiply",
+    "threesuperior",
+    "copyright",
+    "Aacute",
+    "Acircumflex",
+    "Adieresis",
+    "Agrave",
+    "Aring",
+    "Atilde",
+    "Ccedilla",
+    "Eacute",
+    "Ecircumflex",
+    "Edieresis",
+    "Egrave",
+    "Iacute",
+    "Icircumflex",
+    "Idieresis",
+    "Igrave",
+    "Ntilde",
+    "Oacute",
+    "Ocircumflex",
+    "Odieresis",
+    "Ograve",
+    "Otilde",
+    "Scaron",
+    "Uacute",
+    "Ucircumflex",
+    "Udieresis",
+    "Ugrave",
+    "Yacute",
+    "Ydieresis",
+    "Zcaron",
+    "aacute",
+    "acircumflex",
+    "adieresis",
+    "agrave",
+    "aring",
+    "atilde",
+    "ccedilla",
+    "eacute",
+    "ecircumflex",
+    "edieresis",
+    "egrave",
+    "iacute",
+    "icircumflex",
+    "idieresis",
+    "igrave",
+    "ntilde",
+    "oacute",
+    "ocircumflex",
+    "odieresis",
+    "ograve",
+    "otilde",
+    "scaron",
+    "uacute",
+    "ucircumflex",
+    "udieresis",
+    "ugrave",
+    "yacute",
+    "ydieresis",
+    "zcaron",
+    "exclamsmall",
+    "Hungarumlautsmall",
+    "dollaroldstyle",
+    "dollarsuperior",
+    "ampersandsmall",
+    "Acutesmall",
+    "parenleftsuperior",
+    "parenrightsuperior",
+    "twodotenleader",
+    "onedotenleader",
+    "zerooldstyle",
+    "oneoldstyle",
+    "twooldstyle",
+    "threeoldstyle",
+    "fouroldstyle",
+    "fiveoldstyle",
+    "sixoldstyle",
+    "sevenoldstyle",
+    "eightoldstyle",
+    "nineoldstyle",
+    "commasuperior",
+    "threequartersemdash",
+    "periodsuperior",
+    "questionsmall",
+    "asuperior",
+    "bsuperior",
+    "centsuperior",
+    "dsuperior",
+    "esuperior",
+    "isuperior",
+    "lsuperior",
+    "msuperior",
+    "nsuperior",
+    "osuperior",
+    "rsuperior",
+    "ssuperior",
+    "tsuperior",
+    "ff",
+    "ffi",
+    "ffl",
+    "parenleftinferior",
+    "parenrightinferior",
+    "Circumflexsmall",
+    "hyphensuperior",
+    "Gravesmall",
+    "Asmall",
+    "Bsmall",
+    "Csmall",
+    "Dsmall",
+    "Esmall",
+    "Fsmall",
+    "Gsmall",
+    "Hsmall",
+    "Ismall",
+    "Jsmall",
+    "Ksmall",
+    "Lsmall",
+    "Msmall",
+    "Nsmall",
+    "Osmall",
+    "Psmall",
+    "Qsmall",
+    "Rsmall",
+    "Ssmall",
+    "Tsmall",
+    "Usmall",
+    "Vsmall",
+    "Wsmall",
+    "Xsmall",
+    "Ysmall",
+    "Zsmall",
+    "colonmonetary",
+    "onefitted",
+    "rupiah",
+    "Tildesmall",
+    "exclamdownsmall",
+    "centoldstyle",
+    "Lslashsmall",
+    "Scaronsmall",
+    "Zcaronsmall",
+    "Dieresissmall",
+    "Brevesmall",
+    "Caronsmall",
+    "Dotaccentsmall",
+    "Macronsmall",
+    "figuredash",
+    "hypheninferior",
+    "Ogoneksmall",
+    "Ringsmall",
+    "Cedillasmall",
+    "questiondownsmall",
+    "oneeighth",
+    "threeeighths",
+    "fiveeighths",
+    "seveneighths",
+    "onethird",
+    "twothirds",
+    "zerosuperior",
+    "foursuperior",
+    "fivesuperior",
+    "sixsuperior",
+    "sevensuperior",
+    "eightsuperior",
+    "ninesuperior",
+    "zeroinferior",
+    "oneinferior",
+    "twoinferior",
+    "threeinferior",
+    "fourinferior",
+    "fiveinferior",
+    "sixinferior",
+    "seveninferior",
+    "eightinferior",
+    "nineinferior",
+    "centinferior",
+    "dollarinferior",
+    "periodinferior",
+    "commainferior",
+    "Agravesmall",
+    "Aacutesmall",
+    "Acircumflexsmall",
+    "Atildesmall",
+    "Adieresissmall",
+    "Aringsmall",
+    "AEsmall",
+    "Ccedillasmall",
+    "Egravesmall",
+    "Eacutesmall",
+    "Ecircumflexsmall",
+    "Edieresissmall",
+    "Igravesmall",
+    "Iacutesmall",
+    "Icircumflexsmall",
+    "Idieresissmall",
+    "Ethsmall",
+    "Ntildesmall",
+    "Ogravesmall",
+    "Oacutesmall",
+    "Ocircumflexsmall",
+    "Otildesmall",
+    "Odieresissmall",
+    "OEsmall",
+    "Oslashsmall",
+    "Ugravesmall",
+    "Uacutesmall",
+    "Ucircumflexsmall",
+    "Udieresissmall",
+    "Yacutesmall",
+    "Thornsmall",
+    "Ydieresissmall",
+    "001.000",
+    "001.001",
+    "001.002",
+    "001.003",
+    "Black",
+    "Bold",
+    "Book",
+    "Light",
+    "Medium",
+    "Regular",
+    "Roman",
+    "Semibold",
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+    "AEacute",
+    "Abreve",
+    "Acute",
+    "Alpha",
+    "Alphatonos",
+    "Amacron",
+    "Aogonek",
+    "Aringacute",
+    "Beta",
+    "Cacute",
+    "Caron",
+    "Ccaron",
+    "Ccircumflex",
+    "Cdotaccent",
+    "Chi",
+    "Dcaron",
+    "Dcroat",
+    "Delta",
+    "Delta",
+    "Dieresis",
+    "DieresisAcute",
+    "DieresisGrave",
+    "Ebreve",
+    "Ecaron",
+    "Edotaccent",
+    "Emacron",
+    "Eng",
+    "Eogonek",
+    "Epsilon",
+    "Epsilontonos",
+    "Eta",
+    "Etatonos",
+    "Euro",
+    "Gamma",
+    "Gbreve",
+    "Gcaron",
+    "Gcircumflex",
+    "Gcommaaccent",
+    "Gdotaccent",
+    "Grave",
+    "H18533",
+    "H18543",
+    "H18551",
+    "H22073",
+    "Hbar",
+    "Hcircumflex",
+    "Hungarumlaut",
+    "IJ",
+    "Ibreve",
+    "Idotaccent",
+    "Ifraktur",
+    "Imacron",
+    "Iogonek",
+    "Iota",
+    "Iotadieresis",
+    "Iotatonos",
+    "Itilde",
+    "Jcircumflex",
+    "Kappa",
+    "Kcommaaccent",
+    "LL",
+    "Lacute",
+    "Lambda",
+    "Lcaron",
+    "Lcommaaccent",
+    "Ldot",
+    "Macron",
+    "Mu",
+    "Nacute",
+    "Ncaron",
+    "Ncommaaccent",
+    "Nu",
+    "Obreve",
+    "Ohorn",
+    "Ohungarumlaut",
+    "Omacron",
+    "Omega",
+    "Omega",
+    "Omegatonos",
+    "Omicron",
+    "Omicrontonos",
+    "Oslashacute",
+    "Phi",
+    "Pi",
+    "Psi",
+    "Racute",
+    "Rcaron",
+    "Rcommaaccent",
+    "Rfraktur",
+    "Rho",
+    "SF010000",
+    "SF020000",
+    "SF030000",
+    "SF040000",
+    "SF050000",
+    "SF060000",
+    "SF070000",
+    "SF080000",
+    "SF090000",
+    "SF100000",
+    "SF110000",
+    "SF190000",
+    "SF200000",
+    "SF210000",
+    "SF220000",
+    "SF230000",
+    "SF240000",
+    "SF250000",
+    "SF260000",
+    "SF270000",
+    "SF280000",
+    "SF360000",
+    "SF370000",
+    "SF380000",
+    "SF390000",
+    "SF400000",
+    "SF410000",
+    "SF420000",
+    "SF430000",
+    "SF440000",
+    "SF450000",
+    "SF460000",
+    "SF470000",
+    "SF480000",
+    "SF490000",
+    "SF500000",
+    "SF510000",
+    "SF520000",
+    "SF530000",
+    "SF540000",
+    "Sacute",
+    "Scedilla",
+    "Scedilla",
+    "Scircumflex",
+    "Scommaaccent",
+    "Sigma",
+    "Tau",
+    "Tbar",
+    "Tcaron",
+    "Tcommaaccent",
+    "Tcommaaccent",
+    "Theta",
+    "Ubreve",
+    "Uhorn",
+    "Uhungarumlaut",
+    "Umacron",
+    "Uogonek",
+    "Upsilon",
+    "Upsilon1",
+    "Upsilondieresis",
+    "Upsilontonos",
+    "Uring",
+    "Utilde",
+    "Wacute",
+    "Wcircumflex",
+    "Wdieresis",
+    "Wgrave",
+    "Xi",
+    "Ycircumflex",
+    "Ygrave",
+    "Zacute",
+    "Zdotaccent",
+    "Zeta",
+    "abreve",
+    "acutecomb",
+    "aeacute",
+    "afii00208",
+    "afii10017",
+    "afii10018",
+    "afii10019",
+    "afii10020",
+    "afii10021",
+    "afii10022",
+    "afii10023",
+    "afii10024",
+    "afii10025",
+    "afii10026",
+    "afii10027",
+    "afii10028",
+    "afii10029",
+    "afii10030",
+    "afii10031",
+    "afii10032",
+    "afii10033",
+    "afii10034",
+    "afii10035",
+    "afii10036",
+    "afii10037",
+    "afii10038",
+    "afii10039",
+    "afii10040",
+    "afii10041",
+    "afii10042",
+    "afii10043",
+    "afii10044",
+    "afii10045",
+    "afii10046",
+    "afii10047",
+    "afii10048",
+    "afii10049",
+    "afii10050",
+    "afii10051",
+    "afii10052",
+    "afii10053",
+    "afii10054",
+    "afii10055",
+    "afii10056",
+    "afii10057",
+    "afii10058",
+    "afii10059",
+    "afii10060",
+    "afii10061",
+    "afii10062",
+    "afii10063",
+    "afii10064",
+    "afii10065",
+    "afii10066",
+    "afii10067",
+    "afii10068",
+    "afii10069",
+    "afii10070",
+    "afii10071",
+    "afii10072",
+    "afii10073",
+    "afii10074",
+    "afii10075",
+    "afii10076",
+    "afii10077",
+    "afii10078",
+    "afii10079",
+    "afii10080",
+    "afii10081",
+    "afii10082",
+    "afii10083",
+    "afii10084",
+    "afii10085",
+    "afii10086",
+    "afii10087",
+    "afii10088",
+    "afii10089",
+    "afii10090",
+    "afii10091",
+    "afii10092",
+    "afii10093",
+    "afii10094",
+    "afii10095",
+    "afii10096",
+    "afii10097",
+    "afii10098",
+    "afii10099",
+    "afii10100",
+    "afii10101",
+    "afii10102",
+    "afii10103",
+    "afii10104",
+    "afii10105",
+    "afii10106",
+    "afii10107",
+    "afii10108",
+    "afii10109",
+    "afii10110",
+    "afii10145",
+    "afii10146",
+    "afii10147",
+    "afii10148",
+    "afii10192",
+    "afii10193",
+    "afii10194",
+    "afii10195",
+    "afii10196",
+    "afii10831",
+    "afii10832",
+    "afii10846",
+    "afii299",
+    "afii300",
+    "afii301",
+    "afii57381",
+    "afii57388",
+    "afii57392",
+    "afii57393",
+    "afii57394",
+    "afii57395",
+    "afii57396",
+    "afii57397",
+    "afii57398",
+    "afii57399",
+    "afii57400",
+    "afii57401",
+    "afii57403",
+    "afii57407",
+    "afii57409",
+    "afii57410",
+    "afii57411",
+    "afii57412",
+    "afii57413",
+    "afii57414",
+    "afii57415",
+    "afii57416",
+    "afii57417",
+    "afii57418",
+    "afii57419",
+    "afii57420",
+    "afii57421",
+    "afii57422",
+    "afii57423",
+    "afii57424",
+    "afii57425",
+    "afii57426",
+    "afii57427",
+    "afii57428",
+    "afii57429",
+    "afii57430",
+    "afii57431",
+    "afii57432",
+    "afii57433",
+    "afii57434",
+    "afii57440",
+    "afii57441",
+    "afii57442",
+    "afii57443",
+    "afii57444",
+    "afii57445",
+    "afii57446",
+    "afii57448",
+    "afii57449",
+    "afii57450",
+    "afii57451",
+    "afii57452",
+    "afii57453",
+    "afii57454",
+    "afii57455",
+    "afii57456",
+    "afii57457",
+    "afii57458",
+    "afii57470",
+    "afii57505",
+    "afii57506",
+    "afii57507",
+    "afii57508",
+    "afii57509",
+    "afii57511",
+    "afii57512",
+    "afii57513",
+    "afii57514",
+    "afii57519",
+    "afii57534",
+    "afii57636",
+    "afii57645",
+    "afii57658",
+    "afii57664",
+    "afii57665",
+    "afii57666",
+    "afii57667",
+    "afii57668",
+    "afii57669",
+    "afii57670",
+    "afii57671",
+    "afii57672",
+    "afii57673",
+    "afii57674",
+    "afii57675",
+    "afii57676",
+    "afii57677",
+    "afii57678",
+    "afii57679",
+    "afii57680",
+    "afii57681",
+    "afii57682",
+    "afii57683",
+    "afii57684",
+    "afii57685",
+    "afii57686",
+    "afii57687",
+    "afii57688",
+    "afii57689",
+    "afii57690",
+    "afii57694",
+    "afii57695",
+    "afii57700",
+    "afii57705",
+    "afii57716",
+    "afii57717",
+    "afii57718",
+    "afii57723",
+    "afii57793",
+    "afii57794",
+    "afii57795",
+    "afii57796",
+    "afii57797",
+    "afii57798",
+    "afii57799",
+    "afii57800",
+    "afii57801",
+    "afii57802",
+    "afii57803",
+    "afii57804",
+    "afii57806",
+    "afii57807",
+    "afii57839",
+    "afii57841",
+    "afii57842",
+    "afii57929",
+    "afii61248",
+    "afii61289",
+    "afii61352",
+    "afii61573",
+    "afii61574",
+    "afii61575",
+    "afii61664",
+    "afii63167",
+    "afii64937",
+    "aleph",
+    "alpha",
+    "alphatonos",
+    "amacron",
+    "angle",
+    "angleleft",
+    "angleright",
+    "anoteleia",
+    "aogonek",
+    "approxequal",
+    "aringacute",
+    "arrowboth",
+    "arrowdblboth",
+    "arrowdbldown",
+    "arrowdblleft",
+    "arrowdblright",
+    "arrowdblup",
+    "arrowdown",
+    "arrowhorizex",
+    "arrowleft",
+    "arrowright",
+    "arrowup",
+    "arrowupdn",
+    "arrowupdnbse",
+    "arrowvertex",
+    "asteriskmath",
+    "beta",
+    "block",
+    "braceex",
+    "braceleftbt",
+    "braceleftmid",
+    "bracelefttp",
+    "bracerightbt",
+    "bracerightmid",
+    "bracerighttp",
+    "bracketleftbt",
+    "bracketleftex",
+    "bracketlefttp",
+    "bracketrightbt",
+    "bracketrightex",
+    "bracketrighttp",
+    "cacute",
+    "carriagereturn",
+    "ccaron",
+    "ccircumflex",
+    "cdotaccent",
+    "chi",
+    "circle",
+    "circlemultiply",
+    "circleplus",
+    "club",
+    "commaaccent",
+    "congruent",
+    "copyrightsans",
+    "copyrightserif",
+    "cyrBreve",
+    "cyrFlex",
+    "cyrbreve",
+    "cyrflex",
+    "dblGrave",
+    "dblgrave",
+    "dcaron",
+    "dcroat",
+    "delta",
+    "diamond",
+    "dieresisacute",
+    "dieresisgrave",
+    "dieresistonos",
+    "dkshade",
+    "dnblock",
+    "dong",
+    "dotbelowcomb",
+    "dotlessj",
+    "dotmath",
+    "ebreve",
+    "ecaron",
+    "edotaccent",
+    "element",
+    "emacron",
+    "emptyset",
+    "eng",
+    "eogonek",
+    "epsilon",
+    "epsilontonos",
+    "equivalence",
+    "estimated",
+    "eta",
+    "etatonos",
+    "exclamdbl",
+    "existential",
+    "female",
+    "filledbox",
+    "filledrect",
+    "franc",
+    "gamma",
+    "gbreve",
+    "gcaron",
+    "gcircumflex",
+    "gcommaaccent",
+    "gdotaccent",
+    "gradient",
+    "gravecomb",
+    "greaterequal",
+    "hbar",
+    "hcircumflex",
+    "heart",
+    "hookabovecomb",
+    "house",
+    "ibreve",
+    "ij",
+    "imacron",
+    "infinity",
+    "integral",
+    "integralbt",
+    "integralex",
+    "integraltp",
+    "intersection",
+    "invbullet",
+    "invcircle",
+    "invsmileface",
+    "iogonek",
+    "iota",
+    "iotadieresis",
+    "iotadieresistonos",
+    "iotatonos",
+    "itilde",
+    "jcircumflex",
+    "kappa",
+    "kcommaaccent",
+    "kgreenlandic",
+    "lacute",
+    "lambda",
+    "lcaron",
+    "lcommaaccent",
+    "ldot",
+    "lessequal",
+    "lfblock",
+    "lira",
+    "ll",
+    "logicaland",
+    "logicalor",
+    "longs",
+    "lozenge",
+    "ltshade",
+    "male",
+    "minute",
+    "musicalnote",
+    "musicalnotedbl",
+    "nacute",
+    "napostrophe",
+    "ncaron",
+    "ncommaaccent",
+    "notelement",
+    "notequal",
+    "notsubset",
+    "nu",
+    "obreve",
+    "ohorn",
+    "ohungarumlaut",
+    "omacron",
+    "omega",
+    "omega1",
+    "omegatonos",
+    "omicron",
+    "omicrontonos",
+    "openbullet",
+    "orthogonal",
+    "oslashacute",
+    "parenleftbt",
+    "parenleftex",
+    "parenlefttp",
+    "parenrightbt",
+    "parenrightex",
+    "parenrighttp",
+    "partialdiff",
+    "perpendicular",
+    "peseta",
+    "phi",
+    "phi1",
+    "pi",
+    "prescription",
+    "product",
+    "propersubset",
+    "propersuperset",
+    "proportional",
+    "psi",
+    "quotereversed",
+    "racute",
+    "radical",
+    "radicalex",
+    "rcaron",
+    "rcommaaccent",
+    "reflexsubset",
+    "reflexsuperset",
+    "registersans",
+    "registerserif",
+    "revlogicalnot",
+    "rho",
+    "rtblock",
+    "sacute",
+    "scedilla",
+    "scedilla",
+    "scircumflex",
+    "scommaaccent",
+    "second",
+    "shade",
+    "sigma",
+    "sigma1",
+    "similar",
+    "smileface",
+    "spade",
+    "suchthat",
+    "summation",
+    "sun",
+    "tau",
+    "tbar",
+    "tcaron",
+    "tcommaaccent",
+    "tcommaaccent",
+    "therefore",
+    "theta",
+    "theta1",
+    "tildecomb",
+    "tonos",
+    "trademarksans",
+    "trademarkserif",
+    "triagdn",
+    "triaglf",
+    "triagrt",
+    "triagup",
+    "ubreve",
+    "uhorn",
+    "uhungarumlaut",
+    "umacron",
+    "underscoredbl",
+    "union",
+    "universal",
+    "uogonek",
+    "upblock",
+    "upsilon",
+    "upsilondieresis",
+    "upsilondieresistonos",
+    "upsilontonos",
+    "uring",
+    "utilde",
+    "wacute",
+    "wcircumflex",
+    "wdieresis",
+    "weierstrass",
+    "wgrave",
+    "xi",
+    "ycircumflex",
+    "ygrave",
+    "zacute",
+    "zdotaccent",
+    "zeta",
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+    NULL
+  };
+
+
+  static const char* const * const  sid_standard_names = ps_glyph_names + 5;
+
+
+#define NUM_SID_GLYPHS 391
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+#define NUM_ADOBE_GLYPHS 1058
+#else
+#define NUM_ADOBE_GLYPHS 391
+#endif
+
+
+  static const unsigned short  mac_standard_names[259] =
+  {
+    5,
+    0,
+    1,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11,
+    12,
+    109,
+    14,
+    15,
+    16,
+    17,
+    18,
+    19,
+    20,
+    21,
+    22,
+    23,
+    24,
+    25,
+    26,
+    27,
+    28,
+    29,
+    30,
+    31,
+    32,
+    33,
+    34,
+    35,
+    36,
+    37,
+    38,
+    39,
+    40,
+    41,
+    42,
+    43,
+    44,
+    45,
+    46,
+    47,
+    48,
+    49,
+    50,
+    51,
+    52,
+    53,
+    54,
+    55,
+    56,
+    57,
+    58,
+    59,
+    60,
+    61,
+    62,
+    63,
+    64,
+    65,
+    66,
+    67,
+    68,
+    69,
+    129,
+    71,
+    72,
+    73,
+    74,
+    75,
+    76,
+    77,
+    78,
+    79,
+    80,
+    81,
+    82,
+    83,
+    84,
+    85,
+    86,
+    87,
+    88,
+    89,
+    90,
+    91,
+    92,
+    93,
+    94,
+    95,
+    96,
+    97,
+    98,
+    99,
+    100,
+    178,
+    180,
+    182,
+    183,
+    191,
+    194,
+    200,
+    205,
+    208,
+    206,
+    207,
+    210,
+    209,
+    211,
+    212,
+    215,
+    213,
+    214,
+    216,
+    219,
+    217,
+    218,
+    220,
+    221,
+    224,
+    222,
+    223,
+    225,
+    227,
+    230,
+    228,
+    229,
+    117,
+    166,
+    102,
+    103,
+    107,
+    121,
+    120,
+    154,
+    170,
+    175,
+    158,
+    130,
+    136,
+    2,
+    143,
+    146,
+    3,
+    161,
+    4,
+    5,
+    105,
+    157,
+    6,
+    7,
+    8,
+    9,
+    10,
+    144,
+    148,
+    11,
+    149,
+    152,
+    128,
+    101,
+    156,
+    12,
+    106,
+    13,
+    14,
+    111,
+    125,
+    126,
+    15,
+    179,
+    181,
+    196,
+    147,
+    153,
+    116,
+    142,
+    110,
+    124,
+    70,
+    13,
+    164,
+    16,
+    232,
+    203,
+    104,
+    108,
+    112,
+    113,
+    114,
+    115,
+    118,
+    119,
+    122,
+    123,
+    127,
+    177,
+    184,
+    176,
+    185,
+    186,
+    187,
+    188,
+    189,
+    190,
+    192,
+    193,
+    17,
+    195,
+    198,
+    199,
+    201,
+    150,
+    131,
+    132,
+    133,
+    134,
+    135,
+    137,
+    138,
+    139,
+    140,
+    141,
+    145,
+    151,
+    197,
+    226,
+    204,
+    233,
+    165,
+    159,
+    172,
+    202,
+    231,
+    162,
+    167,
+    171,
+    173,
+    155,
+    169,
+    174,
+    160,
+    163,
+    168,
+    18,
+    19,
+    20,
+    21,
+    22,
+    23,
+    24,
+    25,
+    26,
+    27,
+    28,
+    0
+  };
+
+
+
+  static const unsigned short  ps_names_to_unicode[1059] =
+  {
+    0,
+    0x0020,
+    0x0021,
+    0x0022,
+    0x0023,
+    0x0024,
+    0x0025,
+    0x0026,
+    0x2019,
+    0x0028,
+    0x0029,
+    0x002A,
+    0x002B,
+    0x002C,
+    0x002D,
+    0x002E,
+    0x002F,
+    0x0030,
+    0x0031,
+    0x0032,
+    0x0033,
+    0x0034,
+    0x0035,
+    0x0036,
+    0x0037,
+    0x0038,
+    0x0039,
+    0x003A,
+    0x003B,
+    0x003C,
+    0x003D,
+    0x003E,
+    0x003F,
+    0x0040,
+    0x0041,
+    0x0042,
+    0x0043,
+    0x0044,
+    0x0045,
+    0x0046,
+    0x0047,
+    0x0048,
+    0x0049,
+    0x004A,
+    0x004B,
+    0x004C,
+    0x004D,
+    0x004E,
+    0x004F,
+    0x0050,
+    0x0051,
+    0x0052,
+    0x0053,
+    0x0054,
+    0x0055,
+    0x0056,
+    0x0057,
+    0x0058,
+    0x0059,
+    0x005A,
+    0x005B,
+    0x005C,
+    0x005D,
+    0x005E,
+    0x005F,
+    0x2018,
+    0x0061,
+    0x0062,
+    0x0063,
+    0x0064,
+    0x0065,
+    0x0066,
+    0x0067,
+    0x0068,
+    0x0069,
+    0x006A,
+    0x006B,
+    0x006C,
+    0x006D,
+    0x006E,
+    0x006F,
+    0x0070,
+    0x0071,
+    0x0072,
+    0x0073,
+    0x0074,
+    0x0075,
+    0x0076,
+    0x0077,
+    0x0078,
+    0x0079,
+    0x007A,
+    0x007B,
+    0x007C,
+    0x007D,
+    0x007E,
+    0x00A1,
+    0x00A2,
+    0x00A3,
+    0x2044,
+    0x00A5,
+    0x0192,
+    0x00A7,
+    0x00A4,
+    0x0027,
+    0x201C,
+    0x00AB,
+    0x2039,
+    0x203A,
+    0xFB01,
+    0xFB02,
+    0x2013,
+    0x2020,
+    0x2021,
+    0x00B7,
+    0x00B6,
+    0x2022,
+    0x201A,
+    0x201E,
+    0x201D,
+    0x00BB,
+    0x2026,
+    0x2030,
+    0x00BF,
+    0x0060,
+    0x00B4,
+    0x02C6,
+    0x02DC,
+    0x00AF,
+    0x02D8,
+    0x02D9,
+    0x00A8,
+    0x02DA,
+    0x00B8,
+    0x02DD,
+    0x02DB,
+    0x02C7,
+    0x2014,
+    0x00C6,
+    0x00AA,
+    0x0141,
+    0x00D8,
+    0x0152,
+    0x00BA,
+    0x00E6,
+    0x0131,
+    0x0142,
+    0x00F8,
+    0x0153,
+    0x00DF,
+    0x00B9,
+    0x00AC,
+    0x00B5,
+    0x2122,
+    0x00D0,
+    0x00BD,
+    0x00B1,
+    0x00DE,
+    0x00BC,
+    0x00F7,
+    0x00A6,
+    0x00B0,
+    0x00FE,
+    0x00BE,
+    0x00B2,
+    0x00AE,
+    0x2212,
+    0x00F0,
+    0x00D7,
+    0x00B3,
+    0x00A9,
+    0x00C1,
+    0x00C2,
+    0x00C4,
+    0x00C0,
+    0x00C5,
+    0x00C3,
+    0x00C7,
+    0x00C9,
+    0x00CA,
+    0x00CB,
+    0x00C8,
+    0x00CD,
+    0x00CE,
+    0x00CF,
+    0x00CC,
+    0x00D1,
+    0x00D3,
+    0x00D4,
+    0x00D6,
+    0x00D2,
+    0x00D5,
+    0x0160,
+    0x00DA,
+    0x00DB,
+    0x00DC,
+    0x00D9,
+    0x00DD,
+    0x0178,
+    0x017D,
+    0x00E1,
+    0x00E2,
+    0x00E4,
+    0x00E0,
+    0x00E5,
+    0x00E3,
+    0x00E7,
+    0x00E9,
+    0x00EA,
+    0x00EB,
+    0x00E8,
+    0x00ED,
+    0x00EE,
+    0x00EF,
+    0x00EC,
+    0x00F1,
+    0x00F3,
+    0x00F4,
+    0x00F6,
+    0x00F2,
+    0x00F5,
+    0x0161,
+    0x00FA,
+    0x00FB,
+    0x00FC,
+    0x00F9,
+    0x00FD,
+    0x00FF,
+    0x017E,
+    0xF721,
+    0xF6F8,
+    0xF724,
+    0xF6E4,
+    0xF726,
+    0xF7B4,
+    0x207D,
+    0x207E,
+    0x2025,
+    0x2024,
+    0xF730,
+    0xF731,
+    0xF732,
+    0xF733,
+    0xF734,
+    0xF735,
+    0xF736,
+    0xF737,
+    0xF738,
+    0xF739,
+    0xF6E2,
+    0xF6DE,
+    0xF6E8,
+    0xF73F,
+    0xF6E9,
+    0xF6EA,
+    0xF6E0,
+    0xF6EB,
+    0xF6EC,
+    0xF6ED,
+    0xF6EE,
+    0xF6EF,
+    0x207F,
+    0xF6F0,
+    0xF6F1,
+    0xF6F2,
+    0xF6F3,
+    0xFB00,
+    0xFB03,
+    0xFB04,
+    0x208D,
+    0x208E,
+    0xF6F6,
+    0xF6E6,
+    0xF760,
+    0xF761,
+    0xF762,
+    0xF763,
+    0xF764,
+    0xF765,
+    0xF766,
+    0xF767,
+    0xF768,
+    0xF769,
+    0xF76A,
+    0xF76B,
+    0xF76C,
+    0xF76D,
+    0xF76E,
+    0xF76F,
+    0xF770,
+    0xF771,
+    0xF772,
+    0xF773,
+    0xF774,
+    0xF775,
+    0xF776,
+    0xF777,
+    0xF778,
+    0xF779,
+    0xF77A,
+    0x20A1,
+    0xF6DC,
+    0xF6DD,
+    0xF6FE,
+    0xF7A1,
+    0xF7A2,
+    0xF6F9,
+    0xF6FD,
+    0xF6FF,
+    0xF7A8,
+    0xF6F4,
+    0xF6F5,
+    0xF6F7,
+    0xF7AF,
+    0x2012,
+    0xF6E5,
+    0xF6FB,
+    0xF6FC,
+    0xF7B8,
+    0xF7BF,
+    0x215B,
+    0x215C,
+    0x215D,
+    0x215E,
+    0x2153,
+    0x2154,
+    0x2070,
+    0x2074,
+    0x2075,
+    0x2076,
+    0x2077,
+    0x2078,
+    0x2079,
+    0x2080,
+    0x2081,
+    0x2082,
+    0x2083,
+    0x2084,
+    0x2085,
+    0x2086,
+    0x2087,
+    0x2088,
+    0x2089,
+    0xF6DF,
+    0xF6E3,
+    0xF6E7,
+    0xF6E1,
+    0xF7E0,
+    0xF7E1,
+    0xF7E2,
+    0xF7E3,
+    0xF7E4,
+    0xF7E5,
+    0xF7E6,
+    0xF7E7,
+    0xF7E8,
+    0xF7E9,
+    0xF7EA,
+    0xF7EB,
+    0xF7EC,
+    0xF7ED,
+    0xF7EE,
+    0xF7EF,
+    0xF7F0,
+    0xF7F1,
+    0xF7F2,
+    0xF7F3,
+    0xF7F4,
+    0xF7F5,
+    0xF7F6,
+    0xF6FA,
+    0xF7F8,
+    0xF7F9,
+    0xF7FA,
+    0xF7FB,
+    0xF7FC,
+    0xF7FD,
+    0xF7FE,
+    0xF7FF,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+    0x01FC,
+    0x0102,
+    0xF6C9,
+    0x0391,
+    0x0386,
+    0x0100,
+    0x0104,
+    0x01FA,
+    0x0392,
+    0x0106,
+    0xF6CA,
+    0x010C,
+    0x0108,
+    0x010A,
+    0x03A7,
+    0x010E,
+    0x0110,
+    0x2206,
+    0x2206,
+    0xF6CB,
+    0xF6CC,
+    0xF6CD,
+    0x0114,
+    0x011A,
+    0x0116,
+    0x0112,
+    0x014A,
+    0x0118,
+    0x0395,
+    0x0388,
+    0x0397,
+    0x0389,
+    0x20AC,
+    0x0393,
+    0x011E,
+    0x01E6,
+    0x011C,
+    0x0122,
+    0x0120,
+    0xF6CE,
+    0x25CF,
+    0x25AA,
+    0x25AB,
+    0x25A1,
+    0x0126,
+    0x0124,
+    0xF6CF,
+    0x0132,
+    0x012C,
+    0x0130,
+    0x2111,
+    0x012A,
+    0x012E,
+    0x0399,
+    0x03AA,
+    0x038A,
+    0x0128,
+    0x0134,
+    0x039A,
+    0x0136,
+    0xF6BF,
+    0x0139,
+    0x039B,
+    0x013D,
+    0x013B,
+    0x013F,
+    0xF6D0,
+    0x039C,
+    0x0143,
+    0x0147,
+    0x0145,
+    0x039D,
+    0x014E,
+    0x01A0,
+    0x0150,
+    0x014C,
+    0x2126,
+    0x2126,
+    0x038F,
+    0x039F,
+    0x038C,
+    0x01FE,
+    0x03A6,
+    0x03A0,
+    0x03A8,
+    0x0154,
+    0x0158,
+    0x0156,
+    0x211C,
+    0x03A1,
+    0x250C,
+    0x2514,
+    0x2510,
+    0x2518,
+    0x253C,
+    0x252C,
+    0x2534,
+    0x251C,
+    0x2524,
+    0x2500,
+    0x2502,
+    0x2561,
+    0x2562,
+    0x2556,
+    0x2555,
+    0x2563,
+    0x2551,
+    0x2557,
+    0x255D,
+    0x255C,
+    0x255B,
+    0x255E,
+    0x255F,
+    0x255A,
+    0x2554,
+    0x2569,
+    0x2566,
+    0x2560,
+    0x2550,
+    0x256C,
+    0x2567,
+    0x2568,
+    0x2564,
+    0x2565,
+    0x2559,
+    0x2558,
+    0x2552,
+    0x2553,
+    0x256B,
+    0x256A,
+    0x015A,
+    0x015E,
+    0x015E,
+    0x015C,
+    0x0218,
+    0x03A3,
+    0x03A4,
+    0x0166,
+    0x0164,
+    0x0162,
+    0x0162,
+    0x0398,
+    0x016C,
+    0x01AF,
+    0x0170,
+    0x016A,
+    0x0172,
+    0x03A5,
+    0x03D2,
+    0x03AB,
+    0x038E,
+    0x016E,
+    0x0168,
+    0x1E82,
+    0x0174,
+    0x1E84,
+    0x1E80,
+    0x039E,
+    0x0176,
+    0x1EF2,
+    0x0179,
+    0x017B,
+    0x0396,
+    0x0103,
+    0x0301,
+    0x01FD,
+    0x2015,
+    0x0410,
+    0x0411,
+    0x0412,
+    0x0413,
+    0x0414,
+    0x0415,
+    0x0401,
+    0x0416,
+    0x0417,
+    0x0418,
+    0x0419,
+    0x041A,
+    0x041B,
+    0x041C,
+    0x041D,
+    0x041E,
+    0x041F,
+    0x0420,
+    0x0421,
+    0x0422,
+    0x0423,
+    0x0424,
+    0x0425,
+    0x0426,
+    0x0427,
+    0x0428,
+    0x0429,
+    0x042A,
+    0x042B,
+    0x042C,
+    0x042D,
+    0x042E,
+    0x042F,
+    0x0490,
+    0x0402,
+    0x0403,
+    0x0404,
+    0x0405,
+    0x0406,
+    0x0407,
+    0x0408,
+    0x0409,
+    0x040A,
+    0x040B,
+    0x040C,
+    0x040E,
+    0xF6C4,
+    0xF6C5,
+    0x0430,
+    0x0431,
+    0x0432,
+    0x0433,
+    0x0434,
+    0x0435,
+    0x0451,
+    0x0436,
+    0x0437,
+    0x0438,
+    0x0439,
+    0x043A,
+    0x043B,
+    0x043C,
+    0x043D,
+    0x043E,
+    0x043F,
+    0x0440,
+    0x0441,
+    0x0442,
+    0x0443,
+    0x0444,
+    0x0445,
+    0x0446,
+    0x0447,
+    0x0448,
+    0x0449,
+    0x044A,
+    0x044B,
+    0x044C,
+    0x044D,
+    0x044E,
+    0x044F,
+    0x0491,
+    0x0452,
+    0x0453,
+    0x0454,
+    0x0455,
+    0x0456,
+    0x0457,
+    0x0458,
+    0x0459,
+    0x045A,
+    0x045B,
+    0x045C,
+    0x045E,
+    0x040F,
+    0x0462,
+    0x0472,
+    0x0474,
+    0xF6C6,
+    0x045F,
+    0x0463,
+    0x0473,
+    0x0475,
+    0xF6C7,
+    0xF6C8,
+    0x04D9,
+    0x200E,
+    0x200F,
+    0x200D,
+    0x066A,
+    0x060C,
+    0x0660,
+    0x0661,
+    0x0662,
+    0x0663,
+    0x0664,
+    0x0665,
+    0x0666,
+    0x0667,
+    0x0668,
+    0x0669,
+    0x061B,
+    0x061F,
+    0x0621,
+    0x0622,
+    0x0623,
+    0x0624,
+    0x0625,
+    0x0626,
+    0x0627,
+    0x0628,
+    0x0629,
+    0x062A,
+    0x062B,
+    0x062C,
+    0x062D,
+    0x062E,
+    0x062F,
+    0x0630,
+    0x0631,
+    0x0632,
+    0x0633,
+    0x0634,
+    0x0635,
+    0x0636,
+    0x0637,
+    0x0638,
+    0x0639,
+    0x063A,
+    0x0640,
+    0x0641,
+    0x0642,
+    0x0643,
+    0x0644,
+    0x0645,
+    0x0646,
+    0x0648,
+    0x0649,
+    0x064A,
+    0x064B,
+    0x064C,
+    0x064D,
+    0x064E,
+    0x064F,
+    0x0650,
+    0x0651,
+    0x0652,
+    0x0647,
+    0x06A4,
+    0x067E,
+    0x0686,
+    0x0698,
+    0x06AF,
+    0x0679,
+    0x0688,
+    0x0691,
+    0x06BA,
+    0x06D2,
+    0x06D5,
+    0x20AA,
+    0x05BE,
+    0x05C3,
+    0x05D0,
+    0x05D1,
+    0x05D2,
+    0x05D3,
+    0x05D4,
+    0x05D5,
+    0x05D6,
+    0x05D7,
+    0x05D8,
+    0x05D9,
+    0x05DA,
+    0x05DB,
+    0x05DC,
+    0x05DD,
+    0x05DE,
+    0x05DF,
+    0x05E0,
+    0x05E1,
+    0x05E2,
+    0x05E3,
+    0x05E4,
+    0x05E5,
+    0x05E6,
+    0x05E7,
+    0x05E8,
+    0x05E9,
+    0x05EA,
+    0xFB2A,
+    0xFB2B,
+    0xFB4B,
+    0xFB1F,
+    0x05F0,
+    0x05F1,
+    0x05F2,
+    0xFB35,
+    0x05B4,
+    0x05B5,
+    0x05B6,
+    0x05BB,
+    0x05B8,
+    0x05B7,
+    0x05B0,
+    0x05B2,
+    0x05B1,
+    0x05B3,
+    0x05C2,
+    0x05C1,
+    0x05B9,
+    0x05BC,
+    0x05BD,
+    0x05BF,
+    0x05C0,
+    0x02BC,
+    0x2105,
+    0x2113,
+    0x2116,
+    0x202C,
+    0x202D,
+    0x202E,
+    0x200C,
+    0x066D,
+    0x02BD,
+    0x2135,
+    0x03B1,
+    0x03AC,
+    0x0101,
+    0x2220,
+    0x2329,
+    0x232A,
+    0x0387,
+    0x0105,
+    0x2248,
+    0x01FB,
+    0x2194,
+    0x21D4,
+    0x21D3,
+    0x21D0,
+    0x21D2,
+    0x21D1,
+    0x2193,
+    0xF8E7,
+    0x2190,
+    0x2192,
+    0x2191,
+    0x2195,
+    0x21A8,
+    0xF8E6,
+    0x2217,
+    0x03B2,
+    0x2588,
+    0xF8F4,
+    0xF8F3,
+    0xF8F2,
+    0xF8F1,
+    0xF8FE,
+    0xF8FD,
+    0xF8FC,
+    0xF8F0,
+    0xF8EF,
+    0xF8EE,
+    0xF8FB,
+    0xF8FA,
+    0xF8F9,
+    0x0107,
+    0x21B5,
+    0x010D,
+    0x0109,
+    0x010B,
+    0x03C7,
+    0x25CB,
+    0x2297,
+    0x2295,
+    0x2663,
+    0xF6C3,
+    0x2245,
+    0xF8E9,
+    0xF6D9,
+    0xF6D1,
+    0xF6D2,
+    0xF6D4,
+    0xF6D5,
+    0xF6D3,
+    0xF6D6,
+    0x010F,
+    0x0111,
+    0x03B4,
+    0x2666,
+    0xF6D7,
+    0xF6D8,
+    0x0385,
+    0x2593,
+    0x2584,
+    0x20AB,
+    0x0323,
+    0xF6BE,
+    0x22C5,
+    0x0115,
+    0x011B,
+    0x0117,
+    0x2208,
+    0x0113,
+    0x2205,
+    0x014B,
+    0x0119,
+    0x03B5,
+    0x03AD,
+    0x2261,
+    0x212E,
+    0x03B7,
+    0x03AE,
+    0x203C,
+    0x2203,
+    0x2640,
+    0x25A0,
+    0x25AC,
+    0x20A3,
+    0x03B3,
+    0x011F,
+    0x01E7,
+    0x011D,
+    0x0123,
+    0x0121,
+    0x2207,
+    0x0300,
+    0x2265,
+    0x0127,
+    0x0125,
+    0x2665,
+    0x0309,
+    0x2302,
+    0x012D,
+    0x0133,
+    0x012B,
+    0x221E,
+    0x222B,
+    0x2321,
+    0xF8F5,
+    0x2320,
+    0x2229,
+    0x25D8,
+    0x25D9,
+    0x263B,
+    0x012F,
+    0x03B9,
+    0x03CA,
+    0x0390,
+    0x03AF,
+    0x0129,
+    0x0135,
+    0x03BA,
+    0x0137,
+    0x0138,
+    0x013A,
+    0x03BB,
+    0x013E,
+    0x013C,
+    0x0140,
+    0x2264,
+    0x258C,
+    0x20A4,
+    0xF6C0,
+    0x2227,
+    0x2228,
+    0x017F,
+    0x25CA,
+    0x2591,
+    0x2642,
+    0x2032,
+    0x266A,
+    0x266B,
+    0x0144,
+    0x0149,
+    0x0148,
+    0x0146,
+    0x2209,
+    0x2260,
+    0x2284,
+    0x03BD,
+    0x014F,
+    0x01A1,
+    0x0151,
+    0x014D,
+    0x03C9,
+    0x03D6,
+    0x03CE,
+    0x03BF,
+    0x03CC,
+    0x25E6,
+    0x221F,
+    0x01FF,
+    0xF8ED,
+    0xF8EC,
+    0xF8EB,
+    0xF8F8,
+    0xF8F7,
+    0xF8F6,
+    0x2202,
+    0x22A5,
+    0x20A7,
+    0x03C6,
+    0x03D5,
+    0x03C0,
+    0x211E,
+    0x220F,
+    0x2282,
+    0x2283,
+    0x221D,
+    0x03C8,
+    0x201B,
+    0x0155,
+    0x221A,
+    0xF8E5,
+    0x0159,
+    0x0157,
+    0x2286,
+    0x2287,
+    0xF8E8,
+    0xF6DA,
+    0x2310,
+    0x03C1,
+    0x2590,
+    0x015B,
+    0x015F,
+    0x015F,
+    0x015D,
+    0x0219,
+    0x2033,
+    0x2592,
+    0x03C3,
+    0x03C2,
+    0x223C,
+    0x263A,
+    0x2660,
+    0x220B,
+    0x2211,
+    0x263C,
+    0x03C4,
+    0x0167,
+    0x0165,
+    0x0163,
+    0x0163,
+    0x2234,
+    0x03B8,
+    0x03D1,
+    0x0303,
+    0x0384,
+    0xF8EA,
+    0xF6DB,
+    0x25BC,
+    0x25C4,
+    0x25BA,
+    0x25B2,
+    0x016D,
+    0x01B0,
+    0x0171,
+    0x016B,
+    0x2017,
+    0x222A,
+    0x2200,
+    0x0173,
+    0x2580,
+    0x03C5,
+    0x03CB,
+    0x03B0,
+    0x03CD,
+    0x016F,
+    0x0169,
+    0x1E83,
+    0x0175,
+    0x1E85,
+    0x2118,
+    0x1E81,
+    0x03BE,
+    0x0177,
+    0x1EF3,
+    0x017A,
+    0x017C,
+    0x03B6,
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+    0
+  };
+
+
+
+  static const unsigned short  t1_standard_encoding[257] =
+  {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11,
+    12,
+    13,
+    14,
+    15,
+    16,
+    17,
+    18,
+    19,
+    20,
+    21,
+    22,
+    23,
+    24,
+    25,
+    26,
+    27,
+    28,
+    29,
+    30,
+    31,
+    32,
+    33,
+    34,
+    35,
+    36,
+    37,
+    38,
+    39,
+    40,
+    41,
+    42,
+    43,
+    44,
+    45,
+    46,
+    47,
+    48,
+    49,
+    50,
+    51,
+    52,
+    53,
+    54,
+    55,
+    56,
+    57,
+    58,
+    59,
+    60,
+    61,
+    62,
+    63,
+    64,
+    65,
+    66,
+    67,
+    68,
+    69,
+    70,
+    71,
+    72,
+    73,
+    74,
+    75,
+    76,
+    77,
+    78,
+    79,
+    80,
+    81,
+    82,
+    83,
+    84,
+    85,
+    86,
+    87,
+    88,
+    89,
+    90,
+    91,
+    92,
+    93,
+    94,
+    95,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    96,
+    97,
+    98,
+    99,
+    100,
+    101,
+    102,
+    103,
+    104,
+    105,
+    106,
+    107,
+    108,
+    109,
+    110,
+    0,
+    111,
+    112,
+    113,
+    114,
+    0,
+    115,
+    116,
+    117,
+    118,
+    119,
+    120,
+    121,
+    122,
+    0,
+    123,
+    0,
+    124,
+    125,
+    126,
+    127,
+    128,
+    129,
+    130,
+    131,
+    0,
+    132,
+    133,
+    0,
+    134,
+    135,
+    136,
+    137,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    138,
+    0,
+    139,
+    0,
+    0,
+    0,
+    0,
+    140,
+    141,
+    142,
+    143,
+    0,
+    0,
+    0,
+    0,
+    0,
+    144,
+    0,
+    0,
+    0,
+    145,
+    0,
+    0,
+    146,
+    147,
+    148,
+    149,
+    0,
+    0,
+    0,
+    0,
+    0
+  };
+
+
+  static const unsigned short  t1_expert_encoding[257] =
+  {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    1,
+    229,
+    230,
+    0,
+    231,
+    232,
+    233,
+    234,
+    235,
+    236,
+    237,
+    238,
+    13,
+    14,
+    15,
+    99,
+    239,
+    240,
+    241,
+    242,
+    243,
+    244,
+    245,
+    246,
+    247,
+    248,
+    27,
+    28,
+    249,
+    250,
+    251,
+    252,
+    0,
+    253,
+    254,
+    255,
+    256,
+    257,
+    0,
+    0,
+    0,
+    258,
+    0,
+    0,
+    259,
+    260,
+    261,
+    262,
+    0,
+    0,
+    263,
+    264,
+    265,
+    0,
+    266,
+    109,
+    110,
+    267,
+    268,
+    269,
+    0,
+    270,
+    271,
+    272,
+    273,
+    274,
+    275,
+    276,
+    277,
+    278,
+    279,
+    280,
+    281,
+    282,
+    283,
+    284,
+    285,
+    286,
+    287,
+    288,
+    289,
+    290,
+    291,
+    292,
+    293,
+    294,
+    295,
+    296,
+    297,
+    298,
+    299,
+    300,
+    301,
+    302,
+    303,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    304,
+    305,
+    306,
+    0,
+    0,
+    307,
+    308,
+    309,
+    310,
+    311,
+    0,
+    312,
+    0,
+    0,
+    313,
+    0,
+    0,
+    314,
+    315,
+    0,
+    0,
+    316,
+    317,
+    318,
+    0,
+    0,
+    0,
+    158,
+    155,
+    163,
+    319,
+    320,
+    321,
+    322,
+    323,
+    324,
+    325,
+    0,
+    0,
+    326,
+    150,
+    164,
+    169,
+    327,
+    328,
+    329,
+    330,
+    331,
+    332,
+    333,
+    334,
+    335,
+    336,
+    337,
+    338,
+    339,
+    340,
+    341,
+    342,
+    343,
+    344,
+    345,
+    346,
+    347,
+    348,
+    349,
+    350,
+    351,
+    352,
+    353,
+    354,
+    355,
+    356,
+    357,
+    358,
+    359,
+    360,
+    361,
+    362,
+    363,
+    364,
+    365,
+    366,
+    367,
+    368,
+    369,
+    370,
+    371,
+    372,
+    373,
+    374,
+    375,
+    376,
+    377,
+    378,
+    0
+  };
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/rasterrs.h b/libraries/freetype-2.0.5/include/rasterrs.h
new file mode 100644 (file)
index 0000000..5df9a7a
--- /dev/null
@@ -0,0 +1,41 @@
+/***************************************************************************/
+/*                                                                         */
+/*  rasterrs.h                                                             */
+/*                                                                         */
+/*    monochrome renderer error codes (specification only).                */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the monochrome renderer error enumeration */
+  /* constants.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __RASTERRS_H__
+#define __RASTERRS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  Raster_Err_
+#define FT_ERR_BASE    FT_Mod_Err_Raster
+
+#include FT_ERRORS_H
+
+#endif /* __RASTERRS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/sfdriver.h b/libraries/freetype-2.0.5/include/sfdriver.h
new file mode 100644 (file)
index 0000000..92db796
--- /dev/null
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfdriver.h                                                             */
+/*                                                                         */
+/*    High-level SFNT driver interface (specification).                    */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __SFDRIVER_H__
+#define __SFDRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_EXPORT_VAR( const FT_Module_Class )  sfnt_module_class;
+
+
+FT_END_HEADER
+
+#endif /* __SFDRIVER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/sferrors.h b/libraries/freetype-2.0.5/include/sferrors.h
new file mode 100644 (file)
index 0000000..fd2736b
--- /dev/null
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sferrors.h                                                             */
+/*                                                                         */
+/*    SFNT error codes (specification only).                               */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the SFNT error enumeration constants.     */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __SFERRORS_H__
+#define __SFERRORS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  SFNT_Err_
+#define FT_ERR_BASE    FT_Mod_Err_SFNT
+
+#include FT_ERRORS_H
+
+#endif /* __SFERRORS_H__ */
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/sfobjs.h b/libraries/freetype-2.0.5/include/sfobjs.h
new file mode 100644 (file)
index 0000000..463f0b6
--- /dev/null
@@ -0,0 +1,54 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfobjs.h                                                               */
+/*                                                                         */
+/*    SFNT object management (specification).                              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __SFOBJS_H__
+#define __SFOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_OBJECTS_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_LOCAL FT_Error
+  SFNT_Init_Face( FT_Stream      stream,
+                  TT_Face        face,
+                  FT_Int         face_index,
+                  FT_Int         num_params,
+                  FT_Parameter*  params );
+
+  FT_LOCAL FT_Error
+  SFNT_Load_Face( FT_Stream      stream,
+                  TT_Face        face,
+                  FT_Int         face_index,
+                  FT_Int         num_params,
+                  FT_Parameter*  params );
+
+  FT_LOCAL void
+  SFNT_Done_Face( TT_Face  face );
+
+
+FT_END_HEADER
+
+#endif /* __SFDRIVER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/t1afm.h b/libraries/freetype-2.0.5/include/t1afm.h
new file mode 100644 (file)
index 0000000..a828753
--- /dev/null
@@ -0,0 +1,66 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1afm.h                                                                */
+/*                                                                         */
+/*    AFM support for Type 1 fonts (specification).                        */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __T1AFM_H__
+#define __T1AFM_H__
+
+#include <ft2build.h>
+#include "t1objs.h"
+
+
+FT_BEGIN_HEADER
+
+
+  typedef struct  T1_Kern_Pair_
+  {
+    FT_UInt    glyph1;
+    FT_UInt    glyph2;
+    FT_Vector  kerning;
+
+  } T1_Kern_Pair;
+
+
+  typedef struct  T1_AFM_
+  {
+    FT_Int         num_pairs;
+    T1_Kern_Pair*  kern_pairs;
+
+  } T1_AFM;
+
+
+  FT_LOCAL FT_Error
+  T1_Read_AFM( FT_Face    face,
+               FT_Stream  stream );
+
+  FT_LOCAL void
+  T1_Done_AFM( FT_Memory  memory,
+               T1_AFM*    afm );
+
+  FT_LOCAL void
+  T1_Get_Kerning( T1_AFM*     afm,
+                  FT_UInt     glyph1,
+                  FT_UInt     glyph2,
+                  FT_Vector*  kerning );
+
+
+FT_END_HEADER
+
+#endif /* __T1AFM_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/t1decode.h b/libraries/freetype-2.0.5/include/t1decode.h
new file mode 100644 (file)
index 0000000..14dc043
--- /dev/null
@@ -0,0 +1,63 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1decode.h                                                             */
+/*                                                                         */
+/*    PostScript Type 1 decoding routines (specification).                 */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __T1DECODE_H__
+#define __T1DECODE_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_CALLBACK_TABLE
+  const T1_Decoder_Funcs  t1_decoder_funcs;
+
+
+  FT_LOCAL FT_Error
+  T1_Decoder_Parse_Glyph( T1_Decoder*  decoder,
+                          FT_UInt      glyph_index );
+
+  FT_LOCAL FT_Error
+  T1_Decoder_Parse_Charstrings( T1_Decoder*  decoder,
+                                FT_Byte*     base,
+                                FT_UInt      len );
+
+  FT_LOCAL FT_Error
+  T1_Decoder_Init( T1_Decoder*          decoder,
+                   FT_Face              face,
+                   FT_Size              size,
+                   FT_GlyphSlot         slot,
+                   FT_Byte**            glyph_names,
+                   T1_Blend*            blend,
+                   T1_Decoder_Callback  parse_glyph );
+
+  FT_LOCAL void
+  T1_Decoder_Done( T1_Decoder*  decoder );
+
+
+FT_END_HEADER
+
+#endif /* __T1DECODE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/t1driver.h b/libraries/freetype-2.0.5/include/t1driver.h
new file mode 100644 (file)
index 0000000..ce50800
--- /dev/null
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1driver.h                                                             */
+/*                                                                         */
+/*    High-level Type 1 driver interface (specification).                  */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __T1DRIVER_H__
+#define __T1DRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_EXPORT_VAR( const FT_Driver_Class )  t1_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __T1DRIVER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/t1errors.h b/libraries/freetype-2.0.5/include/t1errors.h
new file mode 100644 (file)
index 0000000..81221c3
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1errors.h                                                             */
+/*                                                                         */
+/*    Type 1 error codes (specification only).                             */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the Type 1 error enumeration constants.   */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __T1ERRORS_H__
+#define __T1ERRORS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  T1_Err_
+#define FT_ERR_BASE    FT_Mod_Err_Type1
+
+#include FT_ERRORS_H
+
+#endif /* __T1ERRORS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/t1gload.h b/libraries/freetype-2.0.5/include/t1gload.h
new file mode 100644 (file)
index 0000000..d1960e5
--- /dev/null
@@ -0,0 +1,46 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1gload.h                                                              */
+/*                                                                         */
+/*    Type 1 Glyph Loader (specification).                                 */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __T1GLOAD_H__
+#define __T1GLOAD_H__
+
+
+#include <ft2build.h>
+#include "t1objs.h"
+
+
+FT_BEGIN_HEADER
+
+
+  FT_LOCAL FT_Error
+  T1_Compute_Max_Advance( T1_Face  face,
+                          FT_Int*  max_advance );
+
+  FT_LOCAL FT_Error
+  T1_Load_Glyph( T1_GlyphSlot  glyph,
+                 T1_Size       size,
+                 FT_Int        glyph_index,
+                 FT_Int        load_flags );
+
+
+FT_END_HEADER
+
+#endif /* __T1GLOAD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/t1load.h b/libraries/freetype-2.0.5/include/t1load.h
new file mode 100644 (file)
index 0000000..23082bc
--- /dev/null
@@ -0,0 +1,84 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1load.h                                                               */
+/*                                                                         */
+/*    Type 1 font loader (specification).                                  */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __T1LOAD_H__
+#define __T1LOAD_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_MULTIPLE_MASTERS_H
+
+#include "t1parse.h"
+
+
+FT_BEGIN_HEADER
+
+
+  typedef struct  T1_Loader_
+  {
+    T1_ParserRec  parser;          /* parser used to read the stream */
+
+    FT_Int        num_chars;       /* number of characters in encoding */
+    PS_Table      encoding_table;  /* PS_Table used to store the       */
+                                   /* encoding character names         */
+
+    FT_Int        num_glyphs;
+    PS_Table      glyph_names;
+    PS_Table      charstrings;
+    PS_Table      swap_table;      /* For moving .notdef glyph to index 0. */
+
+    FT_Int        num_subrs;
+    PS_Table      subrs;
+    FT_Bool       fontdata;
+
+  } T1_Loader;
+
+
+  FT_LOCAL FT_Error
+  T1_Open_Face( T1_Face  face );
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+  FT_LOCAL FT_Error
+  T1_Get_Multi_Master( T1_Face           face,
+                       FT_Multi_Master*  master );
+
+  FT_LOCAL FT_Error
+  T1_Set_MM_Blend( T1_Face    face,
+                   FT_UInt    num_coords,
+                   FT_Fixed*  coords );
+
+  FT_LOCAL FT_Error
+  T1_Set_MM_Design( T1_Face   face,
+                    FT_UInt   num_coords,
+                    FT_Long*  coords );
+
+  FT_LOCAL void
+  T1_Done_Blend( T1_Face  face );
+
+#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+FT_END_HEADER
+
+#endif /* __T1LOAD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/t1objs.h b/libraries/freetype-2.0.5/include/t1objs.h
new file mode 100644 (file)
index 0000000..59e00e1
--- /dev/null
@@ -0,0 +1,160 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1objs.h                                                               */
+/*                                                                         */
+/*    Type 1 objects manager (specification).                              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __T1OBJS_H__
+#define __T1OBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  /* The following structures must be defined by the hinter */
+  typedef struct T1_Size_Hints_   T1_Size_Hints;
+  typedef struct T1_Glyph_Hints_  T1_Glyph_Hints;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_Driver                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 driver object.                                */
+  /*                                                                       */
+  typedef struct T1_DriverRec_   *T1_Driver;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_Size                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 size object.                                  */
+  /*                                                                       */
+  typedef struct T1_SizeRec_*  T1_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_GlyphSlot                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 glyph slot object.                            */
+  /*                                                                       */
+  typedef struct T1_GlyphSlotRec_*  T1_GlyphSlot;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_CharMap                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a Type 1 character mapping object.                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The Type 1 format doesn't use a charmap but an encoding table.     */
+  /*    The driver is responsible for making up charmap objects            */
+  /*    corresponding to these tables.                                     */
+  /*                                                                       */
+  typedef struct T1_CharMapRec_*   T1_CharMap;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                  HERE BEGINS THE TYPE1 SPECIFIC STUFF                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_SizeRec                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Type 1 size record.                                                */
+  /*                                                                       */
+  typedef struct  T1_SizeRec_
+  {
+    FT_SizeRec      root;
+    FT_Bool         valid;
+    T1_Size_Hints*  hints;  /* defined in the hinter. This allows */
+                            /* us to experiment with different    */
+                            /* hinting schemes without having to  */
+                            /* change `t1objs' each time.         */
+  } T1_SizeRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    T1_GlyphSlotRec                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Type 1 glyph slot record.                                          */
+  /*                                                                       */
+  typedef struct  T1_GlyphSlotRec_
+  {
+    FT_GlyphSlotRec  root;
+
+    FT_Bool          hint;
+    FT_Bool          scaled;
+
+    FT_Int           max_points;
+    FT_Int           max_contours;
+
+    FT_Fixed         x_scale;
+    FT_Fixed         y_scale;
+
+    T1_Glyph_Hints*  hints;  /* defined in the hinter */
+
+  } T1_GlyphSlotRec;
+
+
+  FT_LOCAL FT_Error
+  T1_Init_Face( FT_Stream      stream,
+                T1_Face        face,
+                FT_Int         face_index,
+                FT_Int         num_params,
+                FT_Parameter*  params );
+
+  FT_LOCAL void
+  T1_Done_Face( T1_Face  face );
+
+  FT_LOCAL FT_Error
+  T1_Init_Driver( T1_Driver  driver );
+
+  FT_LOCAL void
+  T1_Done_Driver( T1_Driver  driver );
+
+
+FT_END_HEADER
+
+#endif /* __T1OBJS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/t1parse.h b/libraries/freetype-2.0.5/include/t1parse.h
new file mode 100644 (file)
index 0000000..51be1b6
--- /dev/null
@@ -0,0 +1,134 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1parse.h                                                              */
+/*                                                                         */
+/*    Type 1 parser (specification).                                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __T1PARSE_H__
+#define __T1PARSE_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_TYPE1_TYPES_H
+#include FT_INTERNAL_STREAM_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    T1_ParserRec                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A T1_ParserRec is an object used to parse a Type 1 fonts very      */
+  /*    quickly.                                                           */
+  /*                                                                       */
+  /* <Fields>                                                              */
+  /*    root         :: The root parser.                                   */
+  /*                                                                       */
+  /*    stream       :: The current input stream.                          */
+  /*                                                                       */
+  /*    base_dict    :: A pointer to the top-level dictionary.             */
+  /*                                                                       */
+  /*    base_len     :: The length in bytes of the top dictionary.         */
+  /*                                                                       */
+  /*    private_dict :: A pointer to the private dictionary.               */
+  /*                                                                       */
+  /*    private_len  :: The length in bytes of the private dictionary.     */
+  /*                                                                       */
+  /*    in_pfb       :: A boolean.  Indicates that we are handling a PFB   */
+  /*                    file.                                              */
+  /*                                                                       */
+  /*    in_memory    :: A boolean.  Indicates a memory-based stream.       */
+  /*                                                                       */
+  /*    single_block :: A boolean.  Indicates that the private dictionary  */
+  /*                    is stored in lieu of the base dictionary.          */
+  /*                                                                       */
+  typedef struct  T1_ParserRec_
+  {
+    T1_Parser  root;
+    FT_Stream  stream;
+
+    FT_Byte*   base_dict;
+    FT_Int     base_len;
+
+    FT_Byte*   private_dict;
+    FT_Int     private_len;
+
+    FT_Byte    in_pfb;
+    FT_Byte    in_memory;
+    FT_Byte    single_block;
+
+  } T1_ParserRec;
+
+
+#define T1_Add_Table( p, i, o, l )  (p)->funcs.add( (p), i, o, l )
+#define T1_Done_Table( p )          \
+          do                        \
+          {                         \
+            if ( (p)->funcs.done )  \
+              (p)->funcs.done( p ); \
+          } while ( 0 )
+#define T1_Release_Table( p )          \
+          do                           \
+          {                            \
+            if ( (p)->funcs.release )  \
+              (p)->funcs.release( p ); \
+          } while ( 0 )
+
+
+#define T1_Skip_Spaces( p )  (p)->root.funcs.skip_spaces( &(p)->root )
+#define T1_Skip_Alpha( p )   (p)->root.funcs.skip_alpha ( &(p)->root )
+
+#define T1_ToInt( p )       (p)->root.funcs.to_int( &(p)->root )
+#define T1_ToFixed( p, t )  (p)->root.funcs.to_fixed( &(p)->root, t )
+
+#define T1_ToCoordArray( p, m, c )    \
+          (p)->root.funcs.to_coord_array( &(p)->root, m, c )
+#define T1_ToFixedArray( p, m, f, t ) \
+          (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
+#define T1_ToToken( p, t )            \
+          (p)->root.funcs.to_token( &(p)->root, t )
+#define T1_ToTokenArray( p, t, m, c ) \
+          (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
+
+#define T1_Load_Field( p, f, o, m, pf )       \
+          (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
+#define T1_Load_Field_Table( p, f, o, m, pf ) \
+          (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
+
+
+  FT_LOCAL FT_Error
+  T1_New_Parser( T1_ParserRec*     parser,
+                 FT_Stream         stream,
+                 FT_Memory         memory,
+                 PSAux_Interface*  psaux );
+
+  FT_LOCAL FT_Error
+  T1_Get_Private_Dict( T1_ParserRec*     parser,
+                       PSAux_Interface*  psaux );
+
+  FT_LOCAL void
+  T1_Finalize_Parser( T1_ParserRec*  parser );
+
+
+FT_END_HEADER
+
+#endif /* __T1PARSE_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/t1tokens.h b/libraries/freetype-2.0.5/include/t1tokens.h
new file mode 100644 (file)
index 0000000..f0a0c5d
--- /dev/null
@@ -0,0 +1,73 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1tokens.h                                                             */
+/*                                                                         */
+/*    Type 1 tokenizer (specification).                                    */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  T1_FontInfo
+#undef  T1CODE
+#define T1CODE        t1_field_font_info
+
+  T1_FIELD_STRING( "version", version )
+  T1_FIELD_STRING( "Notice", notice )
+  T1_FIELD_STRING( "FullName", full_name )
+  T1_FIELD_STRING( "FamilyName", family_name )
+  T1_FIELD_STRING( "Weight", weight )
+
+  T1_FIELD_NUM   ( "ItalicAngle", italic_angle )
+  T1_FIELD_BOOL  ( "isFixedPitch", is_fixed_pitch )
+  T1_FIELD_NUM   ( "UnderlinePosition", underline_position )
+  T1_FIELD_NUM   ( "UnderlineThickness", underline_thickness )
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  T1_Private
+#undef  T1CODE
+#define T1CODE        t1_field_private
+
+  T1_FIELD_NUM       ( "UniqueID", unique_id )
+  T1_FIELD_NUM       ( "lenIV", lenIV )
+  T1_FIELD_NUM       ( "LanguageGroup", language_group )
+  T1_FIELD_NUM       ( "password", password )
+
+  T1_FIELD_FIXED     ( "BlueScale", blue_scale )
+  T1_FIELD_NUM       ( "BlueShift", blue_shift )
+  T1_FIELD_NUM       ( "BlueFuzz",  blue_fuzz )
+
+  T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 )
+  T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 )
+  T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 )
+  T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 )
+
+  T1_FIELD_NUM_TABLE2( "StdHW", standard_width,  1 )
+  T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 )
+  T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 )
+
+  T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 )
+  T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 )
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  T1_Font
+#undef  T1CODE
+#define T1CODE        t1_field_font_dict
+
+  T1_FIELD_NUM( "PaintType", paint_type )
+  T1_FIELD_NUM( "FontType", font_type )
+  T1_FIELD_NUM( "StrokeWidth", stroke_width )
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ttcmap.h b/libraries/freetype-2.0.5/include/ttcmap.h
new file mode 100644 (file)
index 0000000..2dea02e
--- /dev/null
@@ -0,0 +1,45 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttcmap.h                                                               */
+/*                                                                         */
+/*    TrueType character mapping table (cmap) support (specification).     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTCMAP_H__
+#define __TTCMAP_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_LOCAL FT_Error
+  TT_CharMap_Load( TT_Face        face,
+                   TT_CMapTable*  cmap,
+                   FT_Stream      input );
+
+  FT_LOCAL FT_Error
+  TT_CharMap_Free( TT_Face        face,
+                   TT_CMapTable*  cmap );
+
+
+FT_END_HEADER
+
+#endif /* __TTCMAP_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ttdriver.h b/libraries/freetype-2.0.5/include/ttdriver.h
new file mode 100644 (file)
index 0000000..7c6f95e
--- /dev/null
@@ -0,0 +1,38 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttdriver.h                                                             */
+/*                                                                         */
+/*    High-level TrueType driver interface (specification).                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTDRIVER_H__
+#define __TTDRIVER_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_EXPORT_VAR( const FT_Driver_Class )  tt_driver_class;
+
+
+FT_END_HEADER
+
+#endif /* __TTDRIVER_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/tterrors.h b/libraries/freetype-2.0.5/include/tterrors.h
new file mode 100644 (file)
index 0000000..d317c70
--- /dev/null
@@ -0,0 +1,40 @@
+/***************************************************************************/
+/*                                                                         */
+/*  tterrors.h                                                             */
+/*                                                                         */
+/*    TrueType error codes (specification only).                           */
+/*                                                                         */
+/*  Copyright 2001 by                                                      */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file is used to define the TrueType error enumeration            */
+  /* constants.                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifndef __TTERRORS_H__
+#define __TTERRORS_H__
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#define FT_ERR_PREFIX  TT_Err_
+#define FT_ERR_BASE    FT_Mod_Err_TrueType
+
+#include FT_ERRORS_H
+
+#endif /* __TTERRORS_H__ */
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ttgload.h b/libraries/freetype-2.0.5/include/ttgload.h
new file mode 100644 (file)
index 0000000..ef0a4d7
--- /dev/null
@@ -0,0 +1,55 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttgload.h                                                              */
+/*                                                                         */
+/*    TrueType Glyph Loader (specification).                               */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTGLOAD_H__
+#define __TTGLOAD_H__
+
+
+#include <ft2build.h>
+#include "ttobjs.h"
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include "ttinterp.h"
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+  FT_LOCAL void
+  TT_Get_Metrics( TT_HoriHeader*  header,
+                  FT_UInt         index,
+                  FT_Short*       bearing,
+                  FT_UShort*      advance );
+
+  FT_LOCAL void
+  TT_Init_Glyph_Loading( TT_Face  face );
+
+  FT_LOCAL FT_Error
+  TT_Load_Glyph( TT_Size       size,
+                 TT_GlyphSlot  glyph,
+                 FT_UShort     glyph_index,
+                 FT_UInt       load_flags );
+
+
+FT_END_HEADER
+
+#endif /* __TTGLOAD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ttinterp.h b/libraries/freetype-2.0.5/include/ttinterp.h
new file mode 100644 (file)
index 0000000..f8d8781
--- /dev/null
@@ -0,0 +1,317 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttinterp.h                                                             */
+/*                                                                         */
+/*    TrueType bytecode interpreter (specification).                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTINTERP_H__
+#define __TTINTERP_H__
+
+
+#include <ft2build.h>
+#include "ttobjs.h"
+
+
+FT_BEGIN_HEADER
+
+
+#ifndef TT_CONFIG_OPTION_STATIC_INTEPRETER  /* indirect implementation */
+
+#define EXEC_OP_   TT_ExecContext  exc,
+#define EXEC_OP    TT_ExecContext  exc
+#define EXEC_ARG_  exc,
+#define EXEC_ARG   exc
+
+#else                                       /* static implementation */
+
+#define EXEC_OP_   /* void */
+#define EXEC_OP    /* void */
+#define EXEC_ARG_  /* void */
+#define EXEC_ARG   /* void */
+
+#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Rounding mode constants.                                              */
+  /*                                                                       */
+#define TT_Round_Off             5
+#define TT_Round_To_Half_Grid    0
+#define TT_Round_To_Grid         1
+#define TT_Round_To_Double_Grid  2
+#define TT_Round_Up_To_Grid      4
+#define TT_Round_Down_To_Grid    3
+#define TT_Round_Super           6
+#define TT_Round_Super_45        7
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Function types used by the interpreter, depending on various modes    */
+  /* (e.g. the rounding mode, whether to render a vertical or horizontal   */
+  /* line etc).                                                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /* Rounding function */
+  typedef FT_F26Dot6
+  (*TT_Round_Func)( EXEC_OP_ FT_F26Dot6  distance,
+                             FT_F26Dot6  compensation );
+
+  /* Point displacement along the freedom vector routine */
+  typedef void
+  (*TT_Move_Func)( EXEC_OP_ TT_GlyphZone*  zone,
+                            FT_UShort      point,
+                            FT_F26Dot6     distance );
+
+  /* Distance projection along one of the projection vectors */
+  typedef FT_F26Dot6
+  (*TT_Project_Func)( EXEC_OP_ FT_Vector*  v1,
+                               FT_Vector*  v2 );
+
+  /* reading a cvt value.  Take care of non-square pixels if necessary */
+  typedef FT_F26Dot6
+  (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong  index );
+
+  /* setting or moving a cvt value.  Take care of non-square pixels  */
+  /* if necessary                                                    */
+  typedef void
+  (*TT_Set_CVT_Func)( EXEC_OP_ FT_ULong    index,
+                               FT_F26Dot6  value );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This structure defines a call record, used to manage function calls.  */
+  /*                                                                       */
+  typedef struct  TT_CallRec_
+  {
+    FT_Int   Caller_Range;
+    FT_Long  Caller_IP;
+    FT_Long  Cur_Count;
+    FT_Long  Cur_Restart;
+
+  } TT_CallRec, *TT_CallStack;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The main structure for the interpreter which collects all necessary   */
+  /* variables and states.                                                 */
+  /*                                                                       */
+  typedef struct  TT_ExecContextRec_
+  {
+    TT_Face         face;
+    TT_Size         size;
+    FT_Memory       memory;
+
+    /* instructions state */
+
+    FT_Error        error;      /* last execution error */
+
+    FT_Long         top;        /* top of exec. stack   */
+
+    FT_UInt         stackSize;  /* size of exec. stack  */
+    FT_Long*        stack;      /* current exec. stack  */
+
+    FT_Long         args;
+    FT_UInt         new_top;    /* new top after exec.  */
+
+    TT_GlyphZone    zp0,        /* zone records */
+                    zp1,
+                    zp2,
+                    pts,
+                    twilight;
+
+    FT_Size_Metrics  metrics;
+    TT_Size_Metrics  tt_metrics; /* size metrics */
+
+    TT_GraphicsState  GS;         /* current graphics state */
+
+    FT_Int          curRange;  /* current code range number   */
+    FT_Byte*        code;      /* current code range          */
+    FT_Long         IP;        /* current instruction pointer */
+    FT_Long         codeSize;  /* size of current range       */
+
+    FT_Byte         opcode;    /* current opcode              */
+    FT_Int          length;    /* length of current opcode    */
+
+    FT_Bool         step_ins;  /* true if the interpreter must */
+                               /* increment IP after ins. exec */
+    FT_Long         cvtSize;
+    FT_Long*        cvt;
+
+    FT_UInt         glyphSize; /* glyph instructions buffer size */
+    FT_Byte*        glyphIns;  /* glyph instructions buffer */
+
+    FT_UInt         numFDefs;  /* number of function defs         */
+    FT_UInt         maxFDefs;  /* maximum number of function defs */
+    TT_DefArray     FDefs;     /* table of FDefs entries          */
+
+    FT_UInt         numIDefs;  /* number of instruction defs */
+    FT_UInt         maxIDefs;  /* maximum number of ins defs */
+    TT_DefArray     IDefs;     /* table of IDefs entries     */
+
+    FT_UInt         maxFunc;   /* maximum function index     */
+    FT_UInt         maxIns;    /* maximum instruction index  */
+
+    FT_Int          callTop,    /* top of call stack during execution */
+                    callSize;   /* size of call stack */
+    TT_CallStack    callStack;  /* call stack */
+
+    FT_UShort       maxPoints;    /* capacity of this context's `pts' */
+    FT_Short        maxContours;  /* record, expressed in points and  */
+                                  /* contours.                        */
+
+    TT_CodeRangeTable  codeRangeTable;  /* table of valid code ranges */
+                                        /* useful for the debugger   */
+
+    FT_UShort       storeSize;  /* size of current storage */
+    FT_Long*        storage;    /* storage area            */
+
+    FT_F26Dot6      period;     /* values used for the */
+    FT_F26Dot6      phase;      /* `SuperRounding'     */
+    FT_F26Dot6      threshold;
+
+#if 0
+    /* this seems to be unused */
+    FT_Int          cur_ppem;       /* ppem along the current proj vector */
+#endif
+
+    FT_Bool         instruction_trap;  /* If `True', the interpreter will */
+                                       /* exit after each instruction     */
+
+    TT_GraphicsState  default_GS;      /* graphics state resulting from    */
+                                       /* the prep program                 */
+    FT_Bool          is_composite;     /* true if the glyph is composite   */
+    FT_Bool          pedantic_hinting; /* true for pedantic interpretation */
+
+    /* latest interpreter additions */
+
+    FT_Long            F_dot_P;    /* dot product of freedom and projection */
+                                   /* vectors                               */
+    TT_Round_Func      func_round; /* current rounding function             */
+
+    TT_Project_Func    func_project,   /* current projection function */
+                       func_dualproj,  /* current dual proj. function */
+                       func_freeProj;  /* current freedom proj. func  */
+
+    TT_Move_Func       func_move;      /* current point move function */
+
+    TT_Get_CVT_Func    func_read_cvt;  /* read a cvt entry              */
+    TT_Set_CVT_Func    func_write_cvt; /* write a cvt entry (in pixels) */
+    TT_Set_CVT_Func    func_move_cvt;  /* incr a cvt entry (in pixels)  */
+
+    FT_ULong           loadSize;
+    TT_SubGlyph_Stack  loadStack;      /* loading subglyph stack */
+
+  } TT_ExecContextRec;
+
+
+  extern const TT_GraphicsState  tt_default_graphics_state;
+
+
+  FT_LOCAL FT_Error
+  TT_Goto_CodeRange( TT_ExecContext  exec,
+                     FT_Int          range,
+                     FT_Long         IP );
+
+  FT_LOCAL FT_Error
+  TT_Set_CodeRange( TT_ExecContext  exec,
+                    FT_Int          range,
+                    void*           base,
+                    FT_Long         length );
+
+  FT_LOCAL FT_Error
+  TT_Clear_CodeRange( TT_ExecContext  exec,
+                      FT_Int          range );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_New_Context                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Queries the face context for a given font.  Note that there is     */
+  /*    now a _single_ execution context in the TrueType driver which is   */
+  /*    shared among faces.                                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the source face object.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A handle to the execution context.  Initialized for `face'.        */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  FT_EXPORT( TT_ExecContext )
+  TT_New_Context( TT_Face  face );
+
+
+  FT_LOCAL FT_Error
+  TT_Done_Context( TT_ExecContext  exec );
+
+  FT_LOCAL FT_Error
+  TT_Destroy_Context( TT_ExecContext  exec,
+                      FT_Memory       memory );
+
+  FT_LOCAL FT_Error
+  TT_Load_Context( TT_ExecContext  exec,
+                   TT_Face         face,
+                   TT_Size         size );
+
+  FT_LOCAL FT_Error
+  TT_Save_Context( TT_ExecContext  exec,
+                   TT_Size         ins );
+
+  FT_LOCAL FT_Error
+  TT_Run_Context( TT_ExecContext  exec,
+                  FT_Bool         debug );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_RunIns                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Executes one or more instruction in the execution context.  This   */
+  /*    is the main function of the TrueType opcode interpreter.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    exec :: A handle to the target execution context.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the object manager and debugger should call this function.    */
+  /*                                                                       */
+  /*    This function is publicly exported because it is directly          */
+  /*    invoked by the TrueType debugger.                                  */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  TT_RunIns( TT_ExecContext  exec );
+
+
+FT_END_HEADER
+
+#endif /* __TTINTERP_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ttload.h b/libraries/freetype-2.0.5/include/ttload.h
new file mode 100644 (file)
index 0000000..2e67e03
--- /dev/null
@@ -0,0 +1,137 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttload.h                                                               */
+/*                                                                         */
+/*    Load the basic TrueType tables, i.e., tables that can be either in   */
+/*    TTF or OTF fonts (specification).                                    */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTLOAD_H__
+#define __TTLOAD_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_LOCAL TT_Table*
+  TT_LookUp_Table( TT_Face   face,
+                   FT_ULong  tag );
+
+  FT_LOCAL FT_Error
+  TT_Goto_Table( TT_Face    face,
+                 FT_ULong   tag,
+                 FT_Stream  stream,
+                 FT_ULong*  length );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_SFNT_Header( TT_Face       face,
+                       FT_Stream     stream,
+                       FT_Long       face_index,
+                       SFNT_Header*  sfnt );
+
+  FT_LOCAL FT_Error
+  TT_Load_Directory( TT_Face       face,
+                     FT_Stream     stream,
+                     SFNT_Header*  sfnt );
+
+  FT_LOCAL FT_Error
+  TT_Load_Any( TT_Face    face,
+               FT_ULong   tag,
+               FT_Long    offset,
+               FT_Byte*   buffer,
+               FT_ULong*  length );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_Header( TT_Face    face,
+                  FT_Stream  stream );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_Metrics_Header( TT_Face    face,
+                          FT_Stream  stream,
+                          FT_Bool    vertical );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_CMap( TT_Face    face,
+                FT_Stream  stream );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_MaxProfile( TT_Face    face,
+                      FT_Stream  stream );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_Names( TT_Face    face,
+                 FT_Stream  stream );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_OS2( TT_Face    face,
+               FT_Stream  stream );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_PostScript( TT_Face    face,
+                      FT_Stream  stream );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_Hdmx( TT_Face    face,
+                FT_Stream  stream );
+
+  FT_LOCAL FT_Error
+  TT_Load_PCLT( TT_Face    face,
+                FT_Stream  stream );
+
+  FT_LOCAL void
+  TT_Free_Names( TT_Face  face );
+
+
+  FT_LOCAL void
+  TT_Free_Hdmx ( TT_Face  face );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_Kern( TT_Face    face,
+                FT_Stream  stream );
+
+
+  FT_LOCAL FT_Error
+  TT_Load_Gasp( TT_Face    face,
+                FT_Stream  stream );
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+  FT_LOCAL FT_Error
+  TT_Load_Bitmap_Header( TT_Face    face,
+                         FT_Stream  stream );
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+
+FT_END_HEADER
+
+#endif /* __TTLOAD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ttobjs.h b/libraries/freetype-2.0.5/include/ttobjs.h
new file mode 100644 (file)
index 0000000..d780ce4
--- /dev/null
@@ -0,0 +1,422 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttobjs.h                                                               */
+/*                                                                         */
+/*    Objects manager (specification).                                     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTOBJS_H__
+#define __TTOBJS_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_Driver                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType driver object.                              */
+  /*                                                                       */
+  typedef struct TT_DriverRec_*  TT_Driver;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_Instance                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType size object.                                */
+  /*                                                                       */
+  typedef struct TT_SizeRec_*  TT_Size;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    TT_GlyphSlot                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A handle to a TrueType glyph slot object.                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This is a direct typedef of FT_GlyphSlot, as there is nothing      */
+  /*    specific about the TrueType glyph slot.                            */
+  /*                                                                       */
+  typedef FT_GlyphSlot  TT_GlyphSlot;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    TT_GraphicsState                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The TrueType graphics state used during bytecode interpretation.   */
+  /*                                                                       */
+  typedef struct  TT_GraphicsState_
+  {
+    FT_UShort      rp0;
+    FT_UShort      rp1;
+    FT_UShort      rp2;
+
+    FT_UnitVector  dualVector;
+    FT_UnitVector  projVector;
+    FT_UnitVector  freeVector;
+
+    FT_Long        loop;
+    FT_F26Dot6     minimum_distance;
+    FT_Int         round_state;
+
+    FT_Bool        auto_flip;
+    FT_F26Dot6     control_value_cutin;
+    FT_F26Dot6     single_width_cutin;
+    FT_F26Dot6     single_width_value;
+    FT_Short       delta_base;
+    FT_Short       delta_shift;
+
+    FT_Byte        instruct_control;
+    FT_Bool        scan_control;
+    FT_Int         scan_type;
+
+    FT_UShort      gep0;
+    FT_UShort      gep1;
+    FT_UShort      gep2;
+
+  } TT_GraphicsState;
+
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+  FT_LOCAL void
+  TT_Done_GlyphZone( TT_GlyphZone*  zone );
+
+  FT_LOCAL FT_Error
+  TT_New_GlyphZone( FT_Memory      memory,
+                    FT_UShort      maxPoints,
+                    FT_Short       maxContours,
+                    TT_GlyphZone*  zone );
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  EXECUTION SUBTABLES                                                  */
+  /*                                                                       */
+  /*  These sub-tables relate to instruction execution.                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define TT_MAX_CODE_RANGES  3
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* There can only be 3 active code ranges at once:                       */
+  /*   - the Font Program                                                  */
+  /*   - the CVT Program                                                   */
+  /*   - a glyph's instructions set                                        */
+  /*                                                                       */
+  typedef enum  TT_CodeRange_Tag_
+  {
+    tt_coderange_none = 0,
+    tt_coderange_font,
+    tt_coderange_cvt,
+    tt_coderange_glyph
+
+  } TT_CodeRange_Tag;
+
+
+  typedef struct  TT_CodeRange_
+  {
+    FT_Byte*  base;
+    FT_ULong  size;
+
+  } TT_CodeRange;
+
+  typedef TT_CodeRange  TT_CodeRangeTable[TT_MAX_CODE_RANGES];
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Defines a function/instruction definition record.                     */
+  /*                                                                       */
+  typedef struct  TT_DefRecord_
+  {
+    FT_Int   range;      /* in which code range is it located? */
+    FT_Long  start;      /* where does it start?               */
+    FT_UInt  opc;        /* function #, or instruction code    */
+    FT_Bool  active;     /* is it active?                      */
+
+  } TT_DefRecord, *TT_DefArray;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Subglyph transformation record.                                       */
+  /*                                                                       */
+  typedef struct  TT_Transform_
+  {
+    FT_Fixed    xx, xy;     /* transformation matrix coefficients */
+    FT_Fixed    yx, yy;
+    FT_F26Dot6  ox, oy;     /* offsets        */
+
+  } TT_Transform;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Subglyph loading record.  Used to load composite components.          */
+  /*                                                                       */
+  typedef struct  TT_SubglyphRec_
+  {
+    FT_Long       index;        /* subglyph index; initialized with -1 */
+    FT_Bool       is_scaled;    /* is the subglyph scaled?             */
+    FT_Bool       is_hinted;    /* should it be hinted?                */
+    FT_Bool       preserve_pps; /* preserve phantom points?            */
+
+    FT_Long       file_offset;
+
+    FT_BBox       bbox;
+    FT_Pos        left_bearing;
+    FT_Pos        advance;
+
+    TT_GlyphZone  zone;
+
+    FT_Long       arg1;         /* first argument                      */
+    FT_Long       arg2;         /* second argument                     */
+
+    FT_UShort     element_flag; /* current load element flag           */
+
+    TT_Transform  transform;    /* transformation matrix               */
+
+    FT_Vector     pp1, pp2;     /* phantom points                      */
+
+  } TT_SubGlyphRec, *TT_SubGlyph_Stack;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A note regarding non-squared pixels:                                  */
+  /*                                                                       */
+  /* (This text will probably go into some docs at some time; for now, it  */
+  /*  is kept here to explain some definitions in the TIns_Metrics         */
+  /*  record).                                                             */
+  /*                                                                       */
+  /* The CVT is a one-dimensional array containing values that control     */
+  /* certain important characteristics in a font, like the height of all   */
+  /* capitals, all lowercase letter, default spacing or stem width/height. */
+  /*                                                                       */
+  /* These values are found in FUnits in the font file, and must be scaled */
+  /* to pixel coordinates before being used by the CVT and glyph programs. */
+  /* Unfortunately, when using distinct x and y resolutions (or distinct x */
+  /* and y pointsizes), there are two possible scalings.                   */
+  /*                                                                       */
+  /* A first try was to implement a `lazy' scheme where all values were    */
+  /* scaled when first used.  However, while some values are always used   */
+  /* in the same direction, some others are used under many different      */
+  /* circumstances and orientations.                                       */
+  /*                                                                       */
+  /* I have found a simpler way to do the same, and it even seems to work  */
+  /* in most of the cases:                                                 */
+  /*                                                                       */
+  /* - All CVT values are scaled to the maximum ppem size.                 */
+  /*                                                                       */
+  /* - When performing a read or write in the CVT, a ratio factor is used  */
+  /*   to perform adequate scaling.  Example:                              */
+  /*                                                                       */
+  /*     x_ppem = 14                                                       */
+  /*     y_ppem = 10                                                       */
+  /*                                                                       */
+  /*   We choose ppem = x_ppem = 14 as the CVT scaling size.  All cvt      */
+  /*   entries are scaled to it.                                           */
+  /*                                                                       */
+  /*     x_ratio = 1.0                                                     */
+  /*     y_ratio = y_ppem/ppem (< 1.0)                                     */
+  /*                                                                       */
+  /*   We compute the current ratio like:                                  */
+  /*                                                                       */
+  /*   - If projVector is horizontal,                                      */
+  /*       ratio = x_ratio = 1.0                                           */
+  /*                                                                       */
+  /*   - if projVector is vertical,                                        */
+  /*       ratio = y_ratio                                                 */
+  /*                                                                       */
+  /*   - else,                                                             */
+  /*       ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */
+  /*                                                                       */
+  /*   Reading a cvt value returns                                         */
+  /*     ratio * cvt[index]                                                */
+  /*                                                                       */
+  /*   Writing a cvt value in pixels:                                      */
+  /*     cvt[index] / ratio                                                */
+  /*                                                                       */
+  /*   The current ppem is simply                                          */
+  /*     ratio * ppem                                                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Metrics used by the TrueType size and context objects.                */
+  /*                                                                       */
+  typedef struct  TT_Size_Metrics_
+  {
+    /* for non-square pixels */
+    FT_Long     x_ratio;
+    FT_Long     y_ratio;
+
+    FT_UShort   ppem;               /* maximum ppem size              */
+    FT_Long     ratio;              /* current ratio                  */
+    FT_Fixed    scale;
+
+    FT_F26Dot6  compensations[4];   /* device-specific compensations  */
+
+    FT_Bool     valid;
+
+    FT_Bool     rotated;            /* `is the glyph rotated?'-flag   */
+    FT_Bool     stretched;          /* `is the glyph stretched?'-flag */
+
+  } TT_Size_Metrics;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* TrueType size class.                                                  */
+  /*                                                                       */
+  typedef struct  TT_SizeRec_
+  {
+    FT_SizeRec         root;
+
+    TT_Size_Metrics    ttmetrics;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    FT_UInt            strike_index;    /* 0xFFFF to indicate invalid */
+    FT_Size_Metrics    strike_metrics;  /* current strike's metrics   */
+
+#endif
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    FT_UInt            num_function_defs; /* number of function definitions */
+    FT_UInt            max_function_defs;
+    TT_DefArray        function_defs;     /* table of function definitions  */
+
+    FT_UInt            num_instruction_defs;  /* number of ins. definitions */
+    FT_UInt            max_instruction_defs;
+    TT_DefArray        instruction_defs;      /* table of ins. definitions  */
+
+    FT_UInt            max_func;
+    FT_UInt            max_ins;
+
+    TT_CodeRangeTable  codeRangeTable;
+
+    TT_GraphicsState   GS;
+
+    FT_ULong           cvt_size;      /* the scaled control value table */
+    FT_Long*           cvt;
+
+    FT_UShort          storage_size; /* The storage area is now part of */
+    FT_Long*           storage;      /* the instance                    */
+
+    TT_GlyphZone       twilight;     /* The instance's twilight zone    */
+
+    /* debugging variables */
+
+    /* When using the debugger, we must keep the */
+    /* execution context tied to the instance    */
+    /* object rather than asking it on demand.   */
+
+    FT_Bool            debug;
+    TT_ExecContext     context;
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+  } TT_SizeRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* TrueType driver class.                                                */
+  /*                                                                       */
+  typedef struct  TT_DriverRec_
+  {
+    FT_DriverRec    root;
+    TT_ExecContext  context;  /* execution context        */
+    TT_GlyphZone    zone;     /* glyph loader points zone */
+
+    void*           extension_component;
+
+  } TT_DriverRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Face functions                                                        */
+  /*                                                                       */
+  FT_LOCAL FT_Error
+  TT_Init_Face( FT_Stream      stream,
+                TT_Face        face,
+                FT_Int         face_index,
+                FT_Int         num_params,
+                FT_Parameter*  params );
+
+  FT_LOCAL void
+  TT_Done_Face( TT_Face  face );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Size functions                                                        */
+  /*                                                                       */
+  FT_LOCAL FT_Error
+  TT_Init_Size( TT_Size  size );
+
+  FT_LOCAL void
+  TT_Done_Size( TT_Size  size );
+
+  FT_LOCAL FT_Error
+  TT_Reset_Size( TT_Size  size );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Driver functions                                                      */
+  /*                                                                       */
+  FT_LOCAL FT_Error
+  TT_Init_Driver( TT_Driver  driver );
+
+  FT_LOCAL void
+  TT_Done_Driver( TT_Driver  driver );
+
+
+FT_END_HEADER
+
+#endif /* __TTOBJS_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ttpload.h b/libraries/freetype-2.0.5/include/ttpload.h
new file mode 100644 (file)
index 0000000..83b0b3a
--- /dev/null
@@ -0,0 +1,48 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttpload.h                                                              */
+/*                                                                         */
+/*    TrueType glyph data/program tables loader (specification).           */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTPLOAD_H__
+#define __TTPLOAD_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_LOCAL FT_Error
+  TT_Load_Locations( TT_Face    face,
+                     FT_Stream  stream );
+
+  FT_LOCAL FT_Error
+  TT_Load_CVT( TT_Face    face,
+               FT_Stream  stream );
+
+  FT_LOCAL FT_Error
+  TT_Load_Programs( TT_Face    face,
+                    FT_Stream  stream );
+
+
+FT_END_HEADER
+
+#endif /* __TTPLOAD_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ttpost.h b/libraries/freetype-2.0.5/include/ttpost.h
new file mode 100644 (file)
index 0000000..2c30122
--- /dev/null
@@ -0,0 +1,46 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttpost.h                                                               */
+/*                                                                         */
+/*    Postcript name table processing for TrueType and OpenType fonts      */
+/*    (specification).                                                     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTPOST_H__
+#define __TTPOST_H__
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_LOCAL FT_Error
+  TT_Get_PS_Name( TT_Face      face,
+                  FT_UInt      index,
+                  FT_String**  PSname );
+
+  FT_LOCAL void
+  TT_Free_Post_Names( TT_Face  face );
+
+
+FT_END_HEADER
+
+#endif /* __TTPOST_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/ttsbit.h b/libraries/freetype-2.0.5/include/ttsbit.h
new file mode 100644 (file)
index 0000000..2e0c236
--- /dev/null
@@ -0,0 +1,59 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttsbit.h                                                               */
+/*                                                                         */
+/*    TrueType and OpenType embedded bitmap support (specification).       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __TTSBIT_H__
+#define __TTSBIT_H__
+
+
+#include <ft2build.h>
+#include "ttload.h"
+
+
+FT_BEGIN_HEADER
+
+
+  FT_LOCAL FT_Error
+  TT_Load_SBit_Strikes( TT_Face    face,
+                        FT_Stream  stream );
+
+  FT_LOCAL void
+  TT_Free_SBit_Strikes( TT_Face  face );
+
+
+  FT_LOCAL FT_Error
+  TT_Set_SBit_Strike( TT_Face    face,
+                      FT_Int     x_ppem,
+                      FT_Int     y_ppem,
+                      FT_ULong  *astrike_index );
+
+  FT_LOCAL FT_Error
+  TT_Load_SBit_Image( TT_Face           face,
+                      FT_ULong          strike_index,
+                      FT_UInt           glyph_index,
+                      FT_UInt           load_flags,
+                      FT_Stream         stream,
+                      FT_Bitmap        *map,
+                      TT_SBit_Metrics  *metrics );
+
+
+FT_END_HEADER
+
+#endif /* __TTSBIT_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/include/winfnt.h b/libraries/freetype-2.0.5/include/winfnt.h
new file mode 100644 (file)
index 0000000..e3b6c55
--- /dev/null
@@ -0,0 +1,39 @@
+/***************************************************************************/
+/*                                                                         */
+/*  winfnt.h                                                               */
+/*                                                                         */
+/*    FreeType font driver for Windows FNT/FON files                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __WINFNT_H__
+#define __WINFNT_H__
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DRIVER_H
+
+
+FT_BEGIN_HEADER
+
+
+  FT_EXPORT_VAR( const FT_Driver_Class )  winfnt_driver_class;
+
+
+FT_END_HEADER
+
+
+#endif /* __WINFNT_H__ */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/license.txt b/libraries/freetype-2.0.5/license.txt
new file mode 100644 (file)
index 0000000..741bc9f
--- /dev/null
@@ -0,0 +1,10 @@
+
+FreeType comes with two licenses from which you can choose the one which
+fits your needs best:
+
+  . The FreeType License, in file `docs/FTL.txt'.
+
+  . The GNU General Public License, in file `docs/GPL.txt'.
+
+The contributed PCF driver comes with a license similar to that of X Windows
+which is compatible to the above two licenses (see file src/pcf/readme).
diff --git a/libraries/freetype-2.0.5/pcf.c b/libraries/freetype-2.0.5/pcf.c
new file mode 100644 (file)
index 0000000..315655e
--- /dev/null
@@ -0,0 +1,36 @@
+/*  pcf.c
+
+    FreeType font driver for pcf fonts
+
+  Copyright 2000-2001 by
+  Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+
+#include <ft2build.h>
+#include "pcfutil.c"
+#include "pcfread.c"
+#include "pcfdriver.c"
+
+/* END */
diff --git a/libraries/freetype-2.0.5/pcfdriver.c b/libraries/freetype-2.0.5/pcfdriver.c
new file mode 100644 (file)
index 0000000..6c34524
--- /dev/null
@@ -0,0 +1,345 @@
+/*  pcfdriver.c
+
+    FreeType font driver for pcf files
+
+    Copyright (C) 2000-2001 by
+    Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#include <ft2build.h>
+
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "pcf.h"
+#include "pcfdriver.h"
+#include "pcfutil.h"
+
+#include "pcferror.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_pcfdriver
+
+
+  FT_LOCAL_DEF FT_Error
+  PCF_Done_Face( PCF_Face  face )
+  {
+    FT_Memory    memory = FT_FACE_MEMORY( face );
+    PCF_Property tmp    = face->properties;
+    int i;
+
+
+    FREE( face->encodings );
+    FREE( face->metrics );
+
+    for ( i = 0; i < face->nprops; i++ )
+    {
+      FREE( tmp->name );
+      if ( tmp->isString )
+        FREE( tmp->value );
+    }
+    FREE( face->properties );
+
+    FT_TRACE4(( "DONE_FACE!!!\n" ));
+
+    return PCF_Err_Ok;
+  }
+
+
+  static FT_Error
+  PCF_Init_Face( FT_Stream      stream,
+                 PCF_Face       face,
+                 FT_Int         face_index,
+                 FT_Int         num_params,
+                 FT_Parameter*  params )
+  {
+    FT_Error  error = PCF_Err_Ok;
+
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+    FT_UNUSED( face_index );
+
+
+    error = pcf_load_font( stream, face );
+    if ( error )
+      goto Fail;
+
+    return PCF_Err_Ok;
+
+  Fail:
+    FT_TRACE2(( "[not a valid PCF file]\n" ));
+    PCF_Done_Face( face );
+
+    return PCF_Err_Unknown_File_Format; /* error */
+  }
+
+
+  static FT_Error
+  PCF_Set_Pixel_Size( FT_Size  size )
+  {
+    PCF_Face face = (PCF_Face)FT_SIZE_FACE( size );
+
+
+    FT_TRACE4(( "rec %d - pres %d\n", size->metrics.y_ppem,
+                                      face->root.available_sizes->height ));
+
+    if ( size->metrics.y_ppem == face->root.available_sizes->height )
+    {
+      size->metrics.ascender  = face->accel.fontAscent << 6;
+      size->metrics.descender = face->accel.fontDescent * (-64);
+#if 0
+      size->metrics.height    = face->accel.maxbounds.ascent << 6;
+#endif
+      size->metrics.height    = size->metrics.ascender -
+                                size->metrics.descender;
+
+      return PCF_Err_Ok;
+    }
+    else
+    {
+      FT_TRACE4(( "size WRONG\n" ));
+      return PCF_Err_Invalid_Pixel_Size;
+    }
+  }
+
+
+  static FT_Error
+  PCF_Load_Glyph( FT_GlyphSlot  slot,
+                  FT_Size       size,
+                  FT_UInt       glyph_index,
+                  FT_Int        load_flags )
+  {
+    PCF_Face    face   = (PCF_Face)FT_SIZE_FACE( size );
+    FT_Error    error  = PCF_Err_Ok;
+    FT_Memory   memory = FT_FACE(face)->memory;
+    FT_Bitmap*  bitmap = &slot->bitmap;
+    PCF_Metric  metric;
+    int         bytes;
+
+    FT_Stream   stream = face->root.stream;
+
+    FT_UNUSED( load_flags );
+
+
+    FT_TRACE4(( "load_glyph %d ---", glyph_index ));
+
+    if ( !face )
+    {
+      error = PCF_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    metric = face->metrics + glyph_index;
+
+    bitmap->rows       = metric->ascent + metric->descent;
+    bitmap->width      = metric->rightSideBearing - metric->leftSideBearing;
+    bitmap->num_grays  = 1;
+    bitmap->pixel_mode = ft_pixel_mode_mono;
+
+    FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
+                  PCF_BIT_ORDER( face->bitmapsFormat ),
+                  PCF_BYTE_ORDER( face->bitmapsFormat ),
+                  PCF_GLYPH_PAD( face->bitmapsFormat ) ));
+
+    switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
+    {
+    case 1:
+      bitmap->pitch = ( bitmap->width + 7 ) >> 3;
+      break;
+
+    case 2:
+      bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
+      break;
+
+    case 4:
+      bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
+      break;
+
+    case 8:
+      bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
+      break;
+
+    default:
+      return PCF_Err_Invalid_File_Format;
+    }
+
+    /* XXX: to do: are there cases that need repadding the bitmap? */
+    bytes = bitmap->pitch * bitmap->rows;
+
+    if ( ALLOC( bitmap->buffer, bytes ) )
+      goto Exit;
+
+    if ( FILE_Seek( metric->bits )        ||
+         FILE_Read( bitmap->buffer, bytes ) )
+      goto Exit;
+
+    if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
+      BitOrderInvert( bitmap->buffer,bytes );
+
+    if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
+           PCF_BIT_ORDER( face->bitmapsFormat )  ) )
+    {
+      switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
+      {
+      case 1:
+        break;
+
+      case 2:
+        TwoByteSwap( bitmap->buffer, bytes );
+        break;
+
+      case 4:
+        FourByteSwap( bitmap->buffer, bytes );
+        break;
+      }
+    }
+
+    slot->bitmap_left = metric->leftSideBearing;
+    slot->bitmap_top  = metric->ascent;
+
+    slot->metrics.horiAdvance  = metric->characterWidth << 6 ;
+    slot->metrics.horiBearingX = metric->rightSideBearing << 6 ;
+    slot->metrics.horiBearingY = metric->ascent << 6 ;
+    slot->metrics.width        = metric->characterWidth << 6 ;
+    slot->metrics.height       = bitmap->rows << 6;
+
+    slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16;
+    slot->format            = ft_glyph_format_bitmap;
+    slot->flags             = ft_glyph_own_bitmap;
+
+    FT_TRACE4(( " --- ok\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_UInt
+  PCF_Get_Char_Index( FT_CharMap  charmap,
+                      FT_Long     char_code )
+  {
+    PCF_Face      face     = (PCF_Face)charmap->face;
+    PCF_Encoding  en_table = face->encodings;
+    int           low, high, mid;
+
+
+    FT_TRACE4(( "get_char_index %ld\n", char_code ));
+
+    low = 0;
+    high = face->nencodings - 1;
+    while ( low <= high )
+    {
+      mid = ( low + high ) / 2;
+      if ( char_code < en_table[mid].enc )
+        high = mid - 1;
+      else if ( char_code > en_table[mid].enc )
+        low = mid + 1;
+      else
+        return en_table[mid].glyph;
+    }
+
+    return 0;
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Driver_Class  pcf_driver_class =
+  {
+    {
+      ft_module_font_driver,
+      sizeof ( FT_DriverRec ),
+
+      "pcf",
+      0x10000L,
+      0x20000L,
+
+      0,
+
+      (FT_Module_Constructor)0,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    sizeof( PCF_FaceRec ),
+    sizeof( FT_SizeRec ),
+    sizeof( FT_GlyphSlotRec ),
+
+    (FTDriver_initFace)     PCF_Init_Face,
+    (FTDriver_doneFace)     PCF_Done_Face,
+    (FTDriver_initSize)     0,
+    (FTDriver_doneSize)     0,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) PCF_Set_Pixel_Size,
+    (FTDriver_setPixelSizes)PCF_Set_Pixel_Size,
+
+    (FTDriver_loadGlyph)    PCF_Load_Glyph,
+    (FTDriver_getCharIndex) PCF_Get_Char_Index,
+
+    (FTDriver_getKerning)   0,
+    (FTDriver_attachFile)   0,
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverClass                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the TrueType driver as a      */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+  FT_EXPORT_DEF( const FT_Driver_Class* )
+  getDriverClass( void )
+  {
+    return &pcf_driver_class;
+  }
+
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/pcfread.c b/libraries/freetype-2.0.5/pcfread.c
new file mode 100644 (file)
index 0000000..eac265e
--- /dev/null
@@ -0,0 +1,1065 @@
+/*  pcfread.c
+
+    FreeType font driver for pcf fonts
+
+  Copyright 2000-2001 by
+  Francesco Zappa Nardelli
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#include <ft2build.h>
+
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "pcf.h"
+#include "pcfdriver.h"
+
+#include "pcferror.h"
+
+#include <string.h>     /* strlen(), strcpy() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_pcfread
+
+
+#if defined( FT_DEBUG_LEVEL_TRACE )
+  static char*  tableNames[] =
+  {
+    "prop", "accl", "mtrcs", "bmps", "imtrcs",
+    "enc", "swidth", "names", "accel"
+  };
+#endif
+
+
+  static
+  const FT_Frame_Field  pcf_toc_header[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PCF_TocRec
+
+    FT_FRAME_START( 8 ),
+      FT_FRAME_ULONG_LE( version ),
+      FT_FRAME_ULONG_LE( count ),
+    FT_FRAME_END
+  };
+
+
+  static
+  const FT_Frame_Field  pcf_table_header[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PCF_TableRec
+
+    FT_FRAME_START( 16  ),
+      FT_FRAME_ULONG_LE( type ),
+      FT_FRAME_ULONG_LE( format ),
+      FT_FRAME_ULONG_LE( size ),
+      FT_FRAME_ULONG_LE( offset ),
+    FT_FRAME_END
+  };
+
+
+  static FT_Error
+  pcf_read_TOC( FT_Stream  stream,
+                PCF_Face   face )
+  {
+    FT_Error   error;
+    PCF_Toc    toc = &face->toc;
+    PCF_Table  tables;
+
+    FT_Memory     memory = FT_FACE(face)->memory;
+    unsigned int  i;
+
+
+    if ( FILE_Seek ( 0 )                   ||
+         READ_Fields ( pcf_toc_header, toc ) )
+      return PCF_Err_Cannot_Open_Resource;
+
+    if ( toc->version != PCF_FILE_VERSION )
+      return PCF_Err_Invalid_File_Format;
+
+    if ( ALLOC( face->toc.tables, toc->count * sizeof ( PCF_TableRec ) ) )
+      return PCF_Err_Out_Of_Memory;
+
+    tables = face->toc.tables;
+    for ( i = 0; i < toc->count; i++ )
+    {
+      if ( READ_Fields( pcf_table_header, tables ) )
+        goto Exit;
+      tables++;
+    }
+
+#if defined( FT_DEBUG_LEVEL_TRACE )
+
+    {
+      unsigned int  i,j;
+      char*         name = "?";
+
+
+      FT_TRACE4(( "Tables count: %ld\n", face->toc.count ));
+      tables = face->toc.tables;
+      for ( i = 0; i < toc->count; i++ )
+      {
+        for( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ )
+          if ( tables[i].type == (unsigned int)( 1 << j ) )
+            name=tableNames[j];
+        FT_TRACE4(( "Table %d: type=%-6s format=0x%04lX "
+                    "size=0x%06lX (%8ld) offset=0x%04lX\n",
+                    i, name,
+                    tables[i].format,
+                    tables[i].size, tables[i].size,
+                    tables[i].offset ));
+      }
+    }
+
+#endif
+
+    return PCF_Err_Ok;
+
+  Exit:
+    FREE( face->toc.tables );
+    return error;
+  }
+
+
+  static
+  const FT_Frame_Field  pcf_metric_header[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PCF_MetricRec
+
+    FT_FRAME_START( 12 ),
+      FT_FRAME_SHORT_LE( leftSideBearing ),
+      FT_FRAME_SHORT_LE( rightSideBearing ),
+      FT_FRAME_SHORT_LE( characterWidth ),
+      FT_FRAME_SHORT_LE( ascent ),
+      FT_FRAME_SHORT_LE( descent ),
+      FT_FRAME_SHORT_LE( attributes ),
+    FT_FRAME_END
+  };
+
+
+  static
+  const FT_Frame_Field  pcf_metric_msb_header[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PCF_MetricRec
+
+    FT_FRAME_START( 12 ),
+      FT_FRAME_SHORT( leftSideBearing ),
+      FT_FRAME_SHORT( rightSideBearing ),
+      FT_FRAME_SHORT( characterWidth ),
+      FT_FRAME_SHORT( ascent ),
+      FT_FRAME_SHORT( descent ),
+      FT_FRAME_SHORT( attributes ),
+    FT_FRAME_END
+  };
+
+
+  static
+  const FT_Frame_Field  pcf_compressed_metric_header[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PCF_Compressed_MetricRec
+
+    FT_FRAME_START( 5 ),
+      FT_FRAME_BYTE( leftSideBearing ),
+      FT_FRAME_BYTE( rightSideBearing ),
+      FT_FRAME_BYTE( characterWidth ),
+      FT_FRAME_BYTE( ascent ),
+      FT_FRAME_BYTE( descent ),
+    FT_FRAME_END
+  };
+
+
+  static FT_Error
+  pcf_parse_metric( FT_Stream              stream,
+                    const FT_Frame_Field*  header,
+                    PCF_Metric             metric )
+  {
+    FT_Error  error = PCF_Err_Ok;
+
+
+    if ( READ_Fields( header, metric ) )
+      return error;
+
+    return PCF_Err_Ok;
+  }
+
+
+  static FT_Error
+  pcf_parse_compressed_metric( FT_Stream   stream,
+                               PCF_Metric  metric )
+  {
+    PCF_Compressed_MetricRec  compr_metric;
+    FT_Error                  error = PCF_Err_Ok;
+
+
+    if ( READ_Fields( pcf_compressed_metric_header, &compr_metric ) )
+      return error;
+
+    metric->leftSideBearing =
+      (FT_Short)( compr_metric.leftSideBearing - 0x80 );
+    metric->rightSideBearing =
+      (FT_Short)( compr_metric.rightSideBearing - 0x80 );
+    metric->characterWidth =
+      (FT_Short)( compr_metric.characterWidth - 0x80 );
+    metric->ascent =
+      (FT_Short)( compr_metric.ascent - 0x80 );
+    metric->descent =
+      (FT_Short)( compr_metric.descent - 0x80 );
+    metric->attributes = 0;
+
+    return PCF_Err_Ok;
+  }
+
+
+  static FT_Error
+  pcf_get_metric( FT_Stream   stream,
+                  FT_ULong    format,
+                  PCF_Metric  metric )
+  {
+    FT_Error error = PCF_Err_Ok;
+
+
+    if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+    {
+      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+        error = pcf_parse_metric( stream, pcf_metric_msb_header, metric );
+      else
+        error = pcf_parse_metric( stream, pcf_metric_header, metric );
+    }
+    else
+      error = pcf_parse_compressed_metric( stream, metric );
+
+    return error;
+  }
+
+
+  static FT_Error
+  pcfSeekToType( FT_Stream  stream,
+                 PCF_Table  tables,
+                 int        ntables,
+                 FT_ULong   type,
+                 FT_ULong*  formatp,
+                 FT_ULong*  sizep )
+  {
+    FT_Error error;
+    int      i;
+
+
+    for ( i = 0; i < ntables; i++ )
+      if ( tables[i].type == type )
+      {
+        if ( stream->pos > tables[i].offset )
+          return PCF_Err_Invalid_Stream_Skip;
+        if ( FILE_Skip( tables[i].offset - stream->pos ) )
+          return PCF_Err_Invalid_Stream_Skip;
+        *sizep   = tables[i].size;  /* unused - to be removed */
+        *formatp = tables[i].format;
+        return PCF_Err_Ok;
+      }
+
+    return PCF_Err_Invalid_File_Format;
+  }
+
+
+  static FT_Bool
+  pcfHasType( PCF_Table  tables,
+              int        ntables,
+              FT_ULong   type )
+  {
+    int i;
+
+
+    for ( i = 0; i < ntables; i++ )
+      if ( tables[i].type == type )
+        return TRUE;
+
+    return FALSE;
+  }
+
+
+  static
+  const FT_Frame_Field  pcf_property_header[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PCF_ParsePropertyRec
+
+    FT_FRAME_START( 9 ),
+      FT_FRAME_LONG_LE( name ),
+      FT_FRAME_BYTE   ( isString ),
+      FT_FRAME_LONG_LE( value ),
+    FT_FRAME_END
+  };
+
+
+  static
+  const FT_Frame_Field  pcf_property_msb_header[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PCF_ParsePropertyRec
+
+    FT_FRAME_START( 9 ),
+      FT_FRAME_LONG( name ),
+      FT_FRAME_BYTE( isString ),
+      FT_FRAME_LONG( value ),
+    FT_FRAME_END
+  };
+
+
+  static PCF_Property
+  find_property( PCF_Face          face,
+                 const FT_String*  prop )
+  {
+    PCF_Property  properties = face->properties;
+    FT_Bool       found      = 0;
+    int           i;
+
+
+    for ( i = 0 ; i < face->nprops && !found; i++ )
+    {
+      if ( !strcmp( properties[i].name, prop ) )
+        found = 1;
+    }
+
+    if ( found )
+      return properties + i - 1;
+    else
+      return NULL;
+  }
+
+
+  static FT_Error
+  pcf_get_properties( FT_Stream  stream,
+                      PCF_Face   face )
+  {
+    PCF_ParseProperty  props      = 0;
+    PCF_Property       properties = 0;
+    int                nprops, i;
+    FT_ULong           format, size;
+    FT_Error           error;
+    FT_Memory          memory     = FT_FACE(face)->memory;
+    FT_ULong           string_size;
+    FT_String*         strings    = 0;
+
+
+    error = pcfSeekToType( stream,
+                           face->toc.tables,
+                           face->toc.count,
+                           PCF_PROPERTIES,
+                           &format,
+                           &size );
+    if ( error )
+      goto Bail;
+
+    if ( READ_ULongLE( format ) )
+      goto Bail;
+
+    FT_TRACE4(( "get_prop: format = %ld\n", format ));
+
+    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+      goto Bail;
+
+    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+      (void)READ_ULong( nprops );
+    else
+      (void)READ_ULongLE( nprops );
+    if ( error )
+      goto Bail;
+
+    FT_TRACE4(( "get_prop: nprop = %d\n", nprops ));
+
+    if ( ALLOC( props, nprops * sizeof ( PCF_ParsePropertyRec ) ) )
+      goto Bail;
+
+    for ( i = 0; i < nprops; i++ )
+    {
+      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+      {
+        if ( READ_Fields( pcf_property_msb_header, props + i ) )
+          goto Bail;
+      }
+      else
+      {
+        if ( READ_Fields( pcf_property_header, props + i ) )
+          goto Bail;
+      }
+    }
+
+    /* pad the property array                                            */
+    /*                                                                   */
+    /* clever here - nprops is the same as the number of odd-units read, */
+    /* as only isStringProp are odd length   (Keith Packard)             */
+    /*                                                                   */
+    if ( nprops & 3 )
+    {
+      i = 4 - ( nprops & 3 );
+      FT_Skip_Stream( stream, i );
+    }
+
+    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+      (void)READ_ULong( string_size );
+    else
+      (void)READ_ULongLE( string_size );
+    if ( error )
+      goto Bail;
+
+    FT_TRACE4(( "get_prop: string_size = %ld\n", string_size ));
+
+    if ( ALLOC( strings, string_size * sizeof ( char ) ) )
+      goto Bail;
+
+    error = FT_Read_Stream( stream, (FT_Byte*)strings, string_size );
+    if ( error )
+      goto Bail;
+
+    if ( ALLOC( properties, nprops * sizeof ( PCF_PropertyRec ) ) )
+      goto Bail;
+
+    for ( i = 0; i < nprops; i++ )
+    {
+      /* XXX: make atom */
+      if ( ALLOC( properties[i].name,
+                     ( strlen( strings + props[i].name ) + 1 ) *
+                       sizeof ( char ) ) )
+        goto Bail;
+      strcpy( properties[i].name,strings + props[i].name );
+
+      properties[i].isString = props[i].isString;
+
+      if ( props[i].isString )
+      {
+        if ( ALLOC( properties[i].value.atom,
+                       ( strlen( strings + props[i].value ) + 1 ) *
+                         sizeof ( char ) ) )
+          goto Bail;
+        strcpy( properties[i].value.atom, strings + props[i].value );
+      }
+      else
+        properties[i].value.integer = props[i].value;
+    }
+
+    face->properties = properties;
+    face->nprops = nprops;
+
+    FREE( props );
+    FREE( strings );
+
+    return PCF_Err_Ok;
+
+  Bail:
+    FREE( props );
+    FREE( strings );
+
+    return error;
+  }
+
+
+  static FT_Error
+  pcf_get_metrics( FT_Stream  stream,
+                   PCF_Face   face )
+  {
+    FT_Error    error    = PCF_Err_Ok;
+    FT_Memory   memory   = FT_FACE(face)->memory;
+    FT_ULong    format   = 0;
+    FT_ULong    size     = 0;
+    PCF_Metric  metrics  = 0;
+    int         i;
+    int         nmetrics = -1;
+
+
+    error = pcfSeekToType( stream,
+                           face->toc.tables,
+                           face->toc.count,
+                           PCF_METRICS,
+                           &format,
+                           &size );
+    if ( error )
+      return error;
+
+    error = READ_ULongLE( format );
+
+    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT )   &&
+         !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
+      return PCF_Err_Invalid_File_Format;
+
+    if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+    {
+      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+        (void)READ_ULong( nmetrics );
+      else
+        (void)READ_ULongLE( nmetrics );
+    }
+    else
+    {
+      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+        (void)READ_UShort( nmetrics );
+      else
+        (void)READ_UShortLE( nmetrics );
+    }
+    if ( error || nmetrics == -1 )
+      return PCF_Err_Invalid_File_Format;
+
+    face->nmetrics = nmetrics;
+
+    if ( ALLOC( face->metrics, nmetrics * sizeof ( PCF_MetricRec ) ) )
+      return PCF_Err_Out_Of_Memory;
+
+    metrics = face->metrics;
+    for ( i = 0; i < nmetrics; i++ )
+    {
+      pcf_get_metric( stream, format, metrics + i );
+
+      metrics[i].bits = 0;
+
+      FT_TRACE4(( "%d : width=%d, "
+                  "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
+                  i,
+                  ( metrics + i )->characterWidth,
+                  ( metrics + i )->leftSideBearing,
+                  ( metrics + i )->rightSideBearing,
+                  ( metrics + i )->ascent,
+                  ( metrics + i )->descent,
+                  ( metrics + i )->attributes ));
+
+      if ( error )
+        break;
+    }
+
+    if ( error )
+      FREE( face->metrics );
+    return error;
+  }
+
+
+  static FT_Error
+  pcf_get_bitmaps( FT_Stream  stream,
+                   PCF_Face   face )
+  {
+    FT_Error   error  = PCF_Err_Ok;
+    FT_Memory  memory = FT_FACE(face)->memory;
+    FT_Long*   offsets;
+    FT_Long    bitmapSizes[GLYPHPADOPTIONS];
+    FT_ULong   format, size;
+    int        nbitmaps, i, sizebitmaps = 0;
+    char*      bitmaps;
+
+
+    error = pcfSeekToType( stream,
+                           face->toc.tables,
+                           face->toc.count,
+                           PCF_BITMAPS,
+                           &format,
+                           &size );
+    if ( error )
+      return error;
+
+    error = FT_Access_Frame( stream, 8 );
+    if ( error )
+      return error;
+    format = GET_ULongLE();
+    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+      return PCF_Err_Invalid_File_Format;
+
+    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+      nbitmaps  = GET_ULong();
+    else
+      nbitmaps  = GET_ULongLE();
+    FT_Forget_Frame( stream );
+    if ( nbitmaps != face->nmetrics )
+      return PCF_Err_Invalid_File_Format;
+
+    if ( ALLOC( offsets, nbitmaps * sizeof ( FT_ULong ) ) )
+      return error;
+
+    if ( error )
+      goto Bail;
+    for ( i = 0; i < nbitmaps; i++ )
+    {
+      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+        (void)READ_Long( offsets[i] );
+      else
+        (void)READ_LongLE( offsets[i] );
+
+      FT_TRACE4(( "bitmap %d is at offset %ld\n", i, offsets[i] ));
+    }
+    if ( error )
+      goto Bail;
+
+    if ( error )
+      goto Bail;
+    for ( i = 0; i < GLYPHPADOPTIONS; i++ )
+    {
+      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+        (void)READ_Long( bitmapSizes[i] );
+      else
+        (void)READ_LongLE( bitmapSizes[i] );
+      if ( error )
+        goto Bail;
+
+      sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
+
+      FT_TRACE4(( "padding %d implies a size of %ld\n", i, bitmapSizes[i] ));
+    }
+
+    FT_TRACE4(( "  %d bitmaps, padding index %ld\n",
+                nbitmaps,
+                PCF_GLYPH_PAD_INDEX( format ) ));
+    FT_TRACE4(( "bitmap size = %d\n", sizebitmaps ));
+
+    for ( i = 0; i < nbitmaps; i++ )
+      face->metrics[i].bits = stream->pos + offsets[i];
+
+    face->bitmapsFormat = format;
+
+    FREE ( offsets );
+    return error;
+
+  Bail:
+    FREE ( offsets );
+    FREE ( bitmaps );
+    return error;
+  }
+
+
+  static FT_Error
+  pcf_get_encodings( FT_Stream  stream,
+                     PCF_Face   face )
+  {
+    FT_Error      error   = PCF_Err_Ok;
+    FT_Memory     memory  = FT_FACE(face)->memory;
+    FT_ULong      format, size;
+    int           firstCol, lastCol;
+    int           firstRow, lastRow;
+    int           nencoding, encodingOffset;
+    int           i, j;
+    PCF_Encoding  tmpEncoding, encoding = 0;
+
+
+    error = pcfSeekToType( stream,
+                           face->toc.tables,
+                           face->toc.count,
+                           PCF_BDF_ENCODINGS,
+                           &format,
+                           &size );
+    if ( error )
+      return error;
+
+    error = FT_Access_Frame( stream, 14 );
+    if ( error )
+      return error;
+    format = GET_ULongLE();
+    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
+      return PCF_Err_Invalid_File_Format;
+
+    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+    {
+      firstCol          = GET_Short();
+      lastCol           = GET_Short();
+      firstRow          = GET_Short();
+      lastRow           = GET_Short();
+      face->defaultChar = GET_Short();
+    }
+    else
+    {
+      firstCol          = GET_ShortLE();
+      lastCol           = GET_ShortLE();
+      firstRow          = GET_ShortLE();
+      lastRow           = GET_ShortLE();
+      face->defaultChar = GET_ShortLE();
+    }
+
+    FT_Forget_Frame( stream );
+
+    FT_TRACE4(( "enc: firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
+                firstCol, lastCol, firstRow, lastRow ));
+
+    nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );
+
+    if ( ALLOC( tmpEncoding, nencoding * sizeof ( PCF_EncodingRec ) ) )
+      return PCF_Err_Out_Of_Memory;
+
+    error = FT_Access_Frame( stream, 2 * nencoding );
+    if ( error )
+      goto Bail;
+
+    for ( i = 0, j = 0 ; i < nencoding; i++ )
+    {
+      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+        encodingOffset = GET_Short();
+      else
+        encodingOffset = GET_ShortLE();
+
+      if ( encodingOffset != -1 )
+      {
+        tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
+                                 firstRow ) * 256 ) +
+                               ( ( i % ( lastCol - firstCol + 1 ) ) +
+                                 firstCol );
+
+        tmpEncoding[j].glyph = (FT_Short)encodingOffset;
+        j++;
+      }
+
+      FT_TRACE4(( "enc n. %d ; Uni %ld ; Glyph %d\n",
+                  i, tmpEncoding[j - 1].enc, encodingOffset ));
+    }
+    FT_Forget_Frame( stream );
+
+    if ( ALLOC( encoding, (--j) * sizeof ( PCF_EncodingRec ) ) )
+      goto Bail;
+
+    for ( i = 0; i < j; i++ )
+    {
+      encoding[i].enc   = tmpEncoding[i].enc;
+      encoding[i].glyph = tmpEncoding[i].glyph;
+    }
+
+    face->nencodings = j;
+    face->encodings  = encoding;
+    FREE( tmpEncoding );
+
+    return error;
+
+  Bail:
+    FREE( encoding );
+    FREE( tmpEncoding );
+    return error;
+  }
+
+
+  static
+  const FT_Frame_Field  pcf_accel_header[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PCF_AccelRec
+
+    FT_FRAME_START( 20 ),
+      FT_FRAME_BYTE      ( noOverlap ),
+      FT_FRAME_BYTE      ( constantMetrics ),
+      FT_FRAME_BYTE      ( terminalFont ),
+      FT_FRAME_BYTE      ( constantWidth ),
+      FT_FRAME_BYTE      ( inkInside ),
+      FT_FRAME_BYTE      ( inkMetrics ),
+      FT_FRAME_BYTE      ( drawDirection ),
+      FT_FRAME_SKIP_BYTES( 1 ),
+      FT_FRAME_LONG_LE   ( fontAscent ),
+      FT_FRAME_LONG_LE   ( fontDescent ),
+      FT_FRAME_LONG_LE   ( maxOverlap ),
+    FT_FRAME_END
+  };
+
+
+  static
+  const FT_Frame_Field  pcf_accel_msb_header[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PCF_AccelRec
+
+    FT_FRAME_START( 20 ),
+      FT_FRAME_BYTE      ( noOverlap ),
+      FT_FRAME_BYTE      ( constantMetrics ),
+      FT_FRAME_BYTE      ( terminalFont ),
+      FT_FRAME_BYTE      ( constantWidth ),
+      FT_FRAME_BYTE      ( inkInside ),
+      FT_FRAME_BYTE      ( inkMetrics ),
+      FT_FRAME_BYTE      ( drawDirection ),
+      FT_FRAME_SKIP_BYTES( 1 ),
+      FT_FRAME_LONG      ( fontAscent ),
+      FT_FRAME_LONG      ( fontDescent ),
+      FT_FRAME_LONG      ( maxOverlap ),
+    FT_FRAME_END
+  };
+
+
+  static FT_Error
+  pcf_get_accel( FT_Stream  stream,
+                 PCF_Face   face,
+                 FT_ULong   type )
+  {
+    FT_ULong   format, size;
+    FT_Error   error = PCF_Err_Ok;
+    PCF_Accel  accel = &face->accel;
+
+
+    error = pcfSeekToType( stream,
+                           face->toc.tables,
+                           face->toc.count,
+                           type,
+                           &format,
+                           &size );
+    if ( error )
+      goto Bail;
+
+    error = READ_ULongLE( format );
+    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT )  &&
+         !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
+      goto Bail;
+
+    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
+    {
+      if ( READ_Fields( pcf_accel_msb_header, accel ) )
+        goto Bail;
+    }
+    else
+    {
+      if ( READ_Fields( pcf_accel_header, accel ) )
+        goto Bail;
+    }
+
+    error = pcf_get_metric( stream, format, &(accel->minbounds) );
+    if ( error )
+      goto Bail;
+    error = pcf_get_metric( stream, format, &(accel->maxbounds) );
+    if ( error )
+      goto Bail;
+
+    if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
+    {
+      error = pcf_get_metric( stream, format, &(accel->ink_minbounds) );
+      if ( error )
+        goto Bail;
+      error = pcf_get_metric( stream, format, &(accel->ink_maxbounds) );
+      if ( error )
+        goto Bail;
+    }
+    else
+    {
+      accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */
+      accel->ink_maxbounds = accel->maxbounds;
+    }
+    return error;
+
+  Bail:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  pcf_load_font( FT_Stream  stream,
+                 PCF_Face   face )
+  {
+    FT_Error   error  = PCF_Err_Ok;
+    FT_Memory  memory = FT_FACE(face)->memory;
+    FT_Bool    hasBDFAccelerators;
+
+
+    error = pcf_read_TOC( stream, face );
+    if ( error )
+      return error;
+
+    error = pcf_get_properties( stream, face );
+    if ( error )
+      return error;;
+
+    /* Use the old accelerators if no BDF accelerators are in the file. */
+    hasBDFAccelerators = pcfHasType( face->toc.tables,
+                                     face->toc.count,
+                                     PCF_BDF_ACCELERATORS );
+    if ( !hasBDFAccelerators )
+    {
+      error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
+      if ( error )
+        goto Bail;
+    }
+
+    /* metrics */
+    error = pcf_get_metrics( stream, face );
+    if ( error )
+      goto Bail;
+
+    /* bitmaps */
+    error = pcf_get_bitmaps( stream, face );
+    if ( error )
+      goto Bail;
+
+    /* encodings */
+    error = pcf_get_encodings( stream, face );
+    if ( error )
+      goto Bail;
+
+    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
+    if ( hasBDFAccelerators )
+    {
+      error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
+      if ( error )
+        goto Bail;
+    }
+
+    /* XXX: TO DO: inkmetrics and glyph_names are missing */
+
+    /* now construct the face object */
+    {
+      FT_Face       root = FT_FACE( face );
+      PCF_Property  prop;
+
+
+      root->num_faces = 1;
+      root->face_index = 0;
+      root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
+                         FT_FACE_FLAG_HORIZONTAL  |
+                         FT_FACE_FLAG_FAST_GLYPHS;
+
+      if ( face->accel.constantWidth )
+        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+      root->style_flags = 0;
+      prop = find_property( face, "SLANT" );
+      if ( prop != NULL )
+        if ( prop->isString )
+          if ( ( *(prop->value.atom) == 'O' ) ||
+               ( *(prop->value.atom) == 'I' ) )
+            root->style_flags |= FT_STYLE_FLAG_ITALIC;
+
+      prop = find_property( face, "WEIGHT_NAME" );
+      if ( prop != NULL )
+        if ( prop->isString )
+          if ( *(prop->value.atom) == 'B' )
+            root->style_flags |= FT_STYLE_FLAG_BOLD;
+
+      root->style_name = (char *)"Regular";
+
+      if ( root->style_flags & FT_STYLE_FLAG_BOLD ) {
+        if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
+          root->style_name = (char *)"Bold Italic";
+        else
+          root->style_name = (char *)"Bold";
+      }
+      else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
+        root->style_name = (char *)"Italic";
+
+      prop = find_property( face, "FAMILY_NAME" );
+      if ( prop != NULL )
+      {
+        if ( prop->isString )
+        {
+          int  l = strlen( prop->value.atom ) + 1;
+
+
+          if ( ALLOC( root->family_name, l * sizeof ( char ) ) )
+            goto Bail;
+          strcpy( root->family_name, prop->value.atom );
+        }
+      }
+      else
+        root->family_name = 0;
+
+      root->num_glyphs = face->nmetrics;
+
+      root->num_fixed_sizes = 1;
+      if ( ALLOC_ARRAY( root->available_sizes, 1, FT_Bitmap_Size ) )
+        goto Bail;
+
+      prop = find_property( face, "PIXEL_SIZE" );
+      if ( prop != NULL )
+      {
+        PCF_Property  xres = 0, yres = 0;
+
+
+        xres = find_property( face, "RESOLUTION_X" );
+        yres = find_property( face, "RESOLUTION_Y" );
+        if ( ( xres != NULL ) && ( yres != NULL ) )
+        {
+          root->available_sizes->width =
+            (FT_Short)( prop->value.integer * 75 / xres->value.integer );
+          root->available_sizes->height =
+            (FT_Short)( prop->value.integer * 75 / yres->value.integer );
+        }
+      }
+      else
+      { /* XXX */
+#if 0
+        printf( "PCF Warning: Pixel Size undefined, assuming 12\n");
+#endif
+        root->available_sizes->width = 12;
+        root->available_sizes->height = 12;
+      }
+
+      /* XXX: charmaps */
+      root->charmaps     = &face->charmap_handle;
+      root->num_charmaps = 1;
+
+      {
+        PCF_Property  charset_registry = 0, charset_encoding = 0;
+
+
+        charset_registry = find_property( face, "CHARSET_REGISTRY" );
+        charset_encoding = find_property( face, "CHARSET_ENCODING" );
+
+        if ( ( charset_registry != NULL ) &&
+             ( charset_encoding != NULL ) )
+        {
+          if ( ( charset_registry->isString ) &&
+               ( charset_encoding->isString ) )
+          {
+            if ( ALLOC( face->charset_encoding,
+                        ( strlen( charset_encoding->value.atom ) + 1 ) *
+                          sizeof ( char ) ) )
+              goto Bail;
+            if ( ALLOC( face->charset_registry,
+                        ( strlen( charset_registry->value.atom ) + 1 ) *
+                          sizeof ( char ) ) )
+              goto Bail;
+            strcpy( face->charset_registry, charset_registry->value.atom );
+            strcpy( face->charset_encoding, charset_encoding->value.atom );
+
+#if 0
+            if ( !strcmp( charset_registry, "ISO10646" ) )
+            {
+              face->charmap.encoding    = ft_encoding_unicode;
+              face->charmap.platform_id = 3;
+              face->charmap.encoding_id = 1;
+              face->charmap.face        = root;
+              face->charmap_handle
+
+              return PCF_Err_Ok;
+            }
+#endif
+          }
+        }
+      }
+
+      face->charmap.encoding    = ft_encoding_none;
+      face->charmap.platform_id = 0;
+      face->charmap.encoding_id = 0;
+      face->charmap.face        = root;
+      face->charmap_handle      = &face->charmap;
+      root->charmap             = face->charmap_handle;
+    }
+    return PCF_Err_Ok;
+
+  Bail:
+    PCF_Done_Face( face );
+    return PCF_Err_Invalid_File_Format;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/pcfutil.c b/libraries/freetype-2.0.5/pcfutil.c
new file mode 100644 (file)
index 0000000..eb911bb
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+
+Copyright 1990, 1994, 1998  The Open Group
+
+All Rights Reserved.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/lib/font/util/utilbitmap.c,v 1.3 1999/08/22 08:58:58 dawes Exp $ */
+
+/*
+ * Author:  Keith Packard, MIT X Consortium
+ */
+
+
+#include <ft2build.h>
+#include "pcfutil.h"
+
+
+  /* Utility functions for reformatting font bitmaps */
+
+  static const unsigned char  _reverse_byte[0x100] =
+  {
+    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+  };
+
+  /*
+   *  Invert bit order within each BYTE of an array.
+   */
+
+  void
+  BitOrderInvert( unsigned char*  buf,
+                  int             nbytes )
+  {
+    const unsigned char*  rev = _reverse_byte;
+
+
+    for ( ; --nbytes >= 0; buf++ )
+      *buf = rev[*buf];
+  }
+
+
+  /*
+   *  Invert byte order within each 16-bits of an array.
+   */
+
+  void
+  TwoByteSwap( unsigned char*  buf,
+               int             nbytes )
+  {
+    unsigned char  c;
+
+
+    for ( ; nbytes > 0; nbytes -= 2, buf += 2 )
+    {
+      c      = buf[0];
+      buf[0] = buf[1];
+      buf[1] = c;
+    }
+  }
+
+  /*
+   *  Invert byte order within each 32-bits of an array.
+   */
+
+  void
+  FourByteSwap( unsigned char*  buf,
+                int             nbytes )
+  {
+    unsigned char  c;
+
+
+    for ( ; nbytes > 0; nbytes -= 4, buf += 4 )
+    {
+      c      = buf[0];
+      buf[0] = buf[3];
+      buf[3] = c;
+
+      c      = buf[1];
+      buf[1] = buf[2];
+      buf[2] = c;
+    }
+  }
+
+
+  /*
+   *  Repad a bitmap.
+   */
+
+  int
+  RepadBitmap( char*         pSrc,
+               char*         pDst,
+               unsigned int  srcPad,
+               unsigned int  dstPad,
+               int           width,
+               int           height )
+  {
+    int   srcWidthBytes, dstWidthBytes;
+    int   row, col;
+    char  *pTmpSrc, *pTmpDst;
+
+
+    switch ( srcPad )
+    {
+    case 1:
+      srcWidthBytes = ( width + 7 ) >> 3;
+      break;
+
+    case 2:
+      srcWidthBytes = ( ( width + 15 ) >> 4 ) << 1;
+      break;
+
+    case 4:
+      srcWidthBytes = ( ( width + 31 ) >> 5 ) << 2;
+      break;
+
+    case 8:
+      srcWidthBytes = ( ( width + 63 ) >> 6 ) << 3;
+      break;
+
+    default:
+      return 0;
+    }
+
+    switch ( dstPad )
+    {
+    case 1:
+      dstWidthBytes = ( width + 7 ) >> 3;
+      break;
+
+    case 2:
+      dstWidthBytes = ( ( width + 15 ) >> 4 ) << 1;
+      break;
+
+    case 4:
+      dstWidthBytes = ( ( width + 31 ) >> 5 ) << 2;
+      break;
+
+    case 8:
+      dstWidthBytes = ( ( width + 63 ) >> 6 ) << 3;
+      break;
+
+    default:
+      return 0;
+    }
+
+    width = srcWidthBytes;
+    if ( width > dstWidthBytes )
+      width = dstWidthBytes;
+
+    pTmpSrc= pSrc;
+    pTmpDst= pDst;
+
+    for ( row = 0; row < height; row++ )
+    {
+      for ( col = 0; col < width; col++ )
+        *pTmpDst++ = *pTmpSrc++;
+
+      while ( col < dstWidthBytes )
+      {
+        *pTmpDst++ = '\0';
+        col++;
+      }
+      pTmpSrc += srcWidthBytes - width;
+    }
+
+    return dstWidthBytes * height;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/psaux.c b/libraries/freetype-2.0.5/psaux.c
new file mode 100644 (file)
index 0000000..54d85e5
--- /dev/null
@@ -0,0 +1,27 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psaux.c                                                                */
+/*                                                                         */
+/*    FreeType auxiliary PostScript driver component (body only).          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "psobjs.c"
+#include "psauxmod.c"
+#include "t1decode.c"
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/psauxmod.c b/libraries/freetype-2.0.5/psauxmod.c
new file mode 100644 (file)
index 0000000..559f9d0
--- /dev/null
@@ -0,0 +1,105 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psauxmod.c                                                             */
+/*                                                                         */
+/*    FreeType auxiliary PostScript module implementation (body).          */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "psauxmod.h"
+#include "psobjs.h"
+#include "t1decode.h"
+
+
+  FT_CALLBACK_TABLE_DEF
+  const PS_Table_Funcs  ps_table_funcs =
+  {
+    PS_Table_New,
+    PS_Table_Done,
+    PS_Table_Add,
+    PS_Table_Release
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const T1_Parser_Funcs  t1_parser_funcs =
+  {
+    T1_Init_Parser,
+    T1_Done_Parser,
+    T1_Skip_Spaces,
+    T1_Skip_Alpha,
+    T1_ToInt,
+    T1_ToFixed,
+    T1_ToCoordArray,
+    T1_ToFixedArray,
+    T1_ToToken,
+    T1_ToTokenArray,
+    T1_Load_Field,
+    T1_Load_Field_Table
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const T1_Builder_Funcs  t1_builder_funcs =
+  {
+    T1_Builder_Init,
+    T1_Builder_Done,
+    T1_Builder_Check_Points,
+    T1_Builder_Add_Point,
+    T1_Builder_Add_Point1,
+    T1_Builder_Add_Contour,
+    T1_Builder_Start_Point,
+    T1_Builder_Close_Contour
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const T1_Decoder_Funcs  t1_decoder_funcs =
+  {
+    T1_Decoder_Init,
+    T1_Decoder_Done,
+    T1_Decoder_Parse_Charstrings
+  };
+
+
+  static
+  const PSAux_Interface  psaux_interface =
+  {
+    &ps_table_funcs,
+    &t1_parser_funcs,
+    &t1_builder_funcs,
+    &t1_decoder_funcs,
+
+    T1_Decrypt
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Module_Class  psaux_module_class =
+  {
+    0,
+    sizeof( FT_ModuleRec ),
+    "psaux",
+    0x10000L,
+    0x20000L,
+
+    &psaux_interface,  /* module-specific interface */
+
+    (FT_Module_Constructor)0,
+    (FT_Module_Destructor) 0,
+    (FT_Module_Requester)  0
+  };
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/psmodule.c b/libraries/freetype-2.0.5/psmodule.c
new file mode 100644 (file)
index 0000000..8ed2768
--- /dev/null
@@ -0,0 +1,311 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psmodule.c                                                             */
+/*                                                                         */
+/*    PSNames module implementation (body).                                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "psmodule.h"
+#include "pstables.h"
+
+#include "psnamerr.h"
+
+#include <stdlib.h>     /* for qsort()             */
+#include <string.h>     /* for strcmp(), strncpy() */
+
+
+#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
+
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+
+  /* return the Unicode value corresponding to a given glyph.  Note that */
+  /* we do deal with glyph variants by detecting a non-initial dot in    */
+  /* the name, as in `A.swash' or `e.final', etc.                        */
+  /*                                                                     */
+  static FT_ULong
+  PS_Unicode_Value( const char*  glyph_name )
+  {
+    FT_Int  n;
+    char    first = glyph_name[0];
+    char    temp[64];
+
+
+    /* if the name begins with `uni', then the glyph name may be a */
+    /* hard-coded unicode character code.                          */
+    if ( glyph_name[0] == 'u' &&
+         glyph_name[1] == 'n' &&
+         glyph_name[2] == 'i' )
+    {
+      /* determine whether the next four characters following are */
+      /* hexadecimal.                                             */
+
+      /* XXX: Add code to deal with ligatures, i.e. glyph names like */
+      /*      `uniXXXXYYYYZZZZ'...                                   */
+
+      FT_Int       count;
+      FT_ULong     value = 0;
+      const char*  p     = glyph_name + 3;
+
+
+      for ( count = 4; count > 0; count--, p++ )
+      {
+        char           c = *p;
+        unsigned int   d;
+
+
+        d = (unsigned char)c - '0';
+        if ( d >= 10 )
+        {
+          d = (unsigned char)c - 'A';
+          if ( d >= 6 )
+            d = 16;
+          else
+            d += 10;
+        }
+
+        /* exit if a non-uppercase hexadecimal character was found */
+        if ( d >= 16 )
+          break;
+
+        value = ( value << 4 ) + d;
+      }
+      if ( count == 0 )
+        return value;
+    }
+
+    /* look for a non-initial dot in the glyph name in order to */
+    /* sort-out variants like `A.swash', `e.final', etc.        */
+    {
+      const char*  p;
+      int          len;
+
+
+      p = glyph_name;
+
+      while ( *p && *p != '.' )
+        p++;
+
+      len = (int)( p - glyph_name );
+
+      if ( *p && len < 64 )
+      {
+        strncpy( temp, glyph_name, len );
+        temp[len]  = 0;
+        glyph_name = temp;
+      }
+    }
+
+    /* now, look up the glyph in the Adobe Glyph List */
+    for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ )
+    {
+      const char*  name = sid_standard_names[n];
+
+
+      if ( first == name[0] && strcmp( glyph_name, name ) == 0 )
+        return ps_names_to_unicode[n];
+    }
+
+    /* not found, there is probably no Unicode value for this glyph name */
+    return 0;
+  }
+
+
+  /* qsort callback to sort the unicode map */
+  FT_CALLBACK_DEF( int )
+  compare_uni_maps( const void*  a,
+                    const void*  b )
+  {
+    PS_UniMap*  map1 = (PS_UniMap*)a;
+    PS_UniMap*  map2 = (PS_UniMap*)b;
+
+
+    return ( map1->unicode - map2->unicode );
+  }
+
+
+  /* Builds a table that maps Unicode values to glyph indices */
+  static FT_Error
+  PS_Build_Unicode_Table( FT_Memory     memory,
+                          FT_UInt       num_glyphs,
+                          const char**  glyph_names,
+                          PS_Unicodes*  table )
+  {
+    FT_Error  error;
+
+
+    /* we first allocate the table */
+    table->num_maps = 0;
+    table->maps     = 0;
+
+    if ( !ALLOC_ARRAY( table->maps, num_glyphs, PS_UniMap ) )
+    {
+      FT_UInt     n;
+      FT_UInt     count;
+      PS_UniMap*  map;
+      FT_ULong    uni_char;
+
+
+      map = table->maps;
+
+      for ( n = 0; n < num_glyphs; n++ )
+      {
+        const char*  gname = glyph_names[n];
+
+
+        if ( gname )
+        {
+          uni_char = PS_Unicode_Value( gname );
+
+          if ( uni_char != 0 && uni_char != 0xFFFF )
+          {
+            map->unicode     = uni_char;
+            map->glyph_index = n;
+            map++;
+          }
+        }
+      }
+
+      /* now, compress the table a bit */
+      count = (FT_UInt)( map - table->maps );
+
+      if ( count > 0 && REALLOC( table->maps,
+                                 num_glyphs * sizeof ( PS_UniMap ),
+                                 count * sizeof ( PS_UniMap ) ) )
+        count = 0;
+
+      if ( count == 0 )
+      {
+        FREE( table->maps );
+        if ( !error )
+          error = PSnames_Err_Invalid_Argument;  /* no unicode chars here! */
+      }
+      else
+        /* sort the table in increasing order of unicode values */
+        qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps );
+
+      table->num_maps = count;
+    }
+
+    return error;
+  }
+
+
+  static FT_UInt
+  PS_Lookup_Unicode( PS_Unicodes*  table,
+                     FT_ULong      unicode )
+  {
+    PS_UniMap  *min, *max, *mid;
+
+
+    /* perform a binary search on the table */
+
+    min = table->maps;
+    max = min + table->num_maps - 1;
+
+    while ( min <= max )
+    {
+      mid = min + ( max - min ) / 2;
+      if ( mid->unicode == unicode )
+        return mid->glyph_index;
+
+      if ( min == max )
+        break;
+
+      if ( mid->unicode < unicode )
+        min = mid + 1;
+      else
+        max = mid - 1;
+    }
+
+    return 0xFFFF;
+  }
+
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+
+  static const char*
+  PS_Macintosh_Name( FT_UInt  name_index )
+  {
+    if ( name_index >= 258 )
+      name_index = 0;
+
+    return ps_glyph_names[mac_standard_names[name_index]];
+  }
+
+
+  static const char*
+  PS_Standard_Strings( FT_UInt  sid )
+  {
+    return ( sid < NUM_SID_GLYPHS ? sid_standard_names[sid] : 0 );
+  }
+
+
+  static
+  const PSNames_Interface  psnames_interface =
+  {
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+    (PS_Unicode_Value_Func)    PS_Unicode_Value,
+    (PS_Build_Unicodes_Func)   PS_Build_Unicode_Table,
+    (PS_Lookup_Unicode_Func)   PS_Lookup_Unicode,
+
+#else
+
+    0,
+    0,
+    0,
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+    (PS_Macintosh_Name_Func)   PS_Macintosh_Name,
+    (PS_Adobe_Std_Strings_Func)PS_Standard_Strings,
+
+    t1_standard_encoding,
+    t1_expert_encoding
+  };
+
+
+#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Module_Class  psnames_module_class =
+  {
+    0,  /* this is not a font driver, nor a renderer */
+    sizeof( FT_ModuleRec ),
+
+    "psnames",  /* driver name                         */
+    0x10000L,   /* driver version                      */
+    0x20000L,   /* driver requires FreeType 2 or above */
+
+#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES
+    0,
+#else
+    (void*)&psnames_interface,   /* module specific interface */
+#endif
+
+    (FT_Module_Constructor)0,
+    (FT_Module_Destructor) 0,
+    (FT_Module_Requester)  0
+  };
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/psnames.c b/libraries/freetype-2.0.5/psnames.c
new file mode 100644 (file)
index 0000000..d6ed998
--- /dev/null
@@ -0,0 +1,25 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psnames.c                                                              */
+/*                                                                         */
+/*    FreeType PSNames module component (body only).                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "psmodule.c"
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/psobjs.c b/libraries/freetype-2.0.5/psobjs.c
new file mode 100644 (file)
index 0000000..a210084
--- /dev/null
@@ -0,0 +1,1304 @@
+/***************************************************************************/
+/*                                                                         */
+/*  psobjs.c                                                               */
+/*                                                                         */
+/*    Auxiliary functions for PostScript fonts (body).                     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "psobjs.h"
+
+#include "psauxerr.h"
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                             PS_TABLE                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    PS_Table_New                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a PS_Table.                                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table  :: The address of the target table.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    count  :: The table size = the maximum number of elements.         */
+  /*                                                                       */
+  /*    memory :: The memory object to use for all subsequent              */
+  /*              reallocations.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  PS_Table_New( PS_Table*  table,
+                FT_Int     count,
+                FT_Memory  memory )
+  {
+    FT_Error  error;
+
+
+    table->memory = memory;
+    if ( ALLOC_ARRAY( table->elements, count, FT_Byte*  ) ||
+         ALLOC_ARRAY( table->lengths, count, FT_Byte* )   )
+      goto Exit;
+
+    table->max_elems = count;
+    table->init      = 0xDEADBEEFUL;
+    table->num_elems = 0;
+    table->block     = 0;
+    table->capacity  = 0;
+    table->cursor    = 0;
+    table->funcs     = ps_table_funcs;
+
+  Exit:
+    if ( error )
+      FREE( table->elements );
+
+    return error;
+  }
+
+
+  static void
+  shift_elements( PS_Table*  table,
+                  FT_Byte*   old_base )
+  {
+    FT_Long    delta  = (FT_Long)( table->block - old_base );
+    FT_Byte**  offset = table->elements;
+    FT_Byte**  limit  = offset + table->max_elems;
+
+
+    for ( ; offset < limit; offset++ )
+    {
+      if ( offset[0] )
+        offset[0] += delta;
+    }
+  }
+
+
+  static FT_Error
+  reallocate_t1_table( PS_Table*  table,
+                       FT_Long    new_size )
+  {
+    FT_Memory  memory   = table->memory;
+    FT_Byte*   old_base = table->block;
+    FT_Error   error;
+
+
+    /* allocate new base block */
+    if ( ALLOC( table->block, new_size ) )
+      return error;
+
+    /* copy elements and shift offsets */
+    if (old_base )
+    {
+      MEM_Copy( table->block, old_base, table->capacity );
+      shift_elements( table, old_base );
+      FREE( old_base );
+    }
+
+    table->capacity = new_size;
+
+    return PSaux_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    PS_Table_Add                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adds an object to a PS_Table, possibly growing its memory block.   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table  :: The target table.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    index  :: The index of the object in the table.                    */
+  /*                                                                       */
+  /*    object :: The address of the object to copy in memory.             */
+  /*                                                                       */
+  /*    length :: The length in bytes of the source object.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  An error is returned if a  */
+  /*    reallocation fails.                                                */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  PS_Table_Add( PS_Table*  table,
+                FT_Int     index,
+                void*      object,
+                FT_Int     length )
+  {
+    if ( index < 0 || index > table->max_elems )
+    {
+      FT_ERROR(( "PS_Table_Add: invalid index\n" ));
+      return PSaux_Err_Invalid_Argument;
+    }
+
+    /* grow the base block if needed */
+    if ( table->cursor + length > table->capacity )
+    {
+      FT_Error   error;
+      FT_Offset  new_size  = table->capacity;
+      FT_Long    in_offset;
+      
+
+      in_offset = (FT_Long)((FT_Byte*)object - table->block);
+      if ( (FT_ULong)in_offset >= table->capacity )
+        in_offset = -1;
+
+      while ( new_size < table->cursor + length )
+        new_size += 1024;
+
+      error = reallocate_t1_table( table, new_size );
+      if ( error )
+        return error;
+      
+      if ( in_offset >= 0 )
+        object = table->block + in_offset;
+    }
+
+    /* add the object to the base block and adjust offset */
+    table->elements[index] = table->block + table->cursor;
+    table->lengths [index] = length;
+    MEM_Copy( table->block + table->cursor, object, length );
+
+    table->cursor += length;
+    return PSaux_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    PS_Table_Done                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a PS_Table (i.e., reallocate it to its current cursor).  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table :: The target table.                                         */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function does NOT release the heap's memory block.  It is up  */
+  /*    to the caller to clean it, or reference it in its own structures.  */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  PS_Table_Done( PS_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+    FT_Error   error;
+    FT_Byte*   old_base = table->block;
+
+
+    /* should never fail, because rec.cursor <= rec.size */
+    if ( !old_base )
+      return;
+
+    if ( ALLOC( table->block, table->cursor ) )
+      return;
+    MEM_Copy( table->block, old_base, table->cursor );
+    shift_elements( table, old_base );
+
+    table->capacity = table->cursor;
+    FREE( old_base );
+  }
+
+
+  FT_LOCAL_DEF void
+  PS_Table_Release( PS_Table*  table )
+  {
+    FT_Memory  memory = table->memory;
+
+
+    if ( (FT_ULong)table->init == 0xDEADBEEFUL )
+    {
+      FREE( table->block );
+      FREE( table->elements );
+      FREE( table->lengths );
+      table->init = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                            T1 PARSER                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define IS_T1_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
+#define IS_T1_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' )
+
+#define IS_T1_SPACE( c )  ( IS_T1_WHITESPACE( c ) || IS_T1_LINESPACE( c ) )
+
+
+  FT_LOCAL_DEF void
+  T1_Skip_Spaces( T1_Parser*  parser )
+  {
+    FT_Byte* cur   = parser->cursor;
+    FT_Byte* limit = parser->limit;
+
+
+    while ( cur < limit )
+    {
+      FT_Byte  c = *cur;
+
+
+      if ( !IS_T1_SPACE( c ) )
+        break;
+      cur++;
+    }
+    parser->cursor = cur;
+  }
+
+
+  FT_LOCAL_DEF void
+  T1_Skip_Alpha( T1_Parser*  parser )
+  {
+    FT_Byte* cur   = parser->cursor;
+    FT_Byte* limit = parser->limit;
+
+
+    while ( cur < limit )
+    {
+      FT_Byte  c = *cur;
+
+
+      if ( IS_T1_SPACE( c ) )
+        break;
+      cur++;
+    }
+    parser->cursor = cur;
+  }
+
+
+  FT_LOCAL_DEF void
+  T1_ToToken( T1_Parser*  parser,
+              T1_Token*   token )
+  {
+    FT_Byte*  cur;
+    FT_Byte*  limit;
+    FT_Byte   starter, ender;
+    FT_Int    embed;
+
+
+    token->type  = t1_token_none;
+    token->start = 0;
+    token->limit = 0;
+
+    /* first of all, skip space */
+    T1_Skip_Spaces( parser );
+
+    cur   = parser->cursor;
+    limit = parser->limit;
+
+    if ( cur < limit )
+    {
+      switch ( *cur )
+      {
+        /************* check for strings ***********************/
+      case '(':
+        token->type = t1_token_string;
+        ender = ')';
+        goto Lookup_Ender;
+
+        /************* check for programs/array ****************/
+      case '{':
+        token->type = t1_token_array;
+        ender = '}';
+        goto Lookup_Ender;
+
+        /************* check for table/array ******************/
+      case '[':
+        token->type = t1_token_array;
+        ender = ']';
+
+      Lookup_Ender:
+        embed   = 1;
+        starter = *cur++;
+        token->start = cur;
+        while ( cur < limit )
+        {
+          if ( *cur == starter )
+            embed++;
+          else if ( *cur == ender )
+          {
+            embed--;
+            if ( embed <= 0 )
+            {
+              token->limit = cur++;
+              break;
+            }
+          }
+          cur++;
+        }
+        break;
+
+        /* **************** otherwise, it's any token **********/
+      default:
+        token->start = cur++;
+        token->type  = t1_token_any;
+        while ( cur < limit && !IS_T1_SPACE( *cur ) )
+          cur++;
+
+        token->limit = cur;
+      }
+
+      if ( !token->limit )
+      {
+        token->start = 0;
+        token->type  = t1_token_none;
+      }
+
+      parser->cursor = cur;
+    }
+  }
+
+
+  FT_LOCAL_DEF void
+  T1_ToTokenArray( T1_Parser*  parser,
+                   T1_Token*   tokens,
+                   FT_UInt     max_tokens,
+                   FT_Int*     pnum_tokens )
+  {
+    T1_Token  master;
+
+
+    *pnum_tokens = -1;
+
+    T1_ToToken( parser, &master );
+    if ( master.type == t1_token_array )
+    {
+      FT_Byte*   old_cursor = parser->cursor;
+      FT_Byte*   old_limit  = parser->limit;
+      T1_Token*  cur        = tokens;
+      T1_Token*  limit      = cur + max_tokens;
+
+
+      parser->cursor = master.start;
+      parser->limit  = master.limit;
+
+      while ( parser->cursor < parser->limit )
+      {
+        T1_Token  token;
+
+
+        T1_ToToken( parser, &token );
+        if ( !token.type )
+          break;
+
+        if ( cur < limit )
+          *cur = token;
+
+        cur++;
+      }
+
+      *pnum_tokens = (FT_Int)( cur - tokens );
+
+      parser->cursor = old_cursor;
+      parser->limit  = old_limit;
+    }
+  }
+
+
+  static FT_Long
+  t1_toint( FT_Byte**  cursor,
+            FT_Byte*   limit )
+  {
+    FT_Long   result = 0;
+    FT_Byte*  cur    = *cursor;
+    FT_Byte   c = '\0', d;
+
+
+    for ( ; cur < limit; cur++ )
+    {
+      c = *cur;
+      d = (FT_Byte)( c - '0' );
+      if ( d < 10 )
+        break;
+
+      if ( c == '-' )
+      {
+        cur++;
+        break;
+      }
+    }
+
+    if ( cur < limit )
+    {
+      do
+      {
+        d = (FT_Byte)( cur[0] - '0' );
+        if ( d >= 10 )
+          break;
+
+        result = result * 10 + d;
+        cur++;
+
+      } while ( cur < limit );
+
+      if ( c == '-' )
+        result = -result;
+    }
+
+    *cursor = cur;
+    return result;
+  }
+
+
+  static FT_Long
+  t1_tofixed( FT_Byte**  cursor,
+              FT_Byte*   limit,
+              FT_Long    power_ten )
+  {
+    FT_Byte*  cur  = *cursor;
+    FT_Long   num, divider, result;
+    FT_Int    sign = 0;
+    FT_Byte   d;
+
+
+    if ( cur >= limit )
+      return 0;
+
+    /* first of all, check the sign */
+    if ( *cur == '-' )
+    {
+      sign = 1;
+      cur++;
+    }
+
+    /* then, read the integer part, if any */
+    if ( *cur != '.' )
+      result = t1_toint( &cur, limit ) << 16;
+    else
+      result = 0;
+
+    num     = 0;
+    divider = 1;
+
+    if ( cur >= limit )
+      goto Exit;
+
+    /* read decimal part, if any */
+    if ( *cur == '.' && cur + 1 < limit )
+    {
+      cur++;
+
+      for (;;)
+      {
+        d = (FT_Byte)( *cur - '0' );
+        if ( d >= 10 )
+          break;
+
+        if ( divider < 10000000L )
+        {
+          num      = num * 10 + d;
+          divider *= 10;
+        }
+
+        cur++;
+        if ( cur >= limit )
+          break;
+      }
+    }
+
+    /* read exponent, if any */
+    if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
+    {
+      cur++;
+      power_ten += t1_toint( &cur, limit );
+    }
+
+  Exit:
+    /* raise to power of ten if needed */
+    while ( power_ten > 0 )
+    {
+      result = result * 10;
+      num    = num * 10;
+      power_ten--;
+    }
+
+    while ( power_ten < 0 )
+    {
+      result  = result / 10;
+      divider = divider * 10;
+      power_ten++;
+    }
+
+    if ( num )
+      result += FT_DivFix( num, divider );
+
+    if ( sign )
+      result = -result;
+
+    *cursor = cur;
+    return result;
+  }
+
+
+  static FT_Int
+  t1_tocoordarray( FT_Byte**  cursor,
+                   FT_Byte*   limit,
+                   FT_Int     max_coords,
+                   FT_Short*  coords )
+  {
+    FT_Byte*  cur   = *cursor;
+    FT_Int    count = 0;
+    FT_Byte   c, ender;
+
+
+    if ( cur >= limit )
+      goto Exit;
+
+    /* check for the beginning of an array; if not, only one number will */
+    /* be read                                                           */
+    c     = *cur;
+    ender = 0;
+
+    if ( c == '[' )
+      ender = ']';
+
+    if ( c == '{' )
+      ender = '}';
+
+    if ( ender )
+      cur++;
+
+    /* now, read the coordinates */
+    for ( ; cur < limit; )
+    {
+      /* skip whitespace in front of data */
+      for (;;)
+      {
+        c = *cur;
+        if ( c != ' ' && c != '\t' )
+          break;
+
+        cur++;
+        if ( cur >= limit )
+          goto Exit;
+      }
+
+      if ( count >= max_coords || c == ender )
+        break;
+
+      coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
+      count++;
+
+      if ( !ender )
+        break;
+    }
+
+  Exit:
+    *cursor = cur;
+    return count;
+  }
+
+
+  static FT_Int
+  t1_tofixedarray( FT_Byte**  cursor,
+                   FT_Byte*   limit,
+                   FT_Int     max_values,
+                   FT_Fixed*  values,
+                   FT_Int     power_ten )
+  {
+    FT_Byte*  cur   = *cursor;
+    FT_Int    count = 0;
+    FT_Byte   c, ender;
+
+
+    if ( cur >= limit ) goto Exit;
+
+    /* check for the beginning of an array. If not, only one number will */
+    /* be read                                                           */
+    c     = *cur;
+    ender = 0;
+
+    if ( c == '[' )
+      ender = ']';
+
+    if ( c == '{' )
+      ender = '}';
+
+    if ( ender )
+      cur++;
+
+    /* now, read the values */
+    for ( ; cur < limit; )
+    {
+      /* skip whitespace in front of data */
+      for (;;)
+      {
+        c = *cur;
+        if ( c != ' ' && c != '\t' )
+          break;
+
+        cur++;
+        if ( cur >= limit )
+          goto Exit;
+      }
+
+      if ( count >= max_values || c == ender )
+        break;
+
+      values[count] = t1_tofixed( &cur, limit, power_ten );
+      count++;
+
+      if ( !ender )
+        break;
+    }
+
+  Exit:
+    *cursor = cur;
+    return count;
+  }
+
+
+#if 0
+
+  static FT_String*
+  t1_tostring( FT_Byte**  cursor,
+               FT_Byte*   limit,
+               FT_Memory  memory )
+  {
+    FT_Byte*    cur = *cursor;
+    FT_Int      len = 0;
+    FT_Int      count;
+    FT_String*  result;
+    FT_Error    error;
+
+
+    /* XXX: some stupid fonts have a `Notice' or `Copyright' string     */
+    /*      that simply doesn't begin with an opening parenthesis, even */
+    /*      though they have a closing one!  E.g. "amuncial.pfb"        */
+    /*                                                                  */
+    /*      We must deal with these ill-fated cases there.  Note that   */
+    /*      these fonts didn't work with the old Type 1 driver as the   */
+    /*      notice/copyright was not recognized as a valid string token */
+    /*      and made the old token parser commit errors.                */
+
+    while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
+      cur++;
+    if ( cur + 1 >= limit )
+      return 0;
+
+    if ( *cur == '(' )
+      cur++;  /* skip the opening parenthesis, if there is one */
+
+    *cursor = cur;
+    count   = 0;
+
+    /* then, count its length */
+    for ( ; cur < limit; cur++ )
+    {
+      if ( *cur == '(' )
+        count++;
+
+      else if ( *cur == ')' )
+      {
+        count--;
+        if ( count < 0 )
+          break;
+      }
+    }
+
+    len = cur - *cursor;
+    if ( cur >= limit || ALLOC( result, len + 1 ) )
+      return 0;
+
+    /* now copy the string */
+    MEM_Copy( result, *cursor, len );
+    result[len] = '\0';
+    *cursor = cur;
+    return result;
+  }
+
+#endif /* 0 */
+
+
+  static int
+  t1_tobool( FT_Byte**  cursor,
+             FT_Byte*   limit )
+  {
+    FT_Byte*  cur    = *cursor;
+    FT_Bool   result = 0;
+
+
+    /* return 1 if we find `true', 0 otherwise */
+    if ( cur + 3 < limit &&
+         cur[0] == 't' &&
+         cur[1] == 'r' &&
+         cur[2] == 'u' &&
+         cur[3] == 'e' )
+    {
+      result = 1;
+      cur   += 5;
+    }
+    else if ( cur + 4 < limit &&
+              cur[0] == 'f' &&
+              cur[1] == 'a' &&
+              cur[2] == 'l' &&
+              cur[3] == 's' &&
+              cur[4] == 'e' )
+    {
+      result = 0;
+      cur   += 6;
+    }
+
+    *cursor = cur;
+    return result;
+  }
+
+
+  /* Load a simple field (i.e. non-table) into the current list of objects */
+  FT_LOCAL_DEF FT_Error
+  T1_Load_Field( T1_Parser*       parser,
+                 const T1_Field*  field,
+                 void**           objects,
+                 FT_UInt          max_objects,
+                 FT_ULong*        pflags )
+  {
+    T1_Token  token;
+    FT_Byte*  cur;
+    FT_Byte*  limit;
+    FT_UInt   count;
+    FT_UInt   index;
+    FT_Error  error;
+
+
+    T1_ToToken( parser, &token );
+    if ( !token.type )
+      goto Fail;
+
+    count = 1;
+    index = 0;
+    cur   = token.start;
+    limit = token.limit;
+
+    if ( token.type == t1_token_array )
+    {
+      /* if this is an array, and we have no blend, an error occurs */
+      if ( max_objects == 0 )
+        goto Fail;
+
+      count = max_objects;
+      index = 1;
+    }
+
+    for ( ; count > 0; count--, index++ )
+    {
+      FT_Byte*    q = (FT_Byte*)objects[index] + field->offset;
+      FT_Long     val;
+      FT_String*  string;
+
+
+      switch ( field->type )
+      {
+      case t1_field_bool:
+        val = t1_tobool( &cur, limit );
+        goto Store_Integer;
+
+      case t1_field_fixed:
+        val = t1_tofixed( &cur, limit, 3 );
+        goto Store_Integer;
+
+      case t1_field_integer:
+        val = t1_toint( &cur, limit );
+
+      Store_Integer:
+        switch ( field->size )
+        {
+        case 1:
+          *(FT_Byte*)q = (FT_Byte)val;
+          break;
+
+        case 2:
+          *(FT_UShort*)q = (FT_UShort)val;
+          break;
+
+        case 4:
+          *(FT_UInt32*)q = (FT_UInt32)val;
+          break;
+
+        default:  /* for 64-bit systems */
+          *(FT_Long*)q = val;
+        }
+        break;
+
+      case t1_field_string:
+        {
+          FT_Memory  memory = parser->memory;
+          FT_UInt    len    = (FT_UInt)( limit - cur );
+
+
+          if ( *(FT_String**)q )
+            /* with synthetic fonts, it's possible to find a field twice */
+            break;
+
+          if ( ALLOC( string, len + 1 ) )
+            goto Exit;
+
+          MEM_Copy( string, cur, len );
+          string[len] = 0;
+
+          *(FT_String**)q = string;
+        }
+        break;
+
+      default:
+        /* an error occured */
+        goto Fail;
+      }
+    }
+
+#if 0  /* obsolete - keep for reference */
+    if ( pflags )
+      *pflags |= 1L << field->flag_bit;
+#else
+    FT_UNUSED( pflags );
+#endif
+
+    error = PSaux_Err_Ok;
+
+  Exit:
+    return error;
+
+  Fail:
+    error = PSaux_Err_Invalid_File_Format;
+    goto Exit;
+  }
+
+
+#define T1_MAX_TABLE_ELEMENTS  32
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_Load_Field_Table( T1_Parser*       parser,
+                       const T1_Field*  field,
+                       void**           objects,
+                       FT_UInt          max_objects,
+                       FT_ULong*        pflags )
+  {
+    T1_Token   elements[T1_MAX_TABLE_ELEMENTS];
+    T1_Token*  token;
+    FT_Int     num_elements;
+    FT_Error   error = 0;
+    FT_Byte*   old_cursor;
+    FT_Byte*   old_limit;
+    T1_Field   fieldrec = *(T1_Field*)field;
+
+#if 1
+    fieldrec.type = t1_field_integer;
+    if ( field->type == t1_field_fixed_array )
+      fieldrec.type = t1_field_fixed;
+#endif
+
+    T1_ToTokenArray( parser, elements, 32, &num_elements );
+    if ( num_elements < 0 )
+      goto Fail;
+
+    if ( num_elements > T1_MAX_TABLE_ELEMENTS )
+      num_elements = T1_MAX_TABLE_ELEMENTS;
+
+    old_cursor = parser->cursor;
+    old_limit  = parser->limit;
+
+    /* we store the elements count */
+    *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
+      (FT_Byte)num_elements;
+
+    /* we now load each element, adjusting the field.offset on each one */
+    token = elements;
+    for ( ; num_elements > 0; num_elements--, token++ )
+    {
+      parser->cursor = token->start;
+      parser->limit  = token->limit;
+      T1_Load_Field( parser, &fieldrec, objects, max_objects, 0 );
+      fieldrec.offset += fieldrec.size;
+    }
+
+#if 0  /* obsolete -- keep for reference */
+    if ( pflags )
+      *pflags |= 1L << field->flag_bit;
+#else
+    FT_UNUSED( pflags );
+#endif
+
+    parser->cursor = old_cursor;
+    parser->limit  = old_limit;
+
+  Exit:
+    return error;
+
+  Fail:
+    error = PSaux_Err_Invalid_File_Format;
+    goto Exit;
+  }
+
+
+  FT_LOCAL_DEF FT_Long
+  T1_ToInt( T1_Parser*  parser )
+  {
+    return t1_toint( &parser->cursor, parser->limit );
+  }
+
+
+  FT_LOCAL_DEF FT_Fixed
+  T1_ToFixed( T1_Parser*  parser,
+              FT_Int      power_ten )
+  {
+    return t1_tofixed( &parser->cursor, parser->limit, power_ten );
+  }
+
+
+  FT_LOCAL_DEF FT_Int
+  T1_ToCoordArray( T1_Parser*  parser,
+                   FT_Int      max_coords,
+                   FT_Short*   coords )
+  {
+    return t1_tocoordarray( &parser->cursor, parser->limit,
+                            max_coords, coords );
+  }
+
+
+  FT_LOCAL_DEF FT_Int
+  T1_ToFixedArray( T1_Parser*  parser,
+                   FT_Int      max_values,
+                   FT_Fixed*   values,
+                   FT_Int      power_ten )
+  {
+    return t1_tofixedarray( &parser->cursor, parser->limit,
+                            max_values, values, power_ten );
+  }
+
+
+#if 0
+
+  FT_LOCAL_DEF FT_String*
+  T1_ToString( T1_Parser*  parser )
+  {
+    return t1_tostring( &parser->cursor, parser->limit, parser->memory );
+  }
+
+
+  FT_LOCAL_DEF FT_Bool
+  T1_ToBool( T1_Parser*  parser )
+  {
+    return t1_tobool( &parser->cursor, parser->limit );
+  }
+
+#endif /* 0 */
+
+
+  FT_LOCAL_DEF void
+  T1_Init_Parser( T1_Parser*  parser,
+                  FT_Byte*    base,
+                  FT_Byte*    limit,
+                  FT_Memory   memory )
+  {
+    parser->error  = 0;
+    parser->base   = base;
+    parser->limit  = limit;
+    parser->cursor = base;
+    parser->memory = memory;
+    parser->funcs  = t1_parser_funcs;
+  }
+
+
+  FT_LOCAL_DEF void
+  T1_Done_Parser( T1_Parser*  parser )
+  {
+    FT_UNUSED( parser );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                            T1 BUILDER                         *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Builder_Init                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given glyph builder.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    builder :: A pointer to the glyph builder to initialize.           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face    :: The current face object.                                */
+  /*                                                                       */
+  /*    size    :: The current size object.                                */
+  /*                                                                       */
+  /*    glyph   :: The current glyph object.                               */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  T1_Builder_Init( T1_Builder*   builder,
+                   FT_Face       face,
+                   FT_Size       size,
+                   FT_GlyphSlot  glyph )
+  {
+    builder->path_begun  = 0;
+    builder->load_points = 1;
+
+    builder->face   = face;
+    builder->glyph  = glyph;
+    builder->memory = face->memory;
+
+    if ( glyph )
+    {
+      FT_GlyphLoader*  loader = glyph->internal->loader;
+
+
+      builder->loader  = loader;
+      builder->base    = &loader->base.outline;
+      builder->current = &loader->current.outline;
+      FT_GlyphLoader_Rewind( loader );
+    }
+
+    if ( size )
+    {
+      builder->scale_x = size->metrics.x_scale;
+      builder->scale_y = size->metrics.y_scale;
+    }
+
+    builder->pos_x = 0;
+    builder->pos_y = 0;
+
+    builder->left_bearing.x = 0;
+    builder->left_bearing.y = 0;
+    builder->advance.x      = 0;
+    builder->advance.y      = 0;
+
+    builder->funcs = t1_builder_funcs;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Builder_Done                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given glyph builder.  Its contents can still be used   */
+  /*    after the call, but the function saves important information       */
+  /*    within the corresponding glyph slot.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    builder :: A pointer to the glyph builder to finalize.             */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  T1_Builder_Done( T1_Builder*  builder )
+  {
+    FT_GlyphSlot  glyph = builder->glyph;
+
+
+    if ( glyph )
+      glyph->outline = *builder->base;
+  }
+
+
+  /* check that there is enough room for `count' more points */
+  FT_LOCAL_DEF FT_Error
+  T1_Builder_Check_Points( T1_Builder*  builder,
+                           FT_Int       count )
+  {
+    return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
+  }
+
+
+  /* add a new point, do not check space */
+  FT_LOCAL_DEF void
+  T1_Builder_Add_Point( T1_Builder*  builder,
+                        FT_Pos       x,
+                        FT_Pos       y,
+                        FT_Byte      flag )
+  {
+    FT_Outline*  outline = builder->current;
+
+
+    if ( builder->load_points )
+    {
+      FT_Vector*  point   = outline->points + outline->n_points;
+      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+
+
+      if ( builder->shift )
+      {
+        x >>= 16;
+        y >>= 16;
+      }
+      point->x = x;
+      point->y = y;
+      *control = (FT_Byte)( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
+
+      builder->last = *point;
+    }
+    outline->n_points++;
+  }
+
+
+  /* check space for a new on-curve point, then add it */
+  FT_LOCAL_DEF FT_Error
+  T1_Builder_Add_Point1( T1_Builder*  builder,
+                         FT_Pos       x,
+                         FT_Pos       y )
+  {
+    FT_Error  error;
+
+
+    error = T1_Builder_Check_Points( builder, 1 );
+    if ( !error )
+      T1_Builder_Add_Point( builder, x, y, 1 );
+
+    return error;
+  }
+
+
+  /* check room for a new contour, then add it */
+  FT_LOCAL_DEF FT_Error
+  T1_Builder_Add_Contour( T1_Builder*  builder )
+  {
+    FT_Outline*  outline = builder->current;
+    FT_Error     error;
+
+
+    if ( !builder->load_points )
+    {
+      outline->n_contours++;
+      return PSaux_Err_Ok;
+    }
+
+    error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+    if ( !error )
+    {
+      if ( outline->n_contours > 0 )
+        outline->contours[outline->n_contours - 1] =
+          (short)( outline->n_points - 1 );
+
+      outline->n_contours++;
+    }
+
+    return error;
+  }
+
+
+  /* if a path was begun, add its first on-curve point */
+  FT_LOCAL_DEF FT_Error
+  T1_Builder_Start_Point( T1_Builder*  builder,
+                          FT_Pos       x,
+                          FT_Pos       y )
+  {
+    FT_Error  error = 0;
+
+
+    /* test whether we are building a new contour */
+    if ( !builder->path_begun )
+    {
+      builder->path_begun = 1;
+      error = T1_Builder_Add_Contour( builder );
+      if ( !error )
+        error = T1_Builder_Add_Point1( builder, x, y );
+    }
+    return error;
+  }
+
+
+  /* close the current contour */
+  FT_LOCAL_DEF void
+  T1_Builder_Close_Contour( T1_Builder*  builder )
+  {
+    FT_Outline*  outline = builder->current;
+
+
+    /* XXXX: We must not include the last point in the path if it */
+    /*       is located on the first point.                       */
+    if ( outline->n_points > 1 )
+    {
+      FT_Int      first   = 0;
+      FT_Vector*  p1      = outline->points + first;
+      FT_Vector*  p2      = outline->points + outline->n_points - 1;
+      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+
+
+      if ( outline->n_contours > 1 )
+      {
+        first = outline->contours[outline->n_contours - 2] + 1;
+        p1    = outline->points + first;
+      }
+
+      /* `delete' last point only if it coincides with the first */
+      /* point and it is not a control point (which can happen). */
+      if ( p1->x == p2->x && p1->y == p2->y )
+        if ( *control == FT_Curve_Tag_On )
+          outline->n_points--;
+    }
+
+    if ( outline->n_contours > 0 )
+      outline->contours[outline->n_contours - 1] =
+        (short)( outline->n_points - 1 );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                            OTHER                              *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  FT_LOCAL_DEF void
+  T1_Decrypt( FT_Byte*   buffer,
+              FT_Offset  length,
+              FT_UShort  seed )
+  {
+    while ( length > 0 )
+    {
+      FT_Byte  plain;
+
+
+      plain     = (FT_Byte)( *buffer ^ ( seed >> 8 ) );
+      seed      = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 );
+      *buffer++ = plain;
+      length--;
+    }
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/raster.c b/libraries/freetype-2.0.5/raster.c
new file mode 100644 (file)
index 0000000..f13a67a
--- /dev/null
@@ -0,0 +1,26 @@
+/***************************************************************************/
+/*                                                                         */
+/*  raster.c                                                               */
+/*                                                                         */
+/*    FreeType monochrome rasterer module component (body only).           */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ftraster.c"
+#include "ftrend1.c"
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/sfdriver.c b/libraries/freetype-2.0.5/sfdriver.c
new file mode 100644 (file)
index 0000000..3104564
--- /dev/null
@@ -0,0 +1,273 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfdriver.c                                                             */
+/*                                                                         */
+/*    High-level SFNT driver interface (body).                             */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_OBJECTS_H
+
+#include "sfdriver.h"
+#include "ttload.h"
+#include "ttcmap.h"
+#include "sfobjs.h"
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+#include "ttsbit.h"
+#endif
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+#include "ttpost.h"
+#endif
+
+#include <string.h>     /* for strcmp() */
+
+
+  static void*
+  get_sfnt_table( TT_Face      face,
+                  FT_Sfnt_Tag  tag )
+  {
+    void*  table;
+
+
+    switch ( tag )
+    {
+    case ft_sfnt_head:
+      table = &face->header;
+      break;
+
+    case ft_sfnt_hhea:
+      table = &face->horizontal;
+      break;
+
+    case ft_sfnt_vhea:
+      table = face->vertical_info ? &face->vertical : 0;
+      break;
+
+    case ft_sfnt_os2:
+      table = face->os2.version == 0xFFFF ? 0 : &face->os2;
+      break;
+
+    case ft_sfnt_post:
+      table = &face->postscript;
+      break;
+
+    case ft_sfnt_maxp:
+      table = &face->max_profile;
+      break;
+
+    case ft_sfnt_pclt:
+      table = face->pclt.Version ? &face->pclt : 0;
+      break;
+
+    default:
+      table = 0;
+    }
+
+    return table;
+  }
+
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+  static FT_Error
+  get_sfnt_glyph_name( TT_Face     face,
+                       FT_UInt     glyph_index,
+                       FT_Pointer  buffer,
+                       FT_UInt     buffer_max )
+  {
+    FT_String*  gname;
+    FT_Error    error;
+
+
+    error = TT_Get_PS_Name( face, glyph_index, &gname );
+    if ( !error && buffer_max > 0 )
+    {
+      FT_UInt  len = (FT_UInt)( strlen( gname ) );
+
+
+      if ( len >= buffer_max )
+        len = buffer_max - 1;
+
+      MEM_Copy( buffer, gname, len );
+      ((FT_Byte*)buffer)[len] = 0;
+    }
+
+    return error;
+  }
+
+
+  static const char*
+  get_sfnt_postscript_name( TT_Face  face )
+  {
+    FT_Int  n;
+
+    /* shouldn't happen, but just in case to avoid memory leaks */    
+    if ( face->root.internal->postscript_name )
+      return face->root.internal->postscript_name;
+
+    /* scan the name table to see if we have a Postscript name here, either */
+    /* in Macintosh or Windows platform encodings..                         */
+    for ( n = 0; n < face->num_names; n++ )
+    {
+      TT_NameRec*  name = face->name_table.names + n;
+      
+      if ( name->nameID == 6 )
+      {
+        if ( ( name->platformID == 3 &&
+               name->encodingID == 1 &&
+               name->languageID == 0x409 ) ||
+               
+             ( name->platformID == 1 &&
+               name->encodingID == 0 &&
+               name->languageID == 0     ) )
+        {
+          FT_UInt    len = name->stringLength;
+          FT_Error   error;
+          FT_Memory  memory = face->root.memory;
+          FT_String* result;
+          
+          if ( !ALLOC( result, len+1 ) )
+          {
+            memcpy( result, name->string, len );
+            result[len] = '\0';
+            
+            face->root.internal->postscript_name = result;
+          }
+          return result;
+        }
+      }
+    }
+    
+    return NULL;
+  }
+
+
+#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+  FT_CALLBACK_DEF( FT_Module_Interface )
+  SFNT_Get_Interface( FT_Module    module,
+                      const char*  interface )
+  {
+    FT_UNUSED( module );
+
+    if ( strcmp( interface, "get_sfnt" ) == 0 )
+      return (FT_Module_Interface)get_sfnt_table;
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+    if ( strcmp( interface, "glyph_name" ) == 0 )
+      return (FT_Module_Interface)get_sfnt_glyph_name;
+#endif
+
+    if ( strcmp( interface, "postscript_name" ) == 0 )
+      return (FT_Module_Interface)get_sfnt_postscript_name;
+
+    return 0;
+  }
+
+
+  static
+  const SFNT_Interface  sfnt_interface =
+  {
+    TT_Goto_Table,
+
+    SFNT_Init_Face,
+    SFNT_Load_Face,
+    SFNT_Done_Face,
+    SFNT_Get_Interface,
+
+    TT_Load_Any,
+    TT_Load_SFNT_Header,
+    TT_Load_Directory,
+
+    TT_Load_Header,
+    TT_Load_Metrics_Header,
+    TT_Load_CMap,
+    TT_Load_MaxProfile,
+    TT_Load_OS2,
+    TT_Load_PostScript,
+
+    TT_Load_Names,
+    TT_Free_Names,
+
+    TT_Load_Hdmx,
+    TT_Free_Hdmx,
+
+    TT_Load_Kern,
+    TT_Load_Gasp,
+    TT_Load_PCLT,
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    /* see `ttload.h' */
+    TT_Load_Bitmap_Header,
+
+    /* see `ttsbit.h' */
+    TT_Set_SBit_Strike,
+    TT_Load_SBit_Strikes,
+    TT_Load_SBit_Image,
+    TT_Free_SBit_Strikes,
+
+#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    0,
+    0,
+    0,
+    0,
+    0,
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+    /* see `ttpost.h' */
+    TT_Get_PS_Name,
+    TT_Free_Post_Names,
+
+#else /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+    0,
+    0,
+
+#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+    /* see `ttcmap.h' */
+    TT_CharMap_Load,
+    TT_CharMap_Free,
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Module_Class  sfnt_module_class =
+  {
+    0,  /* not a font driver or renderer */
+    sizeof( FT_ModuleRec ),
+
+    "sfnt",     /* driver name                            */
+    0x10000L,   /* driver version 1.0                     */
+    0x20000L,   /* driver requires FreeType 2.0 or higher */
+
+    (const void*)&sfnt_interface,  /* module specific interface */
+
+    (FT_Module_Constructor)0,
+    (FT_Module_Destructor) 0,
+    (FT_Module_Requester)  SFNT_Get_Interface
+  };
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/sfnt.c b/libraries/freetype-2.0.5/sfnt.c
new file mode 100644 (file)
index 0000000..b1e412b
--- /dev/null
@@ -0,0 +1,36 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfnt.c                                                                 */
+/*                                                                         */
+/*    Single object library component.                                     */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ttload.c"
+#include "ttcmap.c"
+#include "sfobjs.c"
+#include "sfdriver.c"
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+#include "ttsbit.c"
+#endif
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+#include "ttpost.c"
+#endif
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/sfobjs.c b/libraries/freetype-2.0.5/sfobjs.c
new file mode 100644 (file)
index 0000000..f4966be
--- /dev/null
@@ -0,0 +1,673 @@
+/***************************************************************************/
+/*                                                                         */
+/*  sfobjs.c                                                               */
+/*                                                                         */
+/*    SFNT object management (base).                                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "sfobjs.h"
+#include "ttload.h"
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TAGS_H
+
+#include "sferrors.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_sfobjs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Name                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns a given ENGLISH name record in ASCII.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the source face object.                      */
+  /*                                                                       */
+  /*    nameid :: The name id of the name record to return.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Character string.  NULL if no name is present.                     */
+  /*                                                                       */
+  static FT_String*
+  Get_Name( TT_Face    face,
+            FT_UShort  nameid )
+  {
+    FT_Memory    memory = face->root.memory;
+    FT_UShort    n;
+    TT_NameRec*  rec;
+    FT_Bool      wide_chars = 1;
+
+
+    rec = face->name_table.names;
+    for ( n = 0; n < face->name_table.numNameRecords; n++, rec++ )
+    {
+      if ( rec->nameID == nameid )
+      {
+        /* found the name -- now create an ASCII string from it */
+        FT_Bool  found = 0;
+
+
+        /* test for Microsoft English language */
+        if ( rec->platformID == TT_PLATFORM_MICROSOFT &&
+             rec->encodingID <= TT_MS_ID_UNICODE_CS   &&
+             ( rec->languageID & 0x3FF ) == 0x009     )
+          found = 1;
+
+        /* test for Apple Unicode encoding */
+        else if ( rec->platformID == TT_PLATFORM_APPLE_UNICODE )
+          found = 1;
+
+        /* test for Apple Roman */
+        else if ( rec->platformID == TT_PLATFORM_MACINTOSH &&
+                  rec->languageID == TT_MAC_ID_ROMAN       )
+        {
+          found      = 1;
+          wide_chars = 0;
+        }
+
+        /* found a Unicode name */
+        if ( found )
+        {
+          FT_String*  string;
+          FT_UInt     len;
+
+
+          if ( wide_chars )
+          {
+            FT_UInt   m;
+
+
+            len = (FT_UInt)rec->stringLength / 2;
+            if ( MEM_Alloc( string, len + 1 ) )
+              return NULL;
+
+            for ( m = 0; m < len; m ++ )
+              string[m] = rec->string[2 * m + 1];
+          }
+          else
+          {
+            len = rec->stringLength;
+            if ( MEM_Alloc( string, len + 1 ) )
+              return NULL;
+
+            MEM_Copy( string, rec->string, len );
+          }
+
+          string[len] = '\0';
+          return string;
+        }
+      }
+    }
+
+    return NULL;
+  }
+
+
+  static FT_Encoding
+  find_encoding( int  platform_id,
+                 int  encoding_id )
+  {
+    typedef struct  TEncoding
+    {
+      int          platform_id;
+      int          encoding_id;
+      FT_Encoding  encoding;
+
+    } TEncoding;
+
+    static
+    const TEncoding  tt_encodings[] =
+    {
+      { TT_PLATFORM_ISO,           -1,                  ft_encoding_unicode },
+
+      { TT_PLATFORM_APPLE_UNICODE, -1,                  ft_encoding_unicode },
+
+      { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     ft_encoding_apple_roman },
+
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SYMBOL_CS,  ft_encoding_symbol },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UCS_4,      ft_encoding_unicode },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, ft_encoding_unicode },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       ft_encoding_sjis },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     ft_encoding_gb2312 },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      ft_encoding_big5 },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    ft_encoding_wansung },
+      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      ft_encoding_johab }
+    };
+
+    const TEncoding  *cur, *limit;
+
+
+    cur   = tt_encodings;
+    limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
+
+    for ( ; cur < limit; cur++ )
+    {
+      if ( cur->platform_id == platform_id )
+      {
+        if ( cur->encoding_id == encoding_id ||
+             cur->encoding_id == -1          )
+          return cur->encoding;
+      }
+    }
+
+    return ft_encoding_none;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  SFNT_Init_Face( FT_Stream      stream,
+                  TT_Face        face,
+                  FT_Int         face_index,
+                  FT_Int         num_params,
+                  FT_Parameter*  params )
+  {
+    FT_Error            error;
+    FT_Library          library = face->root.driver->root.library;
+    SFNT_Interface*     sfnt;
+    SFNT_Header         sfnt_header;
+
+    /* for now, parameters are unused */
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+
+    sfnt = (SFNT_Interface*)face->sfnt;
+    if ( !sfnt )
+    {
+      sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" );
+      if ( !sfnt )
+      {
+        error = SFNT_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      face->sfnt       = sfnt;
+      face->goto_table = sfnt->goto_table;
+    }
+
+    if ( !face->psnames )
+    {
+      face->psnames = (PSNames_Interface*)
+                       FT_Get_Module_Interface( library, "psnames" );
+    }
+
+    /* check that we have a valid TrueType file */
+    error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header );
+    if ( error )
+      goto Exit;
+
+    face->format_tag = sfnt_header.format_tag;
+    face->num_tables = sfnt_header.num_tables;
+
+    /* Load font directory */
+    error = sfnt->load_directory( face, stream, &sfnt_header );
+    if ( error )
+      goto Exit;
+
+    face->root.num_faces = face->ttc_header.count;
+    if ( face->root.num_faces < 1 )
+      face->root.num_faces = 1;
+
+  Exit:
+    return error;
+  }
+
+
+#undef  LOAD_
+#define LOAD_( x )  ( ( error = sfnt->load_##x( face, stream ) ) \
+                      != SFNT_Err_Ok )
+
+
+  FT_LOCAL_DEF FT_Error
+  SFNT_Load_Face( FT_Stream      stream,
+                  TT_Face        face,
+                  FT_Int         face_index,
+                  FT_Int         num_params,
+                  FT_Parameter*  params )
+  {
+    FT_Error         error;
+    FT_Bool          has_outline;
+    FT_Bool          is_apple_sbit;
+
+    SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
+
+    FT_UNUSED( face_index );
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+
+
+    /* Load tables */
+
+    /* We now support two SFNT-based bitmapped font formats.  They */
+    /* are recognized easily as they do not include a `glyf'       */
+    /* table.                                                      */
+    /*                                                             */
+    /* The first format comes from Apple, and uses a table named   */
+    /* `bhed' instead of `head' to store the font header (using    */
+    /* the same format).  It also doesn't include horizontal and   */
+    /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
+    /* missing).                                                   */
+    /*                                                             */
+    /* The other format comes from Microsoft, and is used with     */
+    /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
+    /* it doesn't contain outlines.                                */
+    /*                                                             */
+
+    /* do we have outlines in there? */
+    has_outline   = FT_BOOL( ( TT_LookUp_Table( face, TTAG_glyf ) != 0 ) ||
+                             ( TT_LookUp_Table( face, TTAG_CFF  ) != 0 ) );
+    is_apple_sbit = 0;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    /* if this font doesn't contain outlines, we try to load */
+    /* a `bhed' table                                        */
+    if ( !has_outline )
+      is_apple_sbit = FT_BOOL( !LOAD_( bitmap_header ) );
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    /* load the font header (`head' table) if this isn't an Apple */
+    /* sbit font file                                             */
+    if ( !is_apple_sbit && LOAD_( header ) )
+      goto Exit;
+
+    /* load other tables */
+    if ( LOAD_( max_profile ) ||
+         LOAD_( charmaps )    ||
+         LOAD_( names )       ||
+         LOAD_( psnames )     )
+      goto Exit;
+
+    /* do not load the metrics headers and tables if this is an Apple */
+    /* sbit font file                                                 */
+    if ( !is_apple_sbit )
+    {
+      /* load the `hhea' and `hmtx' tables at once */
+      error = sfnt->load_metrics( face, stream, 0 );
+      if ( error )
+        goto Exit;
+
+      /* try to load the `vhea' and `vmtx' tables at once */
+      error = sfnt->load_metrics( face, stream, 1 );
+      if ( error )
+        goto Exit;
+
+      if ( LOAD_( os2 ) )
+        goto Exit;
+    }
+
+    /* the optional tables */
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    /* embedded bitmap support. */
+    if ( sfnt->load_sbits && LOAD_( sbits ) )
+    {
+      /* return an error if this font file has no outlines */
+      if ( error == SFNT_Err_Table_Missing && has_outline )
+        error = SFNT_Err_Ok;
+      else
+        goto Exit;
+    }
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    if ( LOAD_( hdmx )    ||
+         LOAD_( gasp )    ||
+         LOAD_( kerning ) ||
+         LOAD_( pclt )    )
+      goto Exit;
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+    if ( ( error = TT_Extension_Create( face ) ) != SFNT_Err_Ok )
+      goto Exit;
+#endif
+
+    face->root.family_name = Get_Name( face, TT_NAME_ID_FONT_FAMILY );
+    face->root.style_name  = Get_Name( face, TT_NAME_ID_FONT_SUBFAMILY );
+
+    /* now set up root fields */
+    {
+      FT_Face     root = &face->root;
+      FT_Int      flags = 0;
+      TT_CharMap  charmap;
+      FT_Int      n;
+      FT_Memory   memory;
+
+
+      memory = root->memory;
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Compute face flags.                                               */
+      /*                                                                   */
+      if ( has_outline == TRUE )
+        flags = FT_FACE_FLAG_SCALABLE;    /* scalable outlines */
+
+      flags |= FT_FACE_FLAG_SFNT      |   /* SFNT file format  */
+               FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
+
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+      /* might need more polish to detect the presence of a Postscript */
+      /* name table in the font                                        */
+      flags |= FT_FACE_FLAG_GLYPH_NAMES;
+#endif
+
+      /* fixed width font? */
+      if ( face->postscript.isFixedPitch )
+        flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+      /* vertical information? */
+      if ( face->vertical_info )
+        flags |= FT_FACE_FLAG_VERTICAL;
+
+      /* kerning available ? */
+      if ( face->kern_pairs )
+        flags |= FT_FACE_FLAG_KERNING;
+
+      root->face_flags = flags;
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Compute style flags.                                              */
+      /*                                                                   */
+      flags = 0;
+      if ( has_outline == TRUE && face->os2.version != 0xFFFF )
+      {
+        /* we have an OS/2 table; use the `fsSelection' field */
+        if ( face->os2.fsSelection & 1 )
+          flags |= FT_STYLE_FLAG_ITALIC;
+
+        if ( face->os2.fsSelection & 32 )
+          flags |= FT_STYLE_FLAG_BOLD;
+      }
+      else
+      {
+        /* this is an old Mac font, use the header field */
+        if ( face->header.Mac_Style & 1 )
+          flags |= FT_STYLE_FLAG_BOLD;
+
+        if ( face->header.Mac_Style & 2 )
+          flags |= FT_STYLE_FLAG_ITALIC;
+      }
+
+      root->style_flags = flags;
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Polish the charmaps.                                              */
+      /*                                                                   */
+      /*   Try to set the charmap encoding according to the platform &     */
+      /*   encoding ID of each charmap.                                    */
+      /*                                                                   */
+      charmap            = face->charmaps;
+      root->num_charmaps = face->num_charmaps;
+
+      /* allocate table of pointers */
+      if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) )
+        goto Exit;
+
+      for ( n = 0; n < root->num_charmaps; n++, charmap++ )
+      {
+        FT_Int  platform = charmap->cmap.platformID;
+        FT_Int  encoding = charmap->cmap.platformEncodingID;
+
+
+        charmap->root.face        = (FT_Face)face;
+        charmap->root.platform_id = (FT_UShort)platform;
+        charmap->root.encoding_id = (FT_UShort)encoding;
+        charmap->root.encoding    = find_encoding( platform, encoding );
+
+        /* now, set root->charmap with a unicode charmap */
+        /* wherever available                            */
+        if ( !root->charmap                                &&
+             charmap->root.encoding == ft_encoding_unicode )
+          root->charmap = (FT_CharMap)charmap;
+
+        root->charmaps[n] = (FT_CharMap)charmap;
+      }
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+      if ( face->num_sbit_strikes )
+      {
+        root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
+
+#if 0
+        /* I don't know criteria whether layout is horizontal or vertical */
+        if ( has_outline.... )
+        {
+          ...
+          root->face_flags |= FT_FACE_FLAG_VERTICAL;
+        }
+#endif
+        root->num_fixed_sizes = face->num_sbit_strikes;
+
+        if ( ALLOC_ARRAY( root->available_sizes,
+                          face->num_sbit_strikes,
+                          FT_Bitmap_Size ) )
+          goto Exit;
+
+        for ( n = 0 ; n < face->num_sbit_strikes ; n++ )
+        {
+          root->available_sizes[n].width =
+            face->sbit_strikes[n].x_ppem;
+
+          root->available_sizes[n].height =
+            face->sbit_strikes[n].y_ppem;
+        }
+      }
+      else
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+      {
+        root->num_fixed_sizes = 0;
+        root->available_sizes = 0;
+      }
+
+      /*********************************************************************/
+      /*                                                                   */
+      /*  Set up metrics.                                                  */
+      /*                                                                   */
+      if ( has_outline == TRUE )
+      {
+        /* XXX What about if outline header is missing */
+        /*     (e.g. sfnt wrapped outline)?            */
+        root->bbox.xMin    = face->header.xMin;
+        root->bbox.yMin    = face->header.yMin;
+        root->bbox.xMax    = face->header.xMax;
+        root->bbox.yMax    = face->header.yMax;
+        root->units_per_EM = face->header.Units_Per_EM;
+
+
+        /* XXX: Computing the ascender/descender/height is very different */
+        /*      from what the specification tells you.  Apparently, we    */
+        /*      must be careful because                                   */
+        /*                                                                */
+        /*      - not all fonts have an OS/2 table; in this case, we take */
+        /*        the values in the horizontal header.  However, these    */
+        /*        values very often are not reliable.                     */
+        /*                                                                */
+        /*      - otherwise, the correct typographic values are in the    */
+        /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
+        /*                                                                */
+        /*        However, certains fonts have these fields set to 0.     */
+        /*        Rather, they have usWinAscent & usWinDescent correctly  */
+        /*        set (but with different values).                        */
+        /*                                                                */
+        /*      As an example, Arial Narrow is implemented through four   */
+        /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
+        /*                                                                */
+        /*      Strangely, all fonts have the same values in their        */
+        /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
+        /*                                                                */
+        /*      On the other hand, they all have different                */
+        /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
+        /*      table cannot be used to compute the text height reliably! */
+        /*                                                                */
+
+        /* The ascender/descender/height are computed from the OS/2 table */
+        /* when found.  Otherwise, they're taken from the horizontal      */
+        /* header.                                                        */
+        /*                                                                */
+
+        root->ascender  = face->horizontal.Ascender;
+        root->descender = face->horizontal.Descender;
+
+        root->height    = (FT_Short)( root->ascender - root->descender +
+                                      face->horizontal.Line_Gap );
+
+        /* if the line_gap is 0, we add an extra 15% to the text height --  */
+        /* this computation is based on various versions of Times New Roman */
+        if ( face->horizontal.Line_Gap == 0 )
+          root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
+
+#if 0
+
+        /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
+        /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
+        if ( face->os2.version != 0xFFFF && root->ascender )
+        {
+          FT_Int  height;
+
+
+          root->ascender  =  face->os2.sTypoAscender;
+          root->descender = -face->os2.sTypoDescender;
+
+          height = root->ascender + root->descender + face->os2.sTypoLineGap;
+          if ( height > root->height )
+            root->height = height;
+        }
+
+#endif /* 0 */
+
+        root->max_advance_width   = face->horizontal.advance_Width_Max;
+
+        root->max_advance_height  = (FT_Short)( face->vertical_info
+                                      ? face->vertical.advance_Height_Max
+                                      : root->height );
+
+        root->underline_position  = face->postscript.underlinePosition;
+        root->underline_thickness = face->postscript.underlineThickness;
+
+        /* root->max_points   -- already set up */
+        /* root->max_contours -- already set up */
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+#undef LOAD_
+
+
+  FT_LOCAL_DEF void
+  SFNT_Done_Face( TT_Face  face )
+  {
+    FT_Memory        memory = face->root.memory;
+    SFNT_Interface*  sfnt   = (SFNT_Interface*)face->sfnt;
+
+
+    if ( sfnt )
+    {
+      /* destroy the postscript names table if it is loaded */
+      if ( sfnt->free_psnames )
+        sfnt->free_psnames( face );
+
+      /* destroy the embedded bitmaps table if it is loaded */
+      if ( sfnt->free_sbits )
+        sfnt->free_sbits( face );
+    }
+
+    /* freeing the kerning table */
+    FREE( face->kern_pairs );
+    face->num_kern_pairs = 0;
+
+    /* freeing the collection table */
+    FREE( face->ttc_header.offsets );
+    face->ttc_header.count = 0;
+
+    /* freeing table directory */
+    FREE( face->dir_tables );
+    face->num_tables = 0;
+
+    /* freeing the character mapping tables */
+    if ( sfnt && sfnt->load_charmaps )
+    {
+      FT_UShort  n;
+
+
+      for ( n = 0; n < face->num_charmaps; n++ )
+        sfnt->free_charmap( face, &face->charmaps[n].cmap );
+    }
+
+    FREE( face->charmaps );
+    face->num_charmaps = 0;
+
+    FREE( face->root.charmaps );
+    face->root.num_charmaps = 0;
+    face->root.charmap      = 0;
+
+    /* freeing the horizontal metrics */
+    FREE( face->horizontal.long_metrics );
+    FREE( face->horizontal.short_metrics );
+
+    /* freeing the vertical ones, if any */
+    if ( face->vertical_info )
+    {
+      FREE( face->vertical.long_metrics  );
+      FREE( face->vertical.short_metrics );
+      face->vertical_info = 0;
+    }
+
+    /* freeing the gasp table */
+    FREE( face->gasp.gaspRanges );
+    face->gasp.numRanges = 0;
+
+    /* freeing the name table */
+    sfnt->free_names( face );
+
+    /* freeing the hdmx table */
+    sfnt->free_hdmx( face );
+
+    /* freeing family and style name */
+    FREE( face->root.family_name );
+    FREE( face->root.style_name );
+
+    /* freeing sbit size table */
+    face->root.num_fixed_sizes = 0;
+    if ( face->root.available_sizes )
+      FREE( face->root.available_sizes );
+
+    face->sfnt = 0;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/smooth.c b/libraries/freetype-2.0.5/smooth.c
new file mode 100644 (file)
index 0000000..ff6be3e
--- /dev/null
@@ -0,0 +1,26 @@
+/***************************************************************************/
+/*                                                                         */
+/*  smooth.c                                                               */
+/*                                                                         */
+/*    FreeType anti-aliasing rasterer module component (body only).        */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ftgrays.c"
+#include "ftsmooth.c"
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/t1afm.c b/libraries/freetype-2.0.5/t1afm.c
new file mode 100644 (file)
index 0000000..d654da9
--- /dev/null
@@ -0,0 +1,286 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1afm.c                                                                */
+/*                                                                         */
+/*    AFM support for Type 1 fonts (body).                                 */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "t1afm.h"
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+#include <stdlib.h>  /* for qsort()   */
+#include <string.h>  /* for strcmp()  */
+#include <ctype.h>   /* for isalnum() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1afm
+
+
+  FT_LOCAL_DEF void
+  T1_Done_AFM( FT_Memory  memory,
+               T1_AFM*    afm )
+  {
+    FREE( afm->kern_pairs );
+    afm->num_pairs = 0;
+    FREE( afm );
+  }
+
+
+#undef  IS_KERN_PAIR
+#define IS_KERN_PAIR( p )  ( p[0] == 'K' && p[1] == 'P' )
+
+#define IS_ALPHANUM( c )  ( isalnum( c ) || \
+                            c == '_'     || \
+                            c == '.'     )
+
+
+  /* read a glyph name and return the equivalent glyph index */
+  static FT_UInt
+  afm_atoindex( FT_Byte**  start,
+                FT_Byte*   limit,
+                T1_Font*   type1 )
+  {
+    FT_Byte*  p = *start;
+    FT_Int    len;
+    FT_UInt   result = 0;
+    char      temp[64];
+
+
+    /* skip whitespace */
+    while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) &&
+            p < limit                                             )
+      p++;
+    *start = p;
+
+    /* now, read glyph name */
+    while ( IS_ALPHANUM( *p ) && p < limit )
+      p++;
+
+    len = (FT_Int)( p - *start );
+
+    if ( len > 0 && len < 64 )
+    {
+      FT_Int  n;
+
+
+      /* copy glyph name to intermediate array */
+      MEM_Copy( temp, *start, len );
+      temp[len] = 0;
+
+      /* lookup glyph name in face array */
+      for ( n = 0; n < type1->num_glyphs; n++ )
+      {
+        char*  gname = (char*)type1->glyph_names[n];
+
+
+        if ( gname && gname[0] == temp[0] && strcmp( gname, temp ) == 0 )
+        {
+          result = n;
+          break;
+        }
+      }
+    }
+    *start = p;
+    return result;
+  }
+
+
+  /* read an integer */
+  static int
+  afm_atoi( FT_Byte**  start,
+            FT_Byte*   limit )
+  {
+    FT_Byte*  p    = *start;
+    int       sum  = 0;
+    int       sign = 1;
+
+
+    /* skip everything that is not a number */
+    while ( p < limit && !isdigit( *p ) )
+    {
+      sign = 1;
+      if ( *p == '-' )
+        sign = -1;
+
+      p++;
+    }
+
+    while ( p < limit && isdigit( *p ) )
+    {
+      sum = sum * 10 + ( *p - '0' );
+      p++;
+    }
+    *start = p;
+
+    return sum * sign;
+  }
+
+
+#undef  KERN_INDEX
+#define KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
+
+
+  /* compare two kerning pairs */
+  FT_CALLBACK_DEF( int )
+  compare_kern_pairs( const void*  a,
+                      const void*  b )
+  {
+    T1_Kern_Pair*  pair1 = (T1_Kern_Pair*)a;
+    T1_Kern_Pair*  pair2 = (T1_Kern_Pair*)b;
+
+    FT_ULong  index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 );
+    FT_ULong  index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 );
+
+
+    return ( index1 - index2 );
+  }
+
+
+  /* parse an AFM file -- for now, only read the kerning pairs */
+  FT_LOCAL_DEF FT_Error
+  T1_Read_AFM( FT_Face    t1_face,
+               FT_Stream  stream )
+  {
+    FT_Error       error;
+    FT_Memory      memory = stream->memory;
+    FT_Byte*       start;
+    FT_Byte*       limit;
+    FT_Byte*       p;
+    FT_Int         count = 0;
+    T1_Kern_Pair*  pair;
+    T1_Font*       type1 = &((T1_Face)t1_face)->type1;
+    T1_AFM*        afm   = 0;
+
+
+    if ( ACCESS_Frame( stream->size ) )
+      return error;
+
+    start = (FT_Byte*)stream->cursor;
+    limit = (FT_Byte*)stream->limit;
+    p     = start;
+
+    /* we are now going to count the occurences of `KP' or `KPX' in */
+    /* the AFM file                                                 */
+    count = 0;
+    for ( p = start; p < limit - 3; p++ )
+    {
+      if ( IS_KERN_PAIR( p ) )
+        count++;
+    }
+
+    /* Actually, kerning pairs are simply optional! */
+    if ( count == 0 )
+      goto Exit;
+
+    /* allocate the pairs */
+    if ( ALLOC( afm, sizeof ( *afm ) )                       ||
+         ALLOC_ARRAY( afm->kern_pairs, count, T1_Kern_Pair ) )
+      goto Exit;
+
+    /* now, read each kern pair */
+    pair           = afm->kern_pairs;
+    afm->num_pairs = count;
+
+    /* save in face object */
+    ((T1_Face)t1_face)->afm_data = afm;
+
+    t1_face->face_flags |= FT_FACE_FLAG_KERNING;
+
+    for ( p = start; p < limit - 3; p++ )
+    {
+      if ( IS_KERN_PAIR( p ) )
+      {
+        FT_Byte*  q;
+
+
+        /* skip keyword (KP or KPX) */
+        q = p + 2;
+        if ( *q == 'X' )
+          q++;
+
+        pair->glyph1    = afm_atoindex( &q, limit, type1 );
+        pair->glyph2    = afm_atoindex( &q, limit, type1 );
+        pair->kerning.x = afm_atoi( &q, limit );
+
+        pair->kerning.y = 0;
+        if ( p[2] != 'X' )
+          pair->kerning.y = afm_atoi( &q, limit );
+
+        pair++;
+      }
+    }
+
+    /* now, sort the kern pairs according to their glyph indices */
+    qsort( afm->kern_pairs, count, sizeof ( T1_Kern_Pair ),
+           compare_kern_pairs );
+
+  Exit:
+    if ( error )
+      FREE( afm );
+
+    FORGET_Frame();
+
+    return error;
+  }
+
+
+  /* find the kerning for a given glyph pair */
+  FT_LOCAL_DEF void
+  T1_Get_Kerning( T1_AFM*     afm,
+                  FT_UInt     glyph1,
+                  FT_UInt     glyph2,
+                  FT_Vector*  kerning )
+  {
+    T1_Kern_Pair  *min, *mid, *max;
+    FT_ULong      index = KERN_INDEX( glyph1, glyph2 );
+
+
+    /* simple binary search */
+    min = afm->kern_pairs;
+    max = min + afm->num_pairs - 1;
+
+    while ( min <= max )
+    {
+      FT_ULong  midi;
+
+
+      mid  = min + ( max - min ) / 2;
+      midi = KERN_INDEX( mid->glyph1, mid->glyph2 );
+
+      if ( midi == index )
+      {
+        *kerning = mid->kerning;
+        return;
+      }
+
+      if ( midi < index )
+        min = mid + 1;
+      else
+        max = mid - 1;
+    }
+
+    kerning->x = 0;
+    kerning->y = 0;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/t1decode.c b/libraries/freetype-2.0.5/t1decode.c
new file mode 100644 (file)
index 0000000..6139ed3
--- /dev/null
@@ -0,0 +1,1082 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1decode.c                                                             */
+/*                                                                         */
+/*    PostScript Type 1 decoding routines (body).                          */
+/*                                                                         */
+/*  Copyright 2000-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_OUTLINE_H
+
+#include "t1decode.h"
+#include "psobjs.h"
+
+#include "psauxerr.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1decode
+
+
+  typedef enum  T1_Operator_
+  {
+    op_none = 0,
+    op_endchar,
+    op_hsbw,
+    op_seac,
+    op_sbw,
+    op_closepath,
+    op_hlineto,
+    op_hmoveto,
+    op_hvcurveto,
+    op_rlineto,
+    op_rmoveto,
+    op_rrcurveto,
+    op_vhcurveto,
+    op_vlineto,
+    op_vmoveto,
+    op_dotsection,
+    op_hstem,
+    op_hstem3,
+    op_vstem,
+    op_vstem3,
+    op_div,
+    op_callothersubr,
+    op_callsubr,
+    op_pop,
+    op_return,
+    op_setcurrentpoint,
+
+    op_max    /* never remove this one */
+
+  } T1_Operator;
+
+  static
+  const FT_Int  t1_args_count[op_max] =
+  {
+    0, /* none */
+    0, /* endchar */
+    2, /* hsbw */
+    5, /* seac */
+    4, /* sbw */
+    0, /* closepath */
+    1, /* hlineto */
+    1, /* hmoveto */
+    4, /* hvcurveto */
+    2, /* rlineto */
+    2, /* rmoveto */
+    6, /* rrcurveto */
+    4, /* vhcurveto */
+    1, /* vlineto */
+    1, /* vmoveto */
+    0, /* dotsection */
+    2, /* hstem */
+    6, /* hstem3 */
+    2, /* vstem */
+    6, /* vstem3 */
+    2, /* div */
+   -1, /* callothersubr */
+    1, /* callsubr */
+    0, /* pop */
+    0, /* return */
+    2  /* setcurrentpoint */
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1_lookup_glyph_by_stdcharcode                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Looks up a given glyph by its StandardEncoding charcode.  Used to  */
+  /*    implement the SEAC Type 1 operator.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: The current face object.                               */
+  /*                                                                       */
+  /*    charcode :: The character code to look for.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A glyph index in the font face.  Returns -1 if the corresponding   */
+  /*    glyph wasn't found.                                                */
+  /*                                                                       */
+  static FT_Int
+  t1_lookup_glyph_by_stdcharcode( T1_Decoder*  decoder,
+                                  FT_Int       charcode )
+  {
+    FT_UInt             n;
+    const FT_String*    glyph_name;
+    PSNames_Interface*  psnames = decoder->psnames;
+
+
+    /* check range of standard char code */
+    if ( charcode < 0 || charcode > 255 )
+      return -1;
+
+    glyph_name = psnames->adobe_std_strings(
+                   psnames->adobe_std_encoding[charcode]);
+
+    for ( n = 0; n < decoder->num_glyphs; n++ )
+    {
+      FT_String*  name = (FT_String*)decoder->glyph_names[n];
+
+
+      if ( name && strcmp( name,glyph_name ) == 0 )
+        return n;
+    }
+
+    return -1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1operator_seac                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    decoder :: The current CID decoder.                                */
+  /*                                                                       */
+  /*    asb     :: The accent's side bearing.                              */
+  /*                                                                       */
+  /*    adx     :: The horizontal offset of the accent.                    */
+  /*                                                                       */
+  /*    ady     :: The vertical offset of the accent.                      */
+  /*                                                                       */
+  /*    bchar   :: The base character's StandardEncoding charcode.         */
+  /*                                                                       */
+  /*    achar   :: The accent character's StandardEncoding charcode.       */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  t1operator_seac( T1_Decoder*  decoder,
+                   FT_Pos       asb,
+                   FT_Pos       adx,
+                   FT_Pos       ady,
+                   FT_Int       bchar,
+                   FT_Int       achar )
+  {
+    FT_Error     error;
+    FT_Int       bchar_index, achar_index, n_base_points;
+    FT_Outline*  base = decoder->builder.base;
+    FT_Vector    left_bearing, advance;
+
+
+    /* seac weirdness */
+    adx += decoder->builder.left_bearing.x;
+
+    /* `glyph_names' is set to 0 for CID fonts which do not */
+    /* include an encoding.  How can we deal with these?    */
+    if ( decoder->glyph_names == 0 )
+    {
+      FT_ERROR(( "t1operator_seac:" ));
+      FT_ERROR(( " glyph names table not available in this font!\n" ));
+      return PSaux_Err_Syntax_Error;
+    }
+
+    bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
+    achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
+
+    if ( bchar_index < 0 || achar_index < 0 )
+    {
+      FT_ERROR(( "t1operator_seac:" ));
+      FT_ERROR(( " invalid seac character code arguments\n" ));
+      return PSaux_Err_Syntax_Error;
+    }
+
+    /* if we are trying to load a composite glyph, do not load the */
+    /* accent character and return the array of subglyphs.         */
+    if ( decoder->builder.no_recurse )
+    {
+      FT_GlyphSlot     glyph  = (FT_GlyphSlot)decoder->builder.glyph;
+      FT_GlyphLoader*  loader = glyph->internal->loader;
+      FT_SubGlyph*     subg;
+
+
+      /* reallocate subglyph array if necessary */
+      error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+      if ( error )
+        goto Exit;
+
+      subg = loader->current.subglyphs;
+
+      /* subglyph 0 = base character */
+      subg->index = bchar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+      subg->arg1  = 0;
+      subg->arg2  = 0;
+      subg++;
+
+      /* subglyph 1 = accent character */
+      subg->index = achar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+      subg->arg1  = adx - asb;
+      subg->arg2  = ady;
+
+      /* set up remaining glyph fields */
+      glyph->num_subglyphs = 2;
+      glyph->subglyphs     = loader->base.subglyphs;
+      glyph->format        = ft_glyph_format_composite;
+
+      loader->current.num_subglyphs = 2;
+    }
+
+    /* First load `bchar' in builder */
+    /* now load the unscaled outline */
+
+    FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */
+
+    error = T1_Decoder_Parse_Glyph( decoder, bchar_index );
+    if ( error )
+      goto Exit;
+
+    n_base_points = base->n_points;
+
+    /* save the left bearing and width of the base character */
+    /* as they will be erased by the next load.              */
+
+    left_bearing = decoder->builder.left_bearing;
+    advance      = decoder->builder.advance;
+
+    decoder->builder.left_bearing.x = 0;
+    decoder->builder.left_bearing.y = 0;
+
+    /* Now load `achar' on top of */
+    /* the base outline           */
+    error = T1_Decoder_Parse_Glyph( decoder, achar_index );
+    if ( error )
+      goto Exit;
+
+    /* restore the left side bearing and   */
+    /* advance width of the base character */
+
+    decoder->builder.left_bearing = left_bearing;
+    decoder->builder.advance      = advance;
+
+    /* Finally, move the accent */
+    if ( decoder->builder.load_points )
+    {
+      FT_Outline  dummy;
+
+
+      dummy.n_points = (short)( base->n_points - n_base_points );
+      dummy.points   = base->points + n_base_points;
+
+      FT_Outline_Translate( &dummy, adx - asb, ady );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Decoder_Parse_Charstrings                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parses a given Type 1 charstrings program.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    decoder         :: The current Type 1 decoder.                     */
+  /*                                                                       */
+  /*    charstring_base :: The base address of the charstring stream.      */
+  /*                                                                       */
+  /*    charstring_len  :: The length in bytes of the charstring stream.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  T1_Decoder_Parse_Charstrings( T1_Decoder*  decoder,
+                                FT_Byte*     charstring_base,
+                                FT_UInt      charstring_len )
+  {
+    FT_Error          error;
+    T1_Decoder_Zone*  zone;
+    FT_Byte*          ip;
+    FT_Byte*          limit;
+    T1_Builder*       builder = &decoder->builder;
+    FT_Pos            x, y;
+
+
+    /* we don't want to touch the source code -- use macro trick */
+#define start_point    T1_Builder_Start_Point
+#define check_points   T1_Builder_Check_Points
+#define add_point      T1_Builder_Add_Point
+#define add_point1     T1_Builder_Add_Point1
+#define add_contour    T1_Builder_Add_Contour
+#define close_contour  T1_Builder_Close_Contour
+
+    /* First of all, initialize the decoder */
+    decoder->top  = decoder->stack;
+    decoder->zone = decoder->zones;
+    zone          = decoder->zones;
+
+    builder->path_begun  = 0;
+
+    zone->base           = charstring_base;
+    limit = zone->limit  = charstring_base + charstring_len;
+    ip    = zone->cursor = zone->base;
+
+    error = PSaux_Err_Ok;
+
+    x = builder->pos_x;
+    y = builder->pos_y;
+
+    /* now, execute loop */
+    while ( ip < limit )
+    {
+      FT_Long*     top   = decoder->top;
+      T1_Operator  op    = op_none;
+      FT_Long      value = 0;
+
+
+      /*********************************************************************/
+      /*                                                                   */
+      /* Decode operator or operand                                        */
+      /*                                                                   */
+      /*                                                                   */
+
+      /* first of all, decompress operator or value */
+      switch ( *ip++ )
+      {
+      case 1:
+        op = op_hstem;
+        break;
+
+      case 3:
+        op = op_vstem;
+        break;
+      case 4:
+        op = op_vmoveto;
+        break;
+      case 5:
+        op = op_rlineto;
+        break;
+      case 6:
+        op = op_hlineto;
+        break;
+      case 7:
+        op = op_vlineto;
+        break;
+      case 8:
+        op = op_rrcurveto;
+        break;
+      case 9:
+        op = op_closepath;
+        break;
+      case 10:
+        op = op_callsubr;
+        break;
+      case 11:
+        op = op_return;
+        break;
+
+      case 13:
+        op = op_hsbw;
+        break;
+      case 14:
+        op = op_endchar;
+        break;
+
+      case 21:
+        op = op_rmoveto;
+        break;
+      case 22:
+        op = op_hmoveto;
+        break;
+
+      case 30:
+        op = op_vhcurveto;
+        break;
+      case 31:
+        op = op_hvcurveto;
+        break;
+
+      case 12:
+        if ( ip > limit )
+        {
+          FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                     "invalid escape (12+EOF)\n" ));
+          goto Syntax_Error;
+        }
+
+        switch ( *ip++ )
+        {
+        case 0:
+          op = op_dotsection;
+          break;
+        case 1:
+          op = op_vstem3;
+          break;
+        case 2:
+          op = op_hstem3;
+          break;
+        case 6:
+          op = op_seac;
+          break;
+        case 7:
+          op = op_sbw;
+          break;
+        case 12:
+          op = op_div;
+          break;
+        case 16:
+          op = op_callothersubr;
+          break;
+        case 17:
+          op = op_pop;
+          break;
+        case 33:
+          op = op_setcurrentpoint;
+          break;
+
+        default:
+          FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                     "invalid escape (12+%d)\n",
+                     ip[-1] ));
+          goto Syntax_Error;
+        }
+        break;
+
+      case 255:    /* four bytes integer */
+        if ( ip + 4 > limit )
+        {
+          FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                     "unexpected EOF in integer\n" ));
+          goto Syntax_Error;
+        }
+
+        value = (FT_Int32)( ((FT_Long)ip[0] << 24) |
+                            ((FT_Long)ip[1] << 16) |
+                            ((FT_Long)ip[2] << 8 ) |
+                                      ip[3] );
+        ip += 4;
+        break;
+
+      default:
+        if ( ip[-1] >= 32 )
+        {
+          if ( ip[-1] < 247 )
+            value = (FT_Long)ip[-1] - 139;
+          else
+          {
+            if ( ++ip > limit )
+            {
+              FT_ERROR(( "T1_Decoder_Parse_CharStrings: " ));
+              FT_ERROR(( "unexpected EOF in integer\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( ip[-2] < 251 )
+              value =  ( ( (FT_Long)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+            else
+              value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+          }
+        }
+        else
+        {
+          FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                     "invalid byte (%d)\n", ip[-1] ));
+          goto Syntax_Error;
+        }
+      }
+
+      /*********************************************************************/
+      /*                                                                   */
+      /*  Push value on stack, or process operator                         */
+      /*                                                                   */
+      /*                                                                   */
+      if ( op == op_none )
+      {
+        if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
+        {
+          FT_ERROR(( "T1_Decoder_Parse_CharStrings: stack overflow!\n" ));
+          goto Syntax_Error;
+        }
+
+        FT_TRACE4(( " %ld", value ));
+
+        *top++       = value;
+        decoder->top = top;
+      }
+      else if ( op == op_callothersubr )  /* callothersubr */
+      {
+        FT_TRACE4(( " callothersubr" ));
+
+        if ( top - decoder->stack < 2 )
+          goto Stack_Underflow;
+
+        top -= 2;
+        switch ( top[1] )
+        {
+        case 1:                     /* start flex feature */
+          if ( top[0] != 0 )
+            goto Unexpected_OtherSubr;
+
+          decoder->flex_state        = 1;
+          decoder->num_flex_vectors  = 0;
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 6 )   )
+            goto Memory_Error;
+          break;
+
+        case 2:                     /* add flex vectors */
+          {
+            FT_Int  index;
+
+            if ( top[0] != 0 )
+              goto Unexpected_OtherSubr;
+
+            /* note that we should not add a point for index 0; */
+            /* this will move our current position to the flex  */
+            /* point without adding any point to the outline    */
+            index = decoder->num_flex_vectors++;
+            if ( index > 0 && index < 7 )
+              add_point( builder,
+                         x,
+                         y,
+                         (FT_Byte)( index == 3 || index == 6 ) );
+          }
+          break;
+
+        case 0:                     /* end flex feature */
+          if ( top[0] != 3 )
+            goto Unexpected_OtherSubr;
+
+          if ( decoder->flex_state       == 0 ||
+               decoder->num_flex_vectors != 7 )
+          {
+            FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                       "unexpected flex end\n" ));
+            goto Syntax_Error;
+          }
+
+          /* now consume the remaining `pop pop setcurpoint' */
+          if ( ip + 6 > limit ||
+               ip[0] != 12 || ip[1] != 17 || /* pop */
+               ip[2] != 12 || ip[3] != 17 || /* pop */
+               ip[4] != 12 || ip[5] != 33 )  /* setcurpoint */
+          {
+            FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                       "invalid flex charstring\n" ));
+            goto Syntax_Error;
+          }
+
+          ip += 6;
+          decoder->flex_state = 0;
+          break;
+
+        case 3:                     /* change hints */
+          if ( top[0] != 1 )
+            goto Unexpected_OtherSubr;
+
+          /* eat the following `pop' */
+          if ( ip + 2 > limit )
+          {
+            FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                       "invalid escape (12+%d)\n", ip[-1] ));
+            goto Syntax_Error;
+          }
+
+          if ( ip[0] != 12 || ip[1] != 17 )
+          {
+            FT_ERROR(( "T1_Decoder_Parse_CharStrings: " ));
+            FT_ERROR(( "`pop' expected, found (%d %d)\n", ip[0], ip[1] ));
+            goto Syntax_Error;
+          }
+          ip += 2;
+          break;
+
+        case 12:
+        case 13:
+          /* counter control hints, clear stack */
+          top = decoder->stack;
+          break;
+
+        case 14:
+        case 15:
+        case 16:
+        case 17:
+        case 18:                    /* multiple masters */
+          {
+            T1_Blend*  blend = decoder->blend;
+            FT_UInt    num_points, nn, mm;
+            FT_Long*   delta;
+            FT_Long*   values;
+
+
+            if ( !blend )
+            {
+              FT_ERROR(( "T1_Decoder_Parse_CharStrings: " ));
+              FT_ERROR(( "unexpected multiple masters operator!\n" ));
+              goto Syntax_Error;
+            }
+
+            num_points = top[1] - 13 + ( top[1] == 18 );
+            if ( top[0] != (FT_Int)( num_points * blend->num_designs ) )
+            {
+              FT_ERROR(( "T1_Decoder_Parse_CharStrings: " ));
+              FT_ERROR(( "incorrect number of mm arguments\n" ));
+              goto Syntax_Error;
+            }
+
+            top -= blend->num_designs*num_points;
+            if ( top < decoder->stack )
+              goto Stack_Underflow;
+
+            /* we want to compute:                                   */
+            /*                                                       */
+            /*  a0*w0 + a1*w1 + ... + ak*wk                          */
+            /*                                                       */
+            /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
+            /* however, given that w0 + w1 + ... + wk == 1, we can   */
+            /* rewrite it easily as:                                 */
+            /*                                                       */
+            /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
+            /*                                                       */
+            /* where k == num_designs-1                              */
+            /*                                                       */
+            /* I guess that's why it's written in this `compact'     */
+            /* form.                                                 */
+            /*                                                       */
+            delta  = top + num_points;
+            values = top;
+            for ( nn = 0; nn < num_points; nn++ )
+            {
+              FT_Int  tmp = values[0];
+
+
+              for ( mm = 1; mm < blend->num_designs; mm++ )
+                tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
+
+              *values++ = tmp;
+            }
+            /* note that `top' will be incremented later by calls to `pop' */
+            break;
+          }
+
+        default:
+        Unexpected_OtherSubr:
+          FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                     "invalid othersubr [%d %d]!\n", top[0], top[1] ));
+          goto Syntax_Error;
+        }
+        decoder->top = top;
+      }
+      else  /* general operator */
+      {
+        FT_Int  num_args = t1_args_count[op];
+
+
+        if ( top - decoder->stack < num_args )
+          goto Stack_Underflow;
+
+        top -= num_args;
+
+        switch ( op )
+        {
+        case op_endchar:
+          FT_TRACE4(( " endchar" ));
+
+          close_contour( builder );
+
+          /* add current outline to the glyph slot */
+          FT_GlyphLoader_Add( builder->loader );
+
+          /* return now! */
+          FT_TRACE4(( "\n\n" ));
+          return PSaux_Err_Ok;
+
+        case op_hsbw:
+          FT_TRACE4(( " hsbw" ));
+
+          builder->left_bearing.x += top[0];
+          builder->advance.x       = top[1];
+          builder->advance.y       = 0;
+
+          builder->last.x = x = top[0];
+          builder->last.y = y = 0;
+
+          /* the `metrics_only' indicates that we only want to compute */
+          /* the glyph's metrics (lsb + advance width), not load the   */
+          /* rest of it; so exit immediately                           */
+          if ( builder->metrics_only )
+            return PSaux_Err_Ok;
+
+          break;
+
+        case op_seac:
+          /* return immediately after the processing */
+          return t1operator_seac( decoder, top[0], top[1],
+                                           top[2], top[3], top[4] );
+
+        case op_sbw:
+          FT_TRACE4(( " sbw" ));
+
+          builder->left_bearing.x += top[0];
+          builder->left_bearing.y += top[1];
+          builder->advance.x       = top[2];
+          builder->advance.y       = top[3];
+
+          builder->last.x = x = top[0];
+          builder->last.y = y = top[1];
+
+          /* the `metrics_only' indicates that we only want to compute */
+          /* the glyph's metrics (lsb + advance width), not load the   */
+          /* rest of it; so exit immediately                           */
+          if ( builder->metrics_only )
+            return PSaux_Err_Ok;
+
+          break;
+
+        case op_closepath:
+          FT_TRACE4(( " closepath" ));
+
+          close_contour( builder );
+          builder->path_begun = 0;
+          break;
+
+        case op_hlineto:
+          FT_TRACE4(( " hlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          x += top[0];
+          goto Add_Line;
+
+        case op_hmoveto:
+          FT_TRACE4(( " hmoveto" ));
+
+          x += top[0];
+          if ( !decoder->flex_state )
+            builder->path_begun = 0;
+          break;
+
+        case op_hvcurveto:
+          FT_TRACE4(( " hvcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          x += top[0];
+          add_point( builder, x, y, 0 );
+          x += top[1];
+          y += top[2];
+          add_point( builder, x, y, 0 );
+          y += top[3];
+          add_point( builder, x, y, 1 );
+          break;
+
+        case op_rlineto:
+          FT_TRACE4(( " rlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          x += top[0];
+          y += top[1];
+
+        Add_Line:
+          if ( add_point1( builder, x, y ) )
+            goto Memory_Error;
+          break;
+
+        case op_rmoveto:
+          FT_TRACE4(( " rmoveto" ));
+
+          x += top[0];
+          y += top[1];
+          if ( !decoder->flex_state )
+            builder->path_begun = 0;
+          break;
+
+        case op_rrcurveto:
+          FT_TRACE4(( " rcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          x += top[0];
+          y += top[1];
+          add_point( builder, x, y, 0 );
+
+          x += top[2];
+          y += top[3];
+          add_point( builder, x, y, 0 );
+
+          x += top[4];
+          y += top[5];
+          add_point( builder, x, y, 1 );
+          break;
+
+        case op_vhcurveto:
+          FT_TRACE4(( " vhcurveto" ));
+
+          if ( start_point( builder, x, y ) ||
+               check_points( builder, 3 )   )
+            goto Memory_Error;
+
+          y += top[0];
+          add_point( builder, x, y, 0 );
+          x += top[1];
+          y += top[2];
+          add_point( builder, x, y, 0 );
+          x += top[3];
+          add_point( builder, x, y, 1 );
+          break;
+
+        case op_vlineto:
+          FT_TRACE4(( " vlineto" ));
+
+          if ( start_point( builder, x, y ) )
+            goto Memory_Error;
+
+          y += top[0];
+          goto Add_Line;
+
+        case op_vmoveto:
+          FT_TRACE4(( " vmoveto" ));
+
+          y += top[0];
+          if ( !decoder->flex_state )
+            builder->path_begun = 0;
+          break;
+
+        case op_div:
+          FT_TRACE4(( " div" ));
+
+          if ( top[1] )
+          {
+            *top = top[0] / top[1];
+            ++top;
+          }
+          else
+          {
+            FT_ERROR(( "T1_Decoder_Parse_CharStrings: division by 0\n" ));
+            goto Syntax_Error;
+          }
+          break;
+
+        case op_callsubr:
+          {
+            FT_Int  index;
+
+
+            FT_TRACE4(( " callsubr" ));
+
+            index = top[0];
+            if ( index < 0 || index >= (FT_Int)decoder->num_subrs )
+            {
+              FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                         "invalid subrs index\n" ));
+              goto Syntax_Error;
+            }
+
+            if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+            {
+              FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                         "too many nested subrs\n" ));
+              goto Syntax_Error;
+            }
+
+            zone->cursor = ip;  /* save current instruction pointer */
+
+            zone++;
+
+            /* The Type 1 driver stores subroutines without the seed bytes. */
+            /* The CID driver stores subroutines with seed bytes.  This     */
+            /* case is taken care of when decoder->subrs_len == 0.          */
+            zone->base = decoder->subrs[index];
+
+            if ( decoder->subrs_len )
+              zone->limit = zone->base + decoder->subrs_len[index];
+            else
+            {
+              /* We are using subroutines from a CID font.  We must adjust */
+              /* for the seed bytes.                                       */
+              zone->base  += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
+              zone->limit  = decoder->subrs[index + 1];
+            }
+
+            zone->cursor = zone->base;
+
+            if ( !zone->base )
+            {
+              FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                         "invoking empty subrs!\n" ));
+              goto Syntax_Error;
+            }
+
+            decoder->zone = zone;
+            ip            = zone->base;
+            limit         = zone->limit;
+            break;
+          }
+
+        case op_pop:
+          FT_TRACE4(( " pop" ));
+
+          /* theoretically, the arguments are already on the stack */
+          top++;
+          break;
+
+        case op_return:
+          FT_TRACE4(( " return" ));
+
+          if ( zone <= decoder->zones )
+          {
+            FT_ERROR(( "T1_Decoder_Parse_CharStrings: unexpected return\n" ));
+            goto Syntax_Error;
+          }
+
+          zone--;
+          ip            = zone->cursor;
+          limit         = zone->limit;
+          decoder->zone = zone;
+          break;
+
+        case op_dotsection:
+          FT_TRACE4(( " dotsection" ));
+
+          break;
+
+        case op_hstem:
+          FT_TRACE4(( " hstem" ));
+
+          break;
+
+        case op_hstem3:
+          FT_TRACE4(( " hstem3" ));
+
+          break;
+
+        case op_vstem:
+          FT_TRACE4(( " vstem" ));
+
+          break;
+
+        case op_vstem3:
+          FT_TRACE4(( " vstem3" ));
+
+          break;
+
+        case op_setcurrentpoint:
+          FT_TRACE4(( " setcurrentpoint" ));
+
+          FT_ERROR(( "T1_Decoder_Parse_CharStrings: " ));
+          FT_ERROR(( "unexpected `setcurrentpoint'\n" ));
+          goto Syntax_Error;
+
+        default:
+          FT_ERROR(( "T1_Decoder_Parse_CharStrings: "
+                     "unhandled opcode %d\n", op ));
+          goto Syntax_Error;
+        }
+
+        decoder->top = top;
+
+      } /* general operator processing */
+
+    } /* while ip < limit */
+
+    FT_TRACE4(( "..end..\n\n" ));
+    return error;
+
+  Syntax_Error:
+    return PSaux_Err_Syntax_Error;
+
+  Stack_Underflow:
+    return PSaux_Err_Stack_Underflow;
+
+  Memory_Error:
+    return builder->error;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_Decoder_Parse_Glyph( T1_Decoder*  decoder,
+                          FT_UInt      glyph )
+  {
+    return decoder->parse_callback( decoder, glyph );
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_Decoder_Init( T1_Decoder*          decoder,
+                   FT_Face              face,
+                   FT_Size              size,
+                   FT_GlyphSlot         slot,
+                   FT_Byte**            glyph_names,
+                   T1_Blend*            blend,
+                   T1_Decoder_Callback  parse_callback )
+  {
+    MEM_Set( decoder, 0, sizeof ( *decoder ) );
+
+    /* retrieve PSNames interface from list of current modules */
+    {
+      PSNames_Interface*  psnames = 0;
+
+
+      psnames = (PSNames_Interface*)FT_Get_Module_Interface(
+                   FT_FACE_LIBRARY(face), "psnames" );
+      if ( !psnames )
+      {
+        FT_ERROR(( "T1_Decoder_Init: " ));
+        FT_ERROR(( "the `psnames' module is not available\n" ));
+        return PSaux_Err_Unimplemented_Feature;
+      }
+
+      decoder->psnames = psnames;
+    }
+    T1_Builder_Init( &decoder->builder, face, size, slot );
+
+    decoder->num_glyphs     = face->num_glyphs;
+    decoder->glyph_names    = glyph_names;
+    decoder->blend          = blend;
+    decoder->parse_callback = parse_callback;
+
+    decoder->funcs       = t1_decoder_funcs;
+
+    return 0;
+  }
+
+
+  FT_LOCAL_DEF void
+  T1_Decoder_Done( T1_Decoder*  decoder )
+  {
+    T1_Builder_Done( &decoder->builder );
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/t1driver.c b/libraries/freetype-2.0.5/t1driver.c
new file mode 100644 (file)
index 0000000..49be9f6
--- /dev/null
@@ -0,0 +1,407 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1driver.c                                                             */
+/*                                                                         */
+/*    Type 1 driver interface (body).                                      */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "t1driver.h"
+#include "t1gload.h"
+#include "t1load.h"
+
+#include "t1errors.h"
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "t1afm.h"
+#endif
+
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+
+#include <string.h>     /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1driver
+
+
+  static FT_Error
+  t1_get_glyph_name( T1_Face     face,
+                     FT_UInt     glyph_index,
+                     FT_Pointer  buffer,
+                     FT_UInt     buffer_max )
+  {
+    FT_String*  gname;
+
+
+    gname = face->type1.glyph_names[glyph_index];
+
+    if ( buffer_max > 0 )
+    {
+      FT_UInt  len = (FT_UInt)( strlen( gname ) );
+
+
+      if (len >= buffer_max)
+        len = buffer_max - 1;
+
+      MEM_Copy( buffer, gname, len );
+      ((FT_Byte*)buffer)[len] = 0;
+    }
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    t1_get_name_index                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses the Type 1 font's `glyph_names' table to find a given glyph   */
+  /*    name's glyph index.                                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the source face object.                  */
+  /*                                                                       */
+  /*    glyph_name :: The glyph name.                                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static FT_UInt
+  t1_get_name_index( T1_Face     face,
+                     FT_String*  glyph_name )
+  {
+    FT_Int      i;
+    FT_String*  gname;
+
+
+    for ( i = 0; i < face->type1.num_glyphs; i++ )
+    {
+      gname = face->type1.glyph_names[i];
+
+      if ( !strcmp( glyph_name, gname ) )
+        return (FT_UInt)i;
+    }
+
+    return 0;
+  }
+
+
+  static const char*
+  t1_get_ps_name( T1_Face    face )
+  {
+    return (const char*) face->type1.font_name;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Interface                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Each driver can provide one or more extensions to the base         */
+  /*    FreeType API.  These can be used to access format specific         */
+  /*    features (e.g., all TrueType/OpenType resources share a common     */
+  /*    file structure and common tables which can be accessed through the */
+  /*    `sfnt' interface), or more simply generic ones (e.g., the          */
+  /*    `postscript names' interface which can be used to retrieve the     */
+  /*     PostScript name of a given glyph index).                          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    driver    :: A handle to a driver object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    interface :: A string designing the interface.  Examples are       */
+  /*                 `sfnt', `post_names', `charmaps', etc.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A typeless pointer to the extension's interface (normally a table  */
+  /*    of function pointers).  Returns NULL if the requested extension    */
+  /*    isn't available (i.e., wasn't compiled in the driver at build      */
+  /*    time).                                                             */
+  /*                                                                       */
+  static FT_Module_Interface
+  Get_Interface( FT_Driver         driver,
+                 const FT_String*  interface )
+  {
+    FT_UNUSED( driver );
+    FT_UNUSED( interface );
+
+    if ( strcmp( (const char*)interface, "glyph_name" ) == 0 )
+      return (FT_Module_Interface)t1_get_glyph_name;
+
+    if ( strcmp( (const char*)interface, "name_index" ) == 0 )
+      return (FT_Module_Interface)t1_get_name_index;
+
+    if ( strcmp( (const char*)interface, "postscript_name" ) == 0 )
+      return (FT_Module_Interface)t1_get_ps_name;
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+    if ( strcmp( (const char*)interface, "get_mm" ) == 0 )
+      return (FT_Module_Interface)T1_Get_Multi_Master;
+
+    if ( strcmp( (const char*)interface, "set_mm_design") == 0 )
+      return (FT_Module_Interface)T1_Set_MM_Design;
+
+    if ( strcmp( (const char*)interface, "set_mm_blend") == 0 )
+      return (FT_Module_Interface)T1_Set_MM_Blend;
+#endif
+    return 0;
+  }
+
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Kerning                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to return the kerning vector between two      */
+  /*    glyphs of the same face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the source face object.                 */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this function.  Other layouts, or more sophisticated  */
+  /*    kernings are out of scope of this method (the basic driver         */
+  /*    interface is meant to be simple).                                  */
+  /*                                                                       */
+  /*    They can be implemented by format-specific interfaces.             */
+  /*                                                                       */
+  static FT_Error
+  Get_Kerning( T1_Face     face,
+               FT_UInt     left_glyph,
+               FT_UInt     right_glyph,
+               FT_Vector*  kerning )
+  {
+    T1_AFM*  afm;
+
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    afm = (T1_AFM*)face->afm_data;
+    if ( afm )
+      T1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+    return T1_Err_Ok;
+  }
+
+
+#endif /* T1_CONFIG_OPTION_NO_AFM */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Char_Index                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static FT_UInt
+  Get_Char_Index( FT_CharMap  charmap,
+                  FT_Long     charcode )
+  {
+    T1_Face             face;
+    FT_UInt             result = 0;
+    PSNames_Interface*  psnames;
+
+
+    face    = (T1_Face)charmap->face;
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( psnames )
+      switch ( charmap->encoding )
+      {
+        /*******************************************************************/
+        /*                                                                 */
+        /* Unicode encoding support                                        */
+        /*                                                                 */
+      case ft_encoding_unicode:
+        /* use the `PSNames' module to synthetize the Unicode charmap */
+        result = psnames->lookup_unicode( &face->unicode_map,
+                                          (FT_ULong)charcode );
+
+        /* the function returns 0xFFFF if the Unicode charcode has */
+        /* no corresponding glyph                                  */
+        if ( result == 0xFFFF )
+          result = 0;
+        goto Exit;
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Custom Type 1 encoding                                          */
+        /*                                                                 */
+      case ft_encoding_adobe_custom:
+        {
+          T1_Encoding*  encoding = &face->type1.encoding;
+
+
+          if ( charcode >= encoding->code_first &&
+               charcode <= encoding->code_last  )
+            result = encoding->char_index[charcode];
+          goto Exit;
+        }
+
+        /*******************************************************************/
+        /*                                                                 */
+        /* Adobe Standard & Expert encoding support                        */
+        /*                                                                 */
+      default:
+        if ( charcode < 256 )
+        {
+          FT_UInt      code;
+          FT_Int       n;
+          const char*  glyph_name;
+
+
+          code = psnames->adobe_std_encoding[charcode];
+          if ( charmap->encoding == ft_encoding_adobe_expert )
+            code = psnames->adobe_expert_encoding[charcode];
+
+          glyph_name = psnames->adobe_std_strings( code );
+          if ( !glyph_name )
+            break;
+
+          for ( n = 0; n < face->type1.num_glyphs; n++ )
+          {
+            const char*  gname = face->type1.glyph_names[n];
+
+
+            if ( gname && gname[0] == glyph_name[0] &&
+                 strcmp( gname, glyph_name ) == 0   )
+            {
+              result = n;
+              break;
+            }
+          }
+        }
+      }
+  Exit:
+    return result;
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Driver_Class  t1_driver_class =
+  {
+    {
+      ft_module_font_driver | ft_module_driver_scalable,
+      sizeof( FT_DriverRec ),
+
+      "type1",
+      0x10000L,
+      0x20000L,
+
+      0,   /* format interface */
+
+      (FT_Module_Constructor)T1_Init_Driver,
+      (FT_Module_Destructor) T1_Done_Driver,
+      (FT_Module_Requester)  Get_Interface,
+    },
+
+    sizeof( T1_FaceRec ),
+    sizeof( T1_SizeRec ),
+    sizeof( T1_GlyphSlotRec ),
+
+    (FTDriver_initFace)     T1_Init_Face,
+    (FTDriver_doneFace)     T1_Done_Face,
+    (FTDriver_initSize)     0,
+    (FTDriver_doneSize)     0,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) 0,
+    (FTDriver_setPixelSizes)0,
+    (FTDriver_loadGlyph)    T1_Load_Glyph,
+    (FTDriver_getCharIndex) Get_Char_Index,
+
+#ifdef T1_CONFIG_OPTION_NO_AFM
+    (FTDriver_getKerning)   0,
+    (FTDriver_attachFile)   0,
+#else
+    (FTDriver_getKerning)   Get_Kerning,
+    (FTDriver_attachFile)   T1_Read_AFM,
+#endif
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverClass                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the TrueType driver as a      */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+  FT_EXPORT_DEF( const FT_Driver_Class* )
+  getDriverClass( void )
+  {
+    return &t1_driver_class;
+  }
+
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/t1gload.c b/libraries/freetype-2.0.5/t1gload.c
new file mode 100644 (file)
index 0000000..f23b2cd
--- /dev/null
@@ -0,0 +1,314 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1gload.c                                                              */
+/*                                                                         */
+/*    Type 1 Glyph Loader (body).                                          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "t1gload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_OUTLINE_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+#include "t1errors.h"
+
+#include <string.h>     /* for strcmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1gload
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of computing      *********/
+  /**********    the maximum advance width of the font.  It        *********/
+  /**********    quickly processes each glyph charstring to        *********/
+  /**********    extract the value from either a `sbw' or `seac'   *********/
+  /**********    operator.                                         *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  T1_Parse_Glyph( T1_Decoder*  decoder,
+                  FT_UInt      glyph_index )
+  {
+    T1_Face   face  = (T1_Face)decoder->builder.face;
+    T1_Font*  type1 = &face->type1;
+
+
+    decoder->font_matrix = type1->font_matrix;
+    decoder->font_offset = type1->font_offset;
+
+    return decoder->funcs.parse_charstrings(
+                      decoder,
+                      type1->charstrings    [glyph_index],
+                      type1->charstrings_len[glyph_index] );
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_Compute_Max_Advance( T1_Face  face,
+                          FT_Int*  max_advance )
+  {
+    FT_Error          error;
+    T1_Decoder        decoder;
+    FT_Int            glyph_index;
+    T1_Font*          type1 = &face->type1;
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+
+    *max_advance = 0;
+
+    /* initialize load decoder */
+    error = psaux->t1_decoder_funcs->init( &decoder,
+                                           (FT_Face)face,
+                                           0, /* size       */
+                                           0, /* glyph slot */
+                                           (FT_Byte**)type1->glyph_names,
+                                           face->blend,
+                                           T1_Parse_Glyph );
+    if ( error )
+      return error;
+
+    decoder.builder.metrics_only = 1;
+    decoder.builder.load_points  = 0;
+
+    decoder.num_subrs = type1->num_subrs;
+    decoder.subrs     = type1->subrs;
+    decoder.subrs_len = type1->subrs_len;
+
+    /* for each glyph, parse the glyph charstring and extract */
+    /* the advance width                                      */
+    for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
+    {
+      /* now get load the unscaled outline */
+      error = T1_Parse_Glyph( &decoder, glyph_index );
+      /* ignore the error if one occured - skip to next glyph */
+    }
+
+    *max_advance = decoder.builder.advance.x;
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /**********                                                      *********/
+  /**********               UNHINTED GLYPH LOADER                  *********/
+  /**********                                                      *********/
+  /**********    The following code is in charge of loading a      *********/
+  /**********    single outline.  It completely ignores hinting    *********/
+  /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
+  /**********                                                      *********/
+  /**********      The Type 1 hinter is located in `t1hint.c'      *********/
+  /**********                                                      *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_Load_Glyph( T1_GlyphSlot  glyph,
+                 T1_Size       size,
+                 FT_Int        glyph_index,
+                 FT_Int        load_flags )
+  {
+    FT_Error                error;
+    T1_Decoder              decoder;
+    T1_Face                 face = (T1_Face)glyph->root.face;
+    FT_Bool                 hinting;
+    T1_Font*                type1         = &face->type1;
+    PSAux_Interface*        psaux         = (PSAux_Interface*)face->psaux;
+    const T1_Decoder_Funcs* decoder_funcs = psaux->t1_decoder_funcs;
+
+    FT_Matrix               font_matrix;
+    FT_Vector               font_offset;
+
+    if ( load_flags & FT_LOAD_NO_RECURSE )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    glyph->x_scale = size->root.metrics.x_scale;
+    glyph->y_scale = size->root.metrics.y_scale;
+
+    glyph->root.outline.n_points   = 0;
+    glyph->root.outline.n_contours = 0;
+
+    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
+                       ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
+
+    glyph->root.format = ft_glyph_format_outline;
+
+    error = decoder_funcs->init( &decoder,
+                                 (FT_Face)face,
+                                 (FT_Size)size,
+                                 (FT_GlyphSlot)glyph,
+                                 (FT_Byte**)type1->glyph_names,
+                                 face->blend,
+                                 T1_Parse_Glyph );
+    if ( error )
+      goto Exit;
+
+    decoder.builder.no_recurse = FT_BOOL(
+                                   ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
+
+    decoder.num_subrs = type1->num_subrs;
+    decoder.subrs     = type1->subrs;
+    decoder.subrs_len = type1->subrs_len;
+
+
+    /* now load the unscaled outline */
+    error = T1_Parse_Glyph( &decoder, glyph_index );
+    if ( error )
+      goto Exit;
+
+    font_matrix = decoder.font_matrix;
+    font_offset = decoder.font_offset;
+
+    /* save new glyph tables */
+    decoder_funcs->done( &decoder );
+
+    /* now, set the metrics -- this is rather simple, as   */
+    /* the left side bearing is the xMin, and the top side */
+    /* bearing the yMax                                    */
+    if ( !error )
+    {
+      glyph->root.outline.flags &= ft_outline_owner;
+      glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+      /* for composite glyphs, return only left side bearing and */
+      /* advance width                                           */
+      if ( load_flags & FT_LOAD_NO_RECURSE )
+      {
+        FT_Slot_Internal  internal = glyph->root.internal;
+
+
+        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+        glyph->root.metrics.horiAdvance  = decoder.builder.advance.x;
+        internal->glyph_matrix           = font_matrix;
+        internal->glyph_delta            = font_offset;
+        internal->glyph_transformed      = 1;
+      }
+      else
+      {
+        FT_BBox            cbox;
+        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
+
+
+        /* copy the _unscaled_ advance width */
+        metrics->horiAdvance                    = decoder.builder.advance.x;
+        glyph->root.linearHoriAdvance           = decoder.builder.advance.x;
+        glyph->root.internal->glyph_transformed = 0;
+
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+
+        glyph->root.linearVertAdvance = 0;
+
+        glyph->root.format = ft_glyph_format_outline;
+
+        if ( size && size->root.metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+
+        /* apply the font matrix */
+        FT_Outline_Transform( &glyph->root.outline, &font_matrix );
+
+        FT_Outline_Translate( &glyph->root.outline,
+                              font_offset.x,
+                              font_offset.y );
+
+#if 0
+
+        glyph->root.outline.second_pass    = TRUE;
+        glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
+        glyph->root.outline.dropout_mode   = 2;
+
+#endif /* 0 */
+
+        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        {
+          /* scale the outline and the metrics */
+          FT_Int       n;
+          FT_Outline*  cur = decoder.builder.base;
+          FT_Vector*   vec = cur->points;
+          FT_Fixed     x_scale = glyph->x_scale;
+          FT_Fixed     y_scale = glyph->y_scale;
+
+
+          /* First of all, scale the points */
+          for ( n = cur->n_points; n > 0; n--, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
+
+          FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+          /* Then scale the metrics */
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
+
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+        }
+
+        /* compute the other metrics */
+        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+        /* grid fit the bounding box if necessary */
+        if ( hinting )
+        {
+          cbox.xMin &= -64;
+          cbox.yMin &= -64;
+          cbox.xMax  = ( cbox.xMax+63 ) & -64;
+          cbox.yMax  = ( cbox.yMax+63 ) & -64;
+        }
+
+        metrics->width  = cbox.xMax - cbox.xMin;
+        metrics->height = cbox.yMax - cbox.yMin;
+
+        metrics->horiBearingX = cbox.xMin;
+        metrics->horiBearingY = cbox.yMax;
+      }
+
+      /* Set control data to the glyph charstrings.  Note that this is */
+      /* _not_ zero-terminated.                                        */
+      glyph->root.control_data = type1->charstrings    [glyph_index];
+      glyph->root.control_len  = type1->charstrings_len[glyph_index];
+    }
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/t1load.c b/libraries/freetype-2.0.5/t1load.c
new file mode 100644 (file)
index 0000000..ce6607f
--- /dev/null
@@ -0,0 +1,1733 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1load.c                                                               */
+/*                                                                         */
+/*    Type 1 font loader (body).                                           */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This is the new and improved Type 1 data loader for FreeType 2.  The  */
+  /* old loader has several problems: it is slow, complex, difficult to    */
+  /* maintain, and contains incredible hacks to make it accept some        */
+  /* ill-formed Type 1 fonts without hiccup-ing.  Moreover, about 5% of    */
+  /* the Type 1 fonts on my machine still aren't loaded correctly by it.   */
+  /*                                                                       */
+  /* This version is much simpler, much faster and also easier to read and */
+  /* maintain by a great order of magnitude.  The idea behind it is to     */
+  /* _not_ try to read the Type 1 token stream with a state machine (i.e.  */
+  /* a Postscript-like interpreter) but rather to perform simple pattern   */
+  /* matching.                                                             */
+  /*                                                                       */
+  /* Indeed, nearly all data definitions follow a simple pattern like      */
+  /*                                                                       */
+  /*  ... /Field <data> ...                                                */
+  /*                                                                       */
+  /* where <data> can be a number, a boolean, a string, or an array of     */
+  /* numbers.  There are a few exceptions, namely the encoding, font name, */
+  /* charstrings, and subrs; they are handled with a special pattern       */
+  /* matching routine.                                                     */
+  /*                                                                       */
+  /* All other common cases are handled very simply.  The matching rules   */
+  /* are defined in the file `t1tokens.h' through the use of several       */
+  /* macros calls PARSE_XXX.                                               */
+  /*                                                                       */
+  /* This file is included twice here; the first time to generate parsing  */
+  /* callback functions, the second to generate a table of keywords (with  */
+  /* pointers to the associated callback).                                 */
+  /*                                                                       */
+  /* The function `parse_dict' simply scans *linearly* a given dictionary  */
+  /* (either the top-level or private one) and calls the appropriate       */
+  /* callback when it encounters an immediate keyword.                     */
+  /*                                                                       */
+  /* This is by far the fastest way one can find to parse and read all     */
+  /* data.                                                                 */
+  /*                                                                       */
+  /* This led to tremendous code size reduction.  Note that later, the     */
+  /* glyph loader will also be _greatly_ simplified, and the automatic     */
+  /* hinter will replace the clumsy `t1hinter'.                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_CONFIG_CONFIG_H
+#include FT_MULTIPLE_MASTERS_H
+#include FT_INTERNAL_TYPE1_TYPES_H
+
+#include "t1load.h"
+
+#include "t1errors.h"
+
+#include <string.h>     /* for strncmp(), strcmp() */
+#include <ctype.h>      /* for isalnum()           */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1load
+
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    MULTIPLE MASTERS SUPPORT                   *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  static FT_Error
+  t1_allocate_blend( T1_Face  face,
+                     FT_UInt  num_designs,
+                     FT_UInt  num_axis )
+  {
+    T1_Blend*  blend;
+    FT_Memory  memory = face->root.memory;
+    FT_Error   error  = 0;
+
+
+    blend = face->blend;
+    if ( !blend )
+    {
+      if ( ALLOC( blend, sizeof ( *blend ) ) )
+        goto Exit;
+
+      face->blend = blend;
+    }
+
+    /* allocate design data if needed */
+    if ( num_designs > 0 )
+    {
+      if ( blend->num_designs == 0 )
+      {
+        FT_UInt  nn;
+
+
+        /* allocate the blend `private' and `font_info' dictionaries */
+        if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo )  ||
+             ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private )     ||
+             ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) )
+          goto Exit;
+
+        blend->default_weight_vector = blend->weight_vector + num_designs;
+
+        blend->font_infos[0] = &face->type1.font_info;
+        blend->privates  [0] = &face->type1.private_dict;
+
+        for ( nn = 2; nn <= num_designs; nn++ )
+        {
+          blend->privates[nn]   = blend->privates  [nn - 1] + 1;
+          blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
+        }
+
+        blend->num_designs   = num_designs;
+      }
+      else if ( blend->num_designs != num_designs )
+        goto Fail;
+    }
+
+    /* allocate axis data if needed */
+    if ( num_axis > 0 )
+    {
+      if ( blend->num_axis != 0 && blend->num_axis != num_axis )
+        goto Fail;
+
+      blend->num_axis = num_axis;
+    }
+
+    /* allocate the blend design pos table if needed */
+    num_designs = blend->num_designs;
+    num_axis    = blend->num_axis;
+    if ( num_designs && num_axis && blend->design_pos[0] == 0 )
+    {
+      FT_UInt  n;
+
+
+      if ( ALLOC_ARRAY( blend->design_pos[0],
+                        num_designs * num_axis, FT_Fixed ) )
+        goto Exit;
+
+      for ( n = 1; n < num_designs; n++ )
+        blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
+    }
+
+  Exit:
+    return error;
+
+  Fail:
+    error = -1;
+    goto Exit;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_Get_Multi_Master( T1_Face           face,
+                       FT_Multi_Master*  master )
+  {
+    T1_Blend*  blend = face->blend;
+    FT_UInt    n;
+    FT_Error   error;
+
+
+    error = T1_Err_Invalid_Argument;
+
+    if ( blend )
+    {
+      master->num_axis    = blend->num_axis;
+      master->num_designs = blend->num_designs;
+
+      for ( n = 0; n < blend->num_axis; n++ )
+      {
+        FT_MM_Axis*    axis = master->axis + n;
+        T1_DesignMap*  map = blend->design_map + n;
+
+
+        axis->name    = blend->axis_names[n];
+        axis->minimum = map->design_points[0];
+        axis->maximum = map->design_points[map->num_points - 1];
+      }
+      error = 0;
+    }
+    return error;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_Set_MM_Blend( T1_Face    face,
+                   FT_UInt    num_coords,
+                   FT_Fixed*  coords )
+  {
+    T1_Blend*  blend = face->blend;
+    FT_Error   error;
+    FT_UInt    n, m;
+
+
+    error = T1_Err_Invalid_Argument;
+
+    if ( blend && blend->num_axis == num_coords )
+    {
+      /* recompute the weight vector from the blend coordinates */
+      error = T1_Err_Ok;
+
+      for ( n = 0; n < blend->num_designs; n++ )
+      {
+        FT_Fixed  result = 0x10000L;  /* 1.0 fixed */
+
+
+        for ( m = 0; m < blend->num_axis; m++ )
+        {
+          FT_Fixed  factor;
+
+
+          /* get current blend axis position */
+          factor = coords[m];
+          if ( factor < 0 )        factor = 0;
+          if ( factor > 0x10000L ) factor = 0x10000L;
+
+          if ( ( n & ( 1 << m ) ) == 0 )
+            factor = 0x10000L - factor;
+
+          result = FT_MulFix( result, factor );
+        }
+        blend->weight_vector[n] = result;
+      }
+
+      error = T1_Err_Ok;
+    }
+    return error;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_Set_MM_Design( T1_Face   face,
+                    FT_UInt   num_coords,
+                    FT_Long*  coords )
+  {
+    T1_Blend*  blend = face->blend;
+    FT_Error   error;
+    FT_UInt    n, p;
+
+
+    error = T1_Err_Invalid_Argument;
+    if ( blend && blend->num_axis == num_coords )
+    {
+      /* compute the blend coordinates through the blend design map */
+      FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
+
+
+      for ( n = 0; n < blend->num_axis; n++ )
+      {
+        FT_Long        design  = coords[n];
+        FT_Fixed       the_blend;
+        T1_DesignMap*  map     = blend->design_map + n;
+        FT_Fixed*      designs = map->design_points;
+        FT_Fixed*      blends  = map->blend_points;
+        FT_Int         before  = -1, after = -1;
+
+        for ( p = 0; p < (FT_UInt)map->num_points; p++ )
+        {
+          FT_Fixed  p_design = designs[p];
+
+
+          /* exact match ? */
+          if ( design == p_design )
+          {
+            the_blend = blends[p];
+            goto Found;
+          }
+
+          if ( design < p_design )
+          {
+            after = p;
+            break;
+          }
+
+          before = p;
+        }
+
+        /* now, interpolate if needed */
+        if ( before < 0 )
+          the_blend = blends[0];
+
+        else if ( after < 0 )
+          the_blend = blends[map->num_points - 1];
+
+        else
+          the_blend = FT_MulDiv( design         - designs[before],
+                                 blends [after] - blends [before],
+                                 designs[after] - designs[before] );
+
+      Found:
+        final_blends[n] = the_blend;
+      }
+
+      error = T1_Set_MM_Blend( face, num_coords, final_blends );
+    }
+
+    return error;
+  }
+
+
+  FT_LOCAL_DEF void
+  T1_Done_Blend( T1_Face  face )
+  {
+    FT_Memory  memory = face->root.memory;
+    T1_Blend*  blend  = face->blend;
+
+
+    if ( blend )
+    {
+      FT_UInt  num_designs = blend->num_designs;
+      FT_UInt  num_axis    = blend->num_axis;
+      FT_UInt  n;
+
+
+      /* release design pos table */
+      FREE( blend->design_pos[0] );
+      for ( n = 1; n < num_designs; n++ )
+        blend->design_pos[n] = 0;
+
+      /* release blend `private' and `font info' dictionaries */
+      FREE( blend->privates[1] );
+      FREE( blend->font_infos[1] );
+
+      for ( n = 0; n < num_designs; n++ )
+      {
+        blend->privates  [n] = 0;
+        blend->font_infos[n] = 0;
+      }
+
+      /* release weight vectors */
+      FREE( blend->weight_vector );
+      blend->default_weight_vector = 0;
+
+      /* release axis names */
+      for ( n = 0; n < num_axis; n++ )
+        FREE( blend->axis_names[n] );
+
+      /* release design map */
+      for ( n = 0; n < num_axis; n++ )
+      {
+        T1_DesignMap*  dmap = blend->design_map + n;
+
+
+        FREE( dmap->design_points );
+        dmap->num_points = 0;
+      }
+
+      FREE( face->blend );
+    }
+  }
+
+
+  static void
+  parse_blend_axis_types( T1_Face     face,
+                          T1_Loader*  loader )
+  {
+    T1_Token   axis_tokens[ T1_MAX_MM_AXIS ];
+    FT_Int     n, num_axis;
+    FT_Error   error = 0;
+    T1_Blend*  blend;
+    FT_Memory  memory;
+
+
+    /* take an array of objects */
+    T1_ToTokenArray( &loader->parser, axis_tokens,
+                     T1_MAX_MM_AXIS, &num_axis );
+    if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
+    {
+      FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
+                 num_axis ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    /* allocate blend if necessary */
+    error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
+    if ( error )
+      goto Exit;
+
+    blend  = face->blend;
+    memory = face->root.memory;
+
+    /* each token is an immediate containing the name of the axis */
+    for ( n = 0; n < num_axis; n++ )
+    {
+      T1_Token*  token = axis_tokens + n;
+      FT_Byte*   name;
+      FT_Int     len;
+
+      /* skip first slash, if any */
+      if (token->start[0] == '/')
+        token->start++;
+
+      len = (FT_Int)( token->limit - token->start );
+      if ( len <= 0 )
+      {
+        error = T1_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      if ( ALLOC( blend->axis_names[n], len + 1 ) )
+        goto Exit;
+
+      name = (FT_Byte*)blend->axis_names[n];
+      MEM_Copy( name, token->start, len );
+      name[len] = 0;
+    }
+
+  Exit:
+    loader->parser.root.error = error;
+  }
+
+
+  static void
+  parse_blend_design_positions( T1_Face     face,
+                                T1_Loader*  loader )
+  {
+    T1_Token       design_tokens[ T1_MAX_MM_DESIGNS ];
+    FT_Int         num_designs;
+    FT_Int         num_axis;
+    T1_ParserRec*  parser = &loader->parser;
+
+    FT_Error       error = 0;
+    T1_Blend*      blend;
+
+
+    /* get the array of design tokens - compute number of designs */
+    T1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
+    if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
+    {
+      FT_ERROR(( "parse_blend_design_positions:" ));
+      FT_ERROR(( " incorrect number of designs: %d\n",
+                 num_designs ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    {
+      FT_Byte*  old_cursor = parser->root.cursor;
+      FT_Byte*  old_limit  = parser->root.limit;
+      FT_UInt   n;
+
+
+      blend    = face->blend;
+      num_axis = 0;  /* make compiler happy */
+
+      for ( n = 0; n < (FT_UInt)num_designs; n++ )
+      {
+        T1_Token   axis_tokens[ T1_MAX_MM_DESIGNS ];
+        T1_Token*  token;
+        FT_Int     axis, n_axis;
+
+
+        /* read axis/coordinates tokens */
+        token = design_tokens + n;
+        parser->root.cursor = token->start - 1;
+        parser->root.limit  = token->limit + 1;
+        T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
+
+        if ( n == 0 )
+        {
+          num_axis = n_axis;
+          error = t1_allocate_blend( face, num_designs, num_axis );
+          if ( error )
+            goto Exit;
+          blend = face->blend;
+        }
+        else if ( n_axis != num_axis )
+        {
+          FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
+          error = T1_Err_Invalid_File_Format;
+          goto Exit;
+        }
+
+        /* now, read each axis token into the design position */
+        for ( axis = 0; axis < n_axis; axis++ )
+        {
+          T1_Token*  token2 = axis_tokens + axis;
+
+
+          parser->root.cursor = token2->start;
+          parser->root.limit  = token2->limit;
+          blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
+        }
+      }
+
+      loader->parser.root.cursor = old_cursor;
+      loader->parser.root.limit  = old_limit;
+    }
+
+  Exit:
+    loader->parser.root.error = error;
+  }
+
+
+  static void
+  parse_blend_design_map( T1_Face     face,
+                          T1_Loader*  loader )
+  {
+    FT_Error       error  = 0;
+    T1_ParserRec*  parser = &loader->parser;
+    T1_Blend*      blend;
+    T1_Token       axis_tokens[ T1_MAX_MM_AXIS ];
+    FT_Int         n, num_axis;
+    FT_Byte*       old_cursor;
+    FT_Byte*       old_limit;
+    FT_Memory      memory = face->root.memory;
+
+
+    T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
+    if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
+    {
+      FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
+                 num_axis ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+    old_cursor = parser->root.cursor;
+    old_limit  = parser->root.limit;
+
+    error = t1_allocate_blend( face, 0, num_axis );
+    if ( error )
+      goto Exit;
+    blend = face->blend;
+
+    /* now, read each axis design map */
+    for ( n = 0; n < num_axis; n++ )
+    {
+      T1_DesignMap* map = blend->design_map + n;
+      T1_Token*     token;
+      FT_Int        p, num_points;
+
+
+      token = axis_tokens + n;
+      parser->root.cursor = token->start;
+      parser->root.limit  = token->limit;
+
+      /* count the number of map points */
+      {
+        FT_Byte*  ptr   = token->start;
+        FT_Byte*  limit = token->limit;
+
+
+        num_points = 0;
+        for ( ; ptr < limit; ptr++ )
+          if ( ptr[0] == '[' )
+            num_points++;
+      }
+      if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
+      {
+        FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
+        error = T1_Err_Invalid_File_Format;
+        goto Exit;
+      }
+
+      /* allocate design map data */
+      if ( ALLOC_ARRAY( map->design_points, num_points * 2, FT_Fixed ) )
+        goto Exit;
+      map->blend_points = map->design_points + num_points;
+      map->num_points   = (FT_Byte)num_points;
+
+      for ( p = 0; p < num_points; p++ )
+      {
+        map->design_points[p] = T1_ToInt( parser );
+        map->blend_points [p] = T1_ToFixed( parser, 0 );
+      }
+    }
+
+    parser->root.cursor = old_cursor;
+    parser->root.limit  = old_limit;
+
+  Exit:
+    parser->root.error = error;
+  }
+
+
+  static void
+  parse_weight_vector( T1_Face     face,
+                       T1_Loader*  loader )
+  {
+    FT_Error       error  = 0;
+    T1_ParserRec*  parser = &loader->parser;
+    T1_Blend*      blend  = face->blend;
+    T1_Token       master;
+    FT_UInt        n;
+    FT_Byte*       old_cursor;
+    FT_Byte*       old_limit;
+
+
+    if ( !blend || blend->num_designs == 0 )
+    {
+      FT_ERROR(( "parse_weight_vector: too early!\n" ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    T1_ToToken( parser, &master );
+    if ( master.type != t1_token_array )
+    {
+      FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
+      error = T1_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    old_cursor = parser->root.cursor;
+    old_limit  = parser->root.limit;
+
+    parser->root.cursor = master.start;
+    parser->root.limit  = master.limit;
+
+    for ( n = 0; n < blend->num_designs; n++ )
+    {
+      blend->default_weight_vector[n] =
+      blend->weight_vector[n]         = T1_ToFixed( parser, 0 );
+    }
+
+    parser->root.cursor = old_cursor;
+    parser->root.limit  = old_limit;
+
+  Exit:
+    parser->root.error = error;
+  }
+
+
+  /* the keyword `/shareddict' appears in some multiple master fonts   */
+  /* with a lot of Postscript garbage behind it (that's completely out */
+  /* of spec!); we detect it and terminate the parsing                 */
+  /*                                                                   */
+  static void
+  parse_shared_dict( T1_Face     face,
+                     T1_Loader*  loader )
+  {
+    T1_ParserRec*  parser = &loader->parser;
+
+    FT_UNUSED( face );
+
+
+    parser->root.cursor = parser->root.limit;
+    parser->root.error  = 0;
+  }
+
+#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      TYPE 1 SYMBOL PARSING                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* First of all, define the token field static variables.  This is a set */
+  /* of T1_Field variables used later.                                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  static FT_Error
+  t1_load_keyword( T1_Face     face,
+                   T1_Loader*  loader,
+                   T1_Field*   field )
+  {
+    FT_Error   error;
+    void*      dummy_object;
+    void**     objects;
+    FT_UInt    max_objects;
+    T1_Blend*  blend = face->blend;
+
+
+    /* if the keyword has a dedicated callback, call it */
+    if ( field->type == t1_field_callback )
+    {
+      field->reader( (FT_Face)face, loader );
+      error = loader->parser.root.error;
+      goto Exit;
+    }
+
+    /* now, the keyword is either a simple field, or a table of fields; */
+    /* we are now going to take care of it                              */
+    switch ( field->location )
+    {
+    case t1_field_font_info:
+      dummy_object = &face->type1.font_info;
+      objects      = &dummy_object;
+      max_objects  = 0;
+
+      if ( blend )
+      {
+        objects     = (void**)blend->font_infos;
+        max_objects = blend->num_designs;
+      }
+      break;
+
+    case t1_field_private:
+      dummy_object = &face->type1.private_dict;
+      objects      = &dummy_object;
+      max_objects  = 0;
+
+      if ( blend )
+      {
+        objects     = (void**)blend->privates;
+        max_objects = blend->num_designs;
+      }
+      break;
+
+    default:
+      dummy_object = &face->type1;
+      objects      = &dummy_object;
+      max_objects  = 0;
+    }
+
+    if ( field->type == t1_field_integer_array ||
+         field->type == t1_field_fixed_array   )
+      error = T1_Load_Field_Table( &loader->parser, field,
+                                   objects, max_objects, 0 );
+    else
+      error = T1_Load_Field( &loader->parser, field,
+                             objects, max_objects, 0 );
+
+  Exit:
+    return error;
+  }
+
+
+  static int
+  is_space( FT_Byte  c )
+  {
+    return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+  }
+
+
+  static int
+  is_alpha( FT_Byte  c )
+  {
+    /* Note: we must accept "+" as a valid character, as it is used in */
+    /*       embedded type1 fonts in PDF documents.                    */
+    /*                                                                 */
+    return ( isalnum( c ) || c == '.' || c == '_' || c == '-' || c == '+' );
+  }
+
+
+  static int
+  read_binary_data( T1_ParserRec*  parser,
+                    FT_Int*        size,
+                    FT_Byte**      base )
+  {
+    FT_Byte*  cur;
+    FT_Byte*  limit = parser->root.limit;
+
+
+    /* the binary data has the following format */
+    /*                                          */
+    /* `size' [white*] RD white ....... ND      */
+    /*                                          */
+
+    T1_Skip_Spaces( parser );
+    cur = parser->root.cursor;
+
+    if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
+    {
+      *size = T1_ToInt( parser );
+
+      T1_Skip_Spaces( parser );
+      T1_Skip_Alpha ( parser );  /* `RD' or `-|' or something else */
+
+      /* there is only one whitespace char after the */
+      /* `RD' or `-|' token                          */
+      *base = parser->root.cursor + 1;
+
+      parser->root.cursor += *size + 1;
+      return 1;
+    }
+
+    FT_ERROR(( "read_binary_data: invalid size field\n" ));
+    parser->root.error = T1_Err_Invalid_File_Format;
+    return 0;
+  }
+
+
+  /* we will now define the routines used to handle */
+  /* the `/Encoding', `/Subrs', and `/CharStrings'  */
+  /* dictionaries                                   */
+
+  static void
+  parse_font_name( T1_Face     face,
+                   T1_Loader*  loader )
+  {
+    T1_ParserRec*  parser = &loader->parser;
+    FT_Error       error;
+    FT_Memory      memory = parser->root.memory;
+    FT_Int         len;
+    FT_Byte*       cur;
+    FT_Byte*       cur2;
+    FT_Byte*       limit;
+
+
+    T1_Skip_Spaces( parser );
+
+    cur   = parser->root.cursor;
+    limit = parser->root.limit;
+
+    if ( cur >= limit - 1 || *cur != '/' )
+      return;
+
+    cur++;
+    cur2 = cur;
+    while ( cur2 < limit && is_alpha( *cur2 ) )
+      cur2++;
+
+    len = (FT_Int)( cur2 - cur );
+    if ( len > 0 )
+    {
+      if ( ALLOC( face->type1.font_name, len + 1 ) )
+      {
+        parser->root.error = error;
+        return;
+      }
+
+      MEM_Copy( face->type1.font_name, cur, len );
+      face->type1.font_name[len] = '\0';
+    }
+    parser->root.cursor = cur2;
+  }
+
+
+  static void
+  parse_font_bbox( T1_Face     face,
+                   T1_Loader*  loader )
+  {
+    T1_ParserRec*  parser = &loader->parser;
+    FT_Fixed       temp[4];
+    FT_BBox*       bbox   = &face->type1.font_bbox;
+
+
+    (void)T1_ToFixedArray( parser, 4, temp, 0 );
+    bbox->xMin = FT_RoundFix( temp[0] );
+    bbox->yMin = FT_RoundFix( temp[1] );
+    bbox->xMax = FT_RoundFix( temp[2] );
+    bbox->yMax = FT_RoundFix( temp[3] );
+  }
+
+
+  static void
+  parse_font_matrix( T1_Face     face,
+                     T1_Loader*  loader )
+  {
+    T1_ParserRec*  parser = &loader->parser;
+    FT_Matrix*     matrix = &face->type1.font_matrix;
+    FT_Vector*     offset = &face->type1.font_offset;
+    FT_Face        root   = (FT_Face)&face->root;
+    FT_Fixed       temp[6];
+    FT_Fixed       temp_scale;
+
+
+    if ( matrix->xx || matrix->yx )
+      /*  with synthetic fonts, it's possible we get here twice  */
+      return;
+
+    (void)T1_ToFixedArray( parser, 6, temp, 3 );
+
+    temp_scale = ABS( temp[3] );
+
+    /* Set Units per EM based on FontMatrix values.  We set the value to */
+    /* 1000 / temp_scale, because temp_scale was already multiplied by   */
+    /* 1000 (in t1_tofixed, from psobjs.c).                              */
+
+    root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
+                                                 temp_scale ) >> 16 );
+
+    /* we need to scale the values by 1.0/temp_scale */
+    if ( temp_scale != 0x10000L )
+    {
+      temp[0] = FT_DivFix( temp[0], temp_scale );
+      temp[1] = FT_DivFix( temp[1], temp_scale );
+      temp[2] = FT_DivFix( temp[2], temp_scale );
+      temp[4] = FT_DivFix( temp[4], temp_scale );
+      temp[5] = FT_DivFix( temp[5], temp_scale );
+      temp[3] = 0x10000L;
+    }
+
+    matrix->xx = temp[0];
+    matrix->yx = temp[1];
+    matrix->xy = temp[2];
+    matrix->yy = temp[3];
+
+    /* note that the offsets must be expressed in integer font units */
+    offset->x  = temp[4] >> 16;
+    offset->y  = temp[5] >> 16;
+  }
+
+
+  static void
+  parse_encoding( T1_Face     face,
+                  T1_Loader*  loader )
+  {
+    T1_ParserRec*  parser = &loader->parser;
+    FT_Byte*       cur    = parser->root.cursor;
+    FT_Byte*       limit  = parser->root.limit;
+
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+
+    /* skip whitespace */
+    while ( is_space( *cur ) )
+    {
+      cur++;
+      if ( cur >= limit )
+      {
+        FT_ERROR(( "parse_encoding: out of bounds!\n" ));
+        parser->root.error = T1_Err_Invalid_File_Format;
+        return;
+      }
+    }
+
+    /* if we have a number, then the encoding is an array, */
+    /* and we must load it now                             */
+    if ( (FT_Byte)( *cur - '0' ) < 10 )
+    {
+      T1_Encoding*  encode     = &face->type1.encoding;
+      FT_Int        count, n;
+      PS_Table*     char_table = &loader->encoding_table;
+      FT_Memory     memory     = parser->root.memory;
+      FT_Error      error;
+
+
+      /* read the number of entries in the encoding, should be 256 */
+      count = T1_ToInt( parser );
+      if ( parser->root.error )
+        return;
+
+      /* we use a T1_Table to store our charnames */
+      encode->num_chars = count;
+      if ( ALLOC_ARRAY( encode->char_index, count, FT_Short   ) ||
+           ALLOC_ARRAY( encode->char_name,  count, FT_String* ) ||
+           ( error = psaux->ps_table_funcs->init(
+                       char_table, count, memory ) ) != 0       )
+      {
+        parser->root.error = error;
+        return;
+      }
+
+      /* We need to `zero' out encoding_table.elements          */
+      for ( n = 0; n < count; n++ )
+      {
+        char*  notdef = (char *)".notdef";
+
+
+        T1_Add_Table( char_table, n, notdef, 8 );
+      }
+
+      /* Now, we will need to read a record of the form         */
+      /* ... charcode /charname ... for each entry in our table */
+      /*                                                        */
+      /* We simply look for a number followed by an immediate   */
+      /* name.  Note that this ignores correctly the sequence   */
+      /* that is often seen in type1 fonts:                     */
+      /*                                                        */
+      /*   0 1 255 { 1 index exch /.notdef put } for dup        */
+      /*                                                        */
+      /* used to clean the encoding array before anything else. */
+      /*                                                        */
+      /* We stop when we encounter a `def'.                     */
+
+      cur   = parser->root.cursor;
+      limit = parser->root.limit;
+      n     = 0;
+
+      for ( ; cur < limit; )
+      {
+        FT_Byte  c;
+
+
+        c = *cur;
+
+        /* we stop when we encounter a `def' */
+        if ( c == 'd' && cur + 3 < limit )
+        {
+          if ( cur[1] == 'e' &&
+               cur[2] == 'f' &&
+               is_space(cur[-1]) &&
+               is_space(cur[3]) )
+          {
+            FT_TRACE6(( "encoding end\n" ));
+            break;
+          }
+        }
+
+        /* otherwise, we must find a number before anything else */
+        if ( (FT_Byte)( c - '0' ) < 10 )
+        {
+          FT_Int  charcode;
+
+
+          parser->root.cursor = cur;
+          charcode = T1_ToInt( parser );
+          cur = parser->root.cursor;
+
+          /* skip whitespace */
+          while ( cur < limit && is_space( *cur ) )
+            cur++;
+
+          if ( cur < limit && *cur == '/' )
+          {
+            /* bingo, we have an immediate name -- it must be a */
+            /* character name                                   */
+            FT_Byte*  cur2 = cur + 1;
+            FT_Int    len;
+
+
+            while ( cur2 < limit && is_alpha( *cur2 ) )
+              cur2++;
+
+            len = (FT_Int)( cur2 - cur - 1 );
+
+            parser->root.error = T1_Add_Table( char_table, charcode,
+                                               cur + 1, len + 1 );
+            char_table->elements[charcode][len] = '\0';
+            if ( parser->root.error )
+              return;
+
+            cur = cur2;
+          }
+        }
+        else
+          cur++;
+      }
+
+      face->type1.encoding_type = t1_encoding_array;
+      parser->root.cursor       = cur;
+    }
+    /* Otherwise, we should have either `StandardEncoding' or */
+    /* `ExpertEncoding'                                       */
+    else
+    {
+      if ( cur + 17 < limit &&
+           strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
+        face->type1.encoding_type = t1_encoding_standard;
+
+      else if ( cur + 15 < limit &&
+                strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
+        face->type1.encoding_type = t1_encoding_expert;
+
+      else
+      {
+        FT_ERROR(( "parse_encoding: invalid token!\n" ));
+        parser->root.error = T1_Err_Invalid_File_Format;
+      }
+    }
+  }
+
+
+  static void
+  parse_subrs( T1_Face     face,
+               T1_Loader*  loader )
+  {
+    T1_ParserRec*  parser = &loader->parser;
+    PS_Table*      table  = &loader->subrs;
+    FT_Memory      memory = parser->root.memory;
+    FT_Error       error;
+    FT_Int         n;
+
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+
+    loader->num_subrs = T1_ToInt( parser );
+    if ( parser->root.error )
+      return;
+
+    /* position the parser right before the `dup' of the first subr */
+    T1_Skip_Spaces( parser );
+    T1_Skip_Alpha( parser );      /* `array' */
+    T1_Skip_Spaces( parser );
+
+    /* initialize subrs array */
+    error = psaux->ps_table_funcs->init( table, loader->num_subrs, memory );
+    if ( error )
+      goto Fail;
+
+    /* the format is simple:                                 */
+    /*                                                       */
+    /*   `index' + binary data                               */
+    /*                                                       */
+
+    for ( n = 0; n < loader->num_subrs; n++ )
+    {
+      FT_Int    index, size;
+      FT_Byte*  base;
+
+
+      /* If the next token isn't `dup', we are also done.  This */
+      /* happens when there are `holes' in the Subrs array.     */
+      if ( strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
+        break;
+
+      index = T1_ToInt( parser );
+
+      if ( !read_binary_data( parser, &size, &base ) )
+        return;
+
+      /* The binary string is followed by one token, e.g. `NP' */
+      /* (bound to `noaccess put') or by two separate tokens:  */
+      /* `noaccess' & `put'.  We position the parser right     */
+      /* before the next `dup', if any.                        */
+      T1_Skip_Spaces( parser );
+      T1_Skip_Alpha( parser );    /* `NP' or `I' or `noaccess' */
+      T1_Skip_Spaces( parser );
+
+      if ( strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
+      {
+        T1_Skip_Alpha( parser );  /* skip `put' */
+        T1_Skip_Spaces( parser );
+      }
+
+      /* some fonts use a value of -1 for lenIV to indicate that */
+      /* the charstrings are unencoded                           */
+      /*                                                         */
+      /* thanks to Tom Kacvinsky for pointing this out           */
+      /*                                                         */
+      if ( face->type1.private_dict.lenIV >= 0 )
+      {
+        psaux->t1_decrypt( base, size, 4330 );
+        size -= face->type1.private_dict.lenIV;
+        base += face->type1.private_dict.lenIV;
+      }
+
+      error = T1_Add_Table( table, index, base, size );
+      if ( error )
+        goto Fail;
+    }
+    return;
+
+  Fail:
+    parser->root.error = error;
+  }
+
+
+  static void
+  parse_charstrings( T1_Face     face,
+                     T1_Loader*  loader )
+  {
+    T1_ParserRec*  parser     = &loader->parser;
+    PS_Table*      code_table = &loader->charstrings;
+    PS_Table*      name_table = &loader->glyph_names;
+    PS_Table*      swap_table = &loader->swap_table;
+    FT_Memory      memory     = parser->root.memory;
+    FT_Error       error;
+
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+    FT_Byte*    cur;
+    FT_Byte*    limit = parser->root.limit;
+    FT_Int      n;
+    FT_UInt     notdef_index = 0;
+    FT_Byte     notdef_found = 0;
+
+
+    if ( loader->num_glyphs )
+      /*  with synthetic fonts, it's possible we get here twice  */
+      return;
+
+    loader->num_glyphs = T1_ToInt( parser );
+    if ( parser->root.error )
+      return;
+
+    /* initialize tables (leaving room for addition of .notdef, */
+    /* if necessary).                                           */
+
+    error = psaux->ps_table_funcs->init( code_table,
+                                         loader->num_glyphs + 1,
+                                         memory );
+    if ( error )
+      goto Fail;
+
+    error = psaux->ps_table_funcs->init( name_table,
+                                         loader->num_glyphs + 1,
+                                         memory );
+    if ( error )
+      goto Fail;
+
+    /* Initialize table for swapping index notdef_index and */
+    /* index 0 names and codes (if necessary).              */
+
+    error = psaux->ps_table_funcs->init( swap_table, 4, memory );
+
+    if ( error )
+      goto Fail;
+
+
+    n = 0;
+    for (;;)
+    {
+      FT_Int    size;
+      FT_Byte*  base;
+
+
+      /* the format is simple:                    */
+      /*   `/glyphname' + binary data             */
+      /*                                          */
+      /* note that we stop when we find a `def'   */
+      /*                                          */
+      T1_Skip_Spaces( parser );
+
+      cur = parser->root.cursor;
+      if ( cur >= limit )
+        break;
+
+      /* we stop when we find a `def' or `end' keyword */
+      if ( *cur   == 'd'   &&
+           cur + 3 < limit &&
+           cur[1] == 'e'   &&
+           cur[2] == 'f'   )
+        break;
+
+      if ( *cur   == 'e'   &&
+           cur + 3 < limit &&
+           cur[1] == 'n'   &&
+           cur[2] == 'd'   )
+        break;
+
+      if ( *cur != '/' )
+        T1_Skip_Alpha( parser );
+      else
+      {
+        FT_Byte*  cur2 = cur + 1;
+        FT_Int    len;
+
+
+        while ( cur2 < limit && is_alpha( *cur2 ) )
+          cur2++;
+        len = (FT_Int)( cur2 - cur - 1 );
+
+        error = T1_Add_Table( name_table, n, cur + 1, len + 1 );
+        if ( error )
+          goto Fail;
+
+        /* add a trailing zero to the name table */
+        name_table->elements[n][len] = '\0';
+
+        /* record index of /.notdef              */
+        if ( strcmp( (const char*)".notdef",
+                     (const char*)(name_table->elements[n]) ) == 0 )
+        {
+          notdef_index = n;
+          notdef_found = 1;
+        }
+
+        parser->root.cursor = cur2;
+        if ( !read_binary_data( parser, &size, &base ) )
+          return;
+
+        if ( face->type1.private_dict.lenIV >= 0 )
+        {
+          psaux->t1_decrypt( base, size, 4330 );
+          size -= face->type1.private_dict.lenIV;
+          base += face->type1.private_dict.lenIV;
+        }
+
+        error = T1_Add_Table( code_table, n, base, size );
+        if ( error )
+          goto Fail;
+
+        n++;
+        if ( n >= loader->num_glyphs )
+          break;
+      }
+    }
+
+    loader->num_glyphs = n;
+
+    /* if /.notdef is found but does not occupy index 0, do our magic.      */
+    if ( strcmp( (const char*)".notdef",
+                 (const char*)name_table->elements[0] ) &&
+         notdef_found                                      )
+    {
+      /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0    */
+      /* name and code entries to swap_table. Then place notdef_index name */
+      /* and code entries into swap_table.  Then swap name and code        */
+      /* entries at indices notdef_index and 0 using values stored in      */
+      /* swap_table.                                                       */
+
+      /* Index 0 name */
+      error = T1_Add_Table( swap_table, 0,
+                            name_table->elements[0],
+                            name_table->lengths [0] );
+      if ( error )
+        goto Fail;
+
+      /* Index 0 code */
+      error = T1_Add_Table( swap_table, 1,
+                            code_table->elements[0],
+                            code_table->lengths [0] );
+      if ( error )
+        goto Fail;
+
+      /* Index notdef_index name */
+      error = T1_Add_Table( swap_table, 2,
+                            name_table->elements[notdef_index],
+                            name_table->lengths [notdef_index] );
+      if ( error )
+        goto Fail;
+
+      /* Index notdef_index code */
+      error = T1_Add_Table( swap_table, 3,
+                            code_table->elements[notdef_index],
+                            code_table->lengths [notdef_index] );
+      if ( error )
+        goto Fail;
+
+      error = T1_Add_Table( name_table, notdef_index,
+                            swap_table->elements[0],
+                            swap_table->lengths [0] );
+      if ( error )
+        goto Fail;
+
+      error = T1_Add_Table( code_table, notdef_index,
+                            swap_table->elements[1],
+                            swap_table->lengths [1] );
+      if ( error )
+        goto Fail;
+
+      error = T1_Add_Table( name_table, 0,
+                            swap_table->elements[2],
+                            swap_table->lengths [2] );
+      if ( error )
+        goto Fail;
+
+      error = T1_Add_Table( code_table, 0,
+                            swap_table->elements[3],
+                            swap_table->lengths [3] );
+      if ( error )
+        goto Fail;
+
+    }
+    else if ( !notdef_found )
+    {
+
+      /* notdef_index is already 0, or /.notdef is undefined in  */
+      /* charstrings dictionary. Worry about /.notdef undefined. */
+      /* We take index 0 and add it to the end of the table(s)   */
+      /* and add our own /.notdef glyph to index 0.              */
+
+      /* 0 333 hsbw endchar                                      */
+      FT_Byte  notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E};
+      char*    notdef_name    = (char *)".notdef";
+
+
+      error = T1_Add_Table( swap_table, 0,
+                            name_table->elements[0],
+                            name_table->lengths [0] );
+      if ( error )
+        goto Fail;
+
+      error = T1_Add_Table( swap_table, 1,
+                            code_table->elements[0],
+                            code_table->lengths [0] );
+      if ( error )
+        goto Fail;
+
+      error = T1_Add_Table( name_table, 0, notdef_name, 8 );
+      if ( error )
+        goto Fail;
+
+      error = T1_Add_Table( code_table, 0, notdef_glyph, 5 );
+
+      if ( error )
+        goto Fail;
+
+      error = T1_Add_Table( name_table, n,
+                            swap_table->elements[0],
+                            swap_table->lengths [0] );
+      if ( error )
+        goto Fail;
+
+      error = T1_Add_Table( code_table, n,
+                            swap_table->elements[1],
+                            swap_table->lengths [1] );
+      if ( error )
+        goto Fail;
+
+      /* we added a glyph. */
+      loader->num_glyphs = n + 1;
+
+    }
+
+
+    return;
+
+  Fail:
+    parser->root.error = error;
+  }
+
+
+  static
+  const T1_Field  t1_keywords[] =
+  {
+
+#include "t1tokens.h"
+
+    /* now add the special functions... */
+    T1_FIELD_CALLBACK( "FontName", parse_font_name )
+    T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
+    T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
+    T1_FIELD_CALLBACK( "Encoding", parse_encoding )
+    T1_FIELD_CALLBACK( "Subrs", parse_subrs )
+    T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+    T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions )
+    T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map )
+    T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types )
+    T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector )
+    T1_FIELD_CALLBACK( "shareddict", parse_shared_dict )
+#endif
+
+    { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
+  };
+
+
+  static FT_Error
+  parse_dict( T1_Face     face,
+              T1_Loader*  loader,
+              FT_Byte*    base,
+              FT_Long     size )
+  {
+    T1_ParserRec*  parser = &loader->parser;
+
+
+    parser->root.cursor = base;
+    parser->root.limit  = base + size;
+    parser->root.error  = 0;
+
+    {
+      FT_Byte*  cur   = base;
+      FT_Byte*  limit = cur + size;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        /* look for `FontDirectory', which causes problems on some fonts */
+        if ( *cur == 'F' && cur + 25 < limit                 &&
+             strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
+        {
+          FT_Byte*  cur2;
+
+
+          /* skip the `FontDirectory' keyword */
+          cur += 13;
+          cur2 = cur;
+
+          /* lookup the `known' keyword */
+          while ( cur < limit && *cur != 'k'        &&
+                  strncmp( (char*)cur, "known", 5 ) )
+            cur++;
+
+          if ( cur < limit )
+          {
+            T1_Token  token;
+
+
+            /* skip the `known' keyword and the token following it */
+            cur += 5;
+            loader->parser.root.cursor = cur;
+            T1_ToToken( &loader->parser, &token );
+
+            /* if the last token was an array, skip it! */
+            if ( token.type == t1_token_array )
+              cur2 = parser->root.cursor;
+          }
+          cur = cur2;
+        }
+        /* look for immediates */
+        else if ( *cur == '/' && cur + 2 < limit )
+        {
+          FT_Byte*  cur2;
+          FT_Int    len;
+
+
+          cur++;
+          cur2 = cur;
+          while ( cur2 < limit && is_alpha( *cur2 ) )
+            cur2++;
+
+          len  = (FT_Int)( cur2 - cur );
+          if ( len > 0 && len < 22 )
+          {
+            {
+              /* now, compare the immediate name to the keyword table */
+              T1_Field*  keyword = (T1_Field*)t1_keywords;
+
+
+              for (;;)
+              {
+                FT_Byte*  name;
+
+
+                name = (FT_Byte*)keyword->ident;
+                if ( !name )
+                  break;
+
+                if ( cur[0] == name[0]                          &&
+                     len == (FT_Int)strlen( (const char*)name ) )
+                {
+                  FT_Int  n;
+
+
+                  for ( n = 1; n < len; n++ )
+                    if ( cur[n] != name[n] )
+                      break;
+
+                  if ( n >= len )
+                  {
+                    /* we found it -- run the parsing callback! */
+                    parser->root.cursor = cur2;
+                    T1_Skip_Spaces( parser );
+                    parser->root.error = t1_load_keyword( face,
+                                                          loader,
+                                                          keyword );
+                    if ( parser->root.error )
+                      return parser->root.error;
+
+                    cur = parser->root.cursor;
+                    break;
+                  }
+                }
+                keyword++;
+              }
+            }
+          }
+        }
+      }
+    }
+    return parser->root.error;
+  }
+
+
+  static void
+  t1_init_loader( T1_Loader*  loader,
+                  T1_Face     face )
+  {
+    FT_UNUSED( face );
+
+    MEM_Set( loader, 0, sizeof ( *loader ) );
+    loader->num_glyphs = 0;
+    loader->num_chars  = 0;
+
+    /* initialize the tables -- simply set their `init' field to 0 */
+    loader->encoding_table.init = 0;
+    loader->charstrings.init    = 0;
+    loader->glyph_names.init    = 0;
+    loader->subrs.init          = 0;
+    loader->swap_table.init     = 0;
+    loader->fontdata            = 0;
+  }
+
+
+  static void
+  t1_done_loader( T1_Loader*  loader )
+  {
+    T1_ParserRec*  parser = &loader->parser;
+
+
+    /* finalize tables */
+    T1_Release_Table( &loader->encoding_table );
+    T1_Release_Table( &loader->charstrings );
+    T1_Release_Table( &loader->glyph_names );
+    T1_Release_Table( &loader->swap_table );
+    T1_Release_Table( &loader->subrs );
+
+    /* finalize parser */
+    T1_Finalize_Parser( parser );
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_Open_Face( T1_Face  face )
+  {
+    T1_Loader      loader;
+    T1_ParserRec*  parser;
+    T1_Font*       type1 = &face->type1;
+    FT_Error       error;
+
+    PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
+
+
+    t1_init_loader( &loader, face );
+
+    /* default lenIV */
+    type1->private_dict.lenIV = 4;
+
+    parser = &loader.parser;
+    error = T1_New_Parser( parser,
+                           face->root.stream,
+                           face->root.memory,
+                           psaux );
+    if ( error )
+      goto Exit;
+
+    error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
+    if ( error )
+      goto Exit;
+
+    error = T1_Get_Private_Dict( parser, psaux );
+    if ( error )
+      goto Exit;
+
+    error = parse_dict( face, &loader, parser->private_dict,
+                        parser->private_len );
+    if ( error )
+      goto Exit;
+
+    /* now, propagate the subrs, charstrings, and glyphnames tables */
+    /* to the Type1 data                                            */
+    type1->num_glyphs = loader.num_glyphs;
+
+    if ( loader.subrs.init )
+    {
+      loader.subrs.init  = 0;
+      type1->num_subrs   = loader.num_subrs;
+      type1->subrs_block = loader.subrs.block;
+      type1->subrs       = loader.subrs.elements;
+      type1->subrs_len   = loader.subrs.lengths;
+    }
+
+    if ( !loader.charstrings.init )
+    {
+      FT_ERROR(( "T1_Open_Face: no charstrings array in face!\n" ));
+      error = T1_Err_Invalid_File_Format;
+    }
+
+    loader.charstrings.init  = 0;
+    type1->charstrings_block = loader.charstrings.block;
+    type1->charstrings       = loader.charstrings.elements;
+    type1->charstrings_len   = loader.charstrings.lengths;
+
+    /* we copy the glyph names `block' and `elements' fields; */
+    /* the `lengths' field must be released later             */
+    type1->glyph_names_block    = loader.glyph_names.block;
+    type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
+    loader.glyph_names.block    = 0;
+    loader.glyph_names.elements = 0;
+
+    /* we must now build type1.encoding when we have a custom */
+    /* array..                                                */
+    if ( type1->encoding_type == t1_encoding_array )
+    {
+      FT_Int    charcode, index, min_char, max_char;
+      FT_Byte*  char_name;
+      FT_Byte*  glyph_name;
+
+
+      /* OK, we do the following: for each element in the encoding  */
+      /* table, look up the index of the glyph having the same name */
+      /* the index is then stored in type1.encoding.char_index, and */
+      /* a the name to type1.encoding.char_name                     */
+
+      min_char = +32000;
+      max_char = -32000;
+
+      charcode = 0;
+      for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
+      {
+        type1->encoding.char_index[charcode] = 0;
+        type1->encoding.char_name [charcode] = (char *)".notdef";
+
+        char_name = loader.encoding_table.elements[charcode];
+        if ( char_name )
+          for ( index = 0; index < type1->num_glyphs; index++ )
+          {
+            glyph_name = (FT_Byte*)type1->glyph_names[index];
+            if ( strcmp( (const char*)char_name,
+                         (const char*)glyph_name ) == 0 )
+            {
+              type1->encoding.char_index[charcode] = (FT_UShort)index;
+              type1->encoding.char_name [charcode] = (char*)glyph_name;
+
+              /* Change min/max encoded char only if glyph name is */
+              /* not /.notdef                                      */
+              if ( strcmp( (const char*)".notdef",
+                           (const char*)glyph_name ) != 0 )
+              {
+                if (charcode < min_char) min_char = charcode;
+                if (charcode > max_char) max_char = charcode;
+              }
+              break;
+            }
+          }
+      }
+      type1->encoding.code_first = min_char;
+      type1->encoding.code_last  = max_char;
+      type1->encoding.num_chars  = loader.num_chars;
+   }
+
+  Exit:
+    t1_done_loader( &loader );
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/t1objs.c b/libraries/freetype-2.0.5/t1objs.c
new file mode 100644 (file)
index 0000000..9eaadcc
--- /dev/null
@@ -0,0 +1,416 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1objs.c                                                               */
+/*                                                                         */
+/*    Type 1 objects manager (body).                                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+
+#include <string.h>         /* strcmp() */
+
+#include "t1gload.h"
+#include "t1load.h"
+
+#include "t1errors.h"
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "t1afm.h"
+#endif
+
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1objs
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                            FACE  FUNCTIONS                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The face object destructor.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A typeless pointer to the face object to destroy.          */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  T1_Done_Face( T1_Face  face )
+  {
+    FT_Memory  memory;
+    T1_Font*   type1 = &face->type1;
+
+
+    if ( face )
+    {
+      memory = face->root.memory;
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+      /* release multiple masters information */
+      T1_Done_Blend( face );
+      face->blend = 0;
+#endif
+
+      /* release font info strings */
+      {
+        T1_FontInfo*  info = &type1->font_info;
+
+
+        FREE( info->version );
+        FREE( info->notice );
+        FREE( info->full_name );
+        FREE( info->family_name );
+        FREE( info->weight );
+      }
+
+      /* release top dictionary */
+      FREE( type1->charstrings_len );
+      FREE( type1->charstrings );
+      FREE( type1->glyph_names );
+
+      FREE( type1->subrs );
+      FREE( type1->subrs_len );
+
+      FREE( type1->subrs_block );
+      FREE( type1->charstrings_block );
+      FREE( type1->glyph_names_block );
+
+      FREE( type1->encoding.char_index );
+      FREE( type1->encoding.char_name );
+      FREE( type1->font_name );
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+      /* release afm data if present */
+      if ( face->afm_data )
+        T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
+#endif
+
+      /* release unicode map, if any */
+      FREE( face->unicode_map.maps );
+      face->unicode_map.num_maps = 0;
+
+      face->root.family_name = 0;
+      face->root.style_name  = 0;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Init_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The face object constructor.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     ::  input stream where to load font data.               */
+  /*                                                                       */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*                                                                       */
+  /*    num_params :: Number of additional generic parameters.  Ignored.   */
+  /*                                                                       */
+  /*    params     :: Additional generic parameters.  Ignored.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The face record to build.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  T1_Init_Face( FT_Stream      stream,
+                T1_Face        face,
+                FT_Int         face_index,
+                FT_Int         num_params,
+                FT_Parameter*  params )
+  {
+    FT_Error            error;
+    PSNames_Interface*  psnames;
+    PSAux_Interface*    psaux;
+
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+    FT_UNUSED( face_index );
+    FT_UNUSED( stream );
+
+
+    face->root.num_faces = 1;
+
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( !psnames )
+    {
+      psnames = (PSNames_Interface*)
+                FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" );
+
+      face->psnames = psnames;
+    }
+
+    psaux = (PSAux_Interface*)face->psaux;
+    if ( !psaux )
+    {
+      psaux = (PSAux_Interface*)
+              FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" );
+
+      face->psaux = psaux;
+    }
+
+    /* open the tokenizer, this will also check the font format */
+    error = T1_Open_Face( face );
+    if ( error )
+      goto Exit;
+
+    /* if we just wanted to check the format, leave successfully now */
+    if ( face_index < 0 )
+      goto Exit;
+
+    /* check the face index */
+    if ( face_index != 0 )
+    {
+      FT_ERROR(( "T1_Init_Face: invalid face index\n" ));
+      error = T1_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    /* Now, load the font program into the face object */
+
+    /* Init the face object fields */
+    /* Now set up root face fields */
+    {
+      FT_Face  root = (FT_Face)&face->root;
+
+
+      root->num_glyphs   = face->type1.num_glyphs;
+      root->num_charmaps = 1;
+
+      root->face_index = face_index;
+      root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+      root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+      root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
+
+      if ( face->type1.font_info.is_fixed_pitch )
+        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+      if ( face->blend )
+        root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+
+      /* XXX: TODO -- add kerning with .afm support */
+
+      /* get style name -- be careful, some broken fonts only */
+      /* have a `/FontName' dictionary entry!                 */
+      root->family_name = face->type1.font_info.family_name;
+      if ( root->family_name )
+      {
+        char*  full   = face->type1.font_info.full_name;
+        char*  family = root->family_name;
+
+
+        while ( *family && *full == *family )
+        {
+          family++;
+          full++;
+        }
+
+        root->style_name = ( *full == ' ' ? full + 1
+                                          : (char *)"Regular" );
+      }
+      else
+      {
+        /* do we have a `/FontName'? */
+        if ( face->type1.font_name )
+        {
+          root->family_name = face->type1.font_name;
+          root->style_name  = (char *)"Regular";
+        }
+      }
+
+      /* compute style flags */
+      root->style_flags = 0;
+      if ( face->type1.font_info.italic_angle )
+        root->style_flags |= FT_STYLE_FLAG_ITALIC;
+      if ( face->type1.font_info.weight )
+      {
+        if ( !strcmp( face->type1.font_info.weight, "Bold"  ) ||
+             !strcmp( face->type1.font_info.weight, "Black" ) )
+          root->style_flags |= FT_STYLE_FLAG_BOLD;
+      }
+
+      /* no embedded bitmap support */
+      root->num_fixed_sizes = 0;
+      root->available_sizes = 0;
+
+      root->bbox = face->type1.font_bbox;
+
+      /* Set units_per_EM if we didn't set it in parse_font_matrix. */
+      if ( !root->units_per_EM )
+        root->units_per_EM = 1000;
+
+      root->ascender  = (FT_Short)( face->type1.font_bbox.yMax >> 16 );
+      root->descender = (FT_Short)( face->type1.font_bbox.yMin >> 16 );
+      root->height    = (FT_Short)(
+                          ( ( root->ascender - root->descender ) * 12 ) / 10 );
+
+      /* now compute the maximum advance width */
+      root->max_advance_width =
+        (FT_Short)( face->type1.font_bbox.xMax >> 16 );
+      {
+        FT_Int  max_advance;
+
+
+        error = T1_Compute_Max_Advance( face, &max_advance );
+
+        /* in case of error, keep the standard width */
+        if ( !error )
+          root->max_advance_width = (FT_Short)max_advance;
+        else
+          error = 0;   /* clear error */
+      }
+
+      root->max_advance_height = root->height;
+
+      root->underline_position  = face->type1.font_info.underline_position;
+      root->underline_thickness = face->type1.font_info.underline_thickness;
+
+      root->internal->max_points   = 0;
+      root->internal->max_contours = 0;
+    }
+
+    /* charmap support -- synthetize unicode charmap if possible */
+    {
+      FT_Face     root    = &face->root;
+      FT_CharMap  charmap = face->charmaprecs;
+
+
+      /* synthesize a Unicode charmap if there is support in the `PSNames' */
+      /* module                                                            */
+      if ( psnames )
+      {
+        if ( psnames->unicode_value )
+        {
+          error = psnames->build_unicodes(
+                    root->memory,
+                    face->type1.num_glyphs,
+                    (const char**)face->type1.glyph_names,
+                    &face->unicode_map );
+          if ( !error )
+          {
+            root->charmap        = charmap;
+            charmap->face        = (FT_Face)face;
+            charmap->encoding    = ft_encoding_unicode;
+            charmap->platform_id = 3;
+            charmap->encoding_id = 1;
+            charmap++;
+          }
+
+          /* simply clear the error in case of failure (which really) */
+          /* means that out of memory or no unicode glyph names       */
+          error = T1_Err_Ok;
+        }
+      }
+
+      /* now, support either the standard, expert, or custom encoding */
+      charmap->face        = (FT_Face)face;
+      charmap->platform_id = 7;  /* a new platform id for Adobe fonts? */
+
+      switch ( face->type1.encoding_type )
+      {
+      case t1_encoding_standard:
+        charmap->encoding    = ft_encoding_adobe_standard;
+        charmap->encoding_id = 0;
+        break;
+
+      case t1_encoding_expert:
+        charmap->encoding    = ft_encoding_adobe_expert;
+        charmap->encoding_id = 1;
+        break;
+
+      default:
+        charmap->encoding    = ft_encoding_adobe_custom;
+        charmap->encoding_id = 2;
+        break;
+      }
+
+      root->charmaps     = face->charmaps;
+      root->num_charmaps = charmap - face->charmaprecs + 1;
+      face->charmaps[0]  = &face->charmaprecs[0];
+      face->charmaps[1]  = &face->charmaprecs[1];
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Init_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given Type 1 driver object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  T1_Init_Driver( T1_Driver  driver )
+  {
+    FT_UNUSED( driver );
+
+    return T1_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    T1_Done_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given Type 1 driver.                                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver  :: A handle to the target Type 1 driver.                   */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  T1_Done_Driver( T1_Driver  driver )
+  {
+    FT_UNUSED( driver );
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/t1parse.c b/libraries/freetype-2.0.5/t1parse.c
new file mode 100644 (file)
index 0000000..7faab53
--- /dev/null
@@ -0,0 +1,462 @@
+/***************************************************************************/
+/*                                                                         */
+/*  t1parse.c                                                              */
+/*                                                                         */
+/*    Type 1 parser (body).                                                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The Type 1 parser is in charge of the following:                      */
+  /*                                                                       */
+  /*  - provide an implementation of a growing sequence of objects called  */
+  /*    a `T1_Table' (used to build various tables needed by the loader).  */
+  /*                                                                       */
+  /*  - opening .pfb and .pfa files to extract their top-level and private */
+  /*    dictionaries.                                                      */
+  /*                                                                       */
+  /*  - read numbers, arrays & strings from any dictionary.                */
+  /*                                                                       */
+  /* See `t1load.c' to see how data is loaded from the font file.          */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+#include "t1parse.h"
+
+#include "t1errors.h"
+
+#include <string.h>     /* for strncmp() */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_t1parse
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   INPUT STREAM PARSER                         *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#define IS_T1_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
+#define IS_T1_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' )
+
+#define IS_T1_SPACE( c )  ( IS_T1_WHITESPACE( c ) || IS_T1_LINESPACE( c ) )
+
+
+  typedef struct  PFB_Tag_
+  {
+    FT_UShort  tag;
+    FT_Long    size;
+
+  } PFB_Tag;
+
+
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PFB_Tag
+
+
+  static
+  const FT_Frame_Field  pfb_tag_fields[] =
+  {
+    FT_FRAME_START( 6 ),
+      FT_FRAME_USHORT ( tag ),
+      FT_FRAME_LONG_LE( size ),
+    FT_FRAME_END
+  };
+
+
+  static FT_Error
+  read_pfb_tag( FT_Stream   stream,
+                FT_UShort*  tag,
+                FT_Long*    size )
+  {
+    FT_Error  error;
+    PFB_Tag   head;
+
+
+    *tag  = 0;
+    *size = 0;
+    if ( !READ_Fields( pfb_tag_fields, &head ) )
+    {
+      if ( head.tag == 0x8001 || head.tag == 0x8002 )
+      {
+        *tag  = head.tag;
+        *size = head.size;
+      }
+    }
+    return error;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_New_Parser( T1_ParserRec*     parser,
+                 FT_Stream         stream,
+                 FT_Memory         memory,
+                 PSAux_Interface*  psaux )
+  {
+    FT_Error   error;
+    FT_UShort  tag;
+    FT_Long    size;
+
+
+    psaux->t1_parser_funcs->init( &parser->root,0, 0, memory );
+
+    parser->stream       = stream;
+    parser->base_len     = 0;
+    parser->base_dict    = 0;
+    parser->private_len  = 0;
+    parser->private_dict = 0;
+    parser->in_pfb       = 0;
+    parser->in_memory    = 0;
+    parser->single_block = 0;
+
+    /******************************************************************/
+    /*                                                                */
+    /* Here a short summary of what is going on:                      */
+    /*                                                                */
+    /*   When creating a new Type 1 parser, we try to locate and load */
+    /*   the base dictionary if this is possible (i.e. for PFB        */
+    /*   files).  Otherwise, we load the whole font into memory.      */
+    /*                                                                */
+    /*   When `loading' the base dictionary, we only setup pointers   */
+    /*   in the case of a memory-based stream.  Otherwise, we         */
+    /*   allocate and load the base dictionary in it.                 */
+    /*                                                                */
+    /*   parser->in_pfb is set if we are in a binary (".pfb") font.   */
+    /*   parser->in_memory is set if we have a memory stream.         */
+    /*                                                                */
+
+    /* try to compute the size of the base dictionary;   */
+    /* look for a Postscript binary file tag, i.e 0x8001 */
+    if ( FILE_Seek( 0L ) )
+      goto Exit;
+
+    error = read_pfb_tag( stream, &tag, &size );
+    if ( error )
+      goto Exit;
+
+    if ( tag != 0x8001 )
+    {
+      /* assume that this is a PFA file for now; an error will */
+      /* be produced later when more things are checked        */
+      if ( FILE_Seek( 0L ) )
+        goto Exit;
+      size = stream->size;
+    }
+    else
+      parser->in_pfb = 1;
+
+    /* now, try to load `size' bytes of the `base' dictionary we */
+    /* found previously                                          */
+
+    /* if it is a memory-based resource, set up pointers */
+    if ( !stream->read )
+    {
+      parser->base_dict = (FT_Byte*)stream->base + stream->pos;
+      parser->base_len  = size;
+      parser->in_memory = 1;
+
+      /* check that the `size' field is valid */
+      if ( FILE_Skip( size ) )
+        goto Exit;
+    }
+    else
+    {
+      /* read segment in memory */
+      if ( ALLOC( parser->base_dict, size )     ||
+           FILE_Read( parser->base_dict, size ) )
+        goto Exit;
+      parser->base_len = size;
+    }
+
+    /* Now check font format; we must see `%!PS-AdobeFont-1' */
+    /* or `%!FontType'                                       */
+    {
+      if ( size <= 16                                    ||
+           ( strncmp( (const char*)parser->base_dict,
+                      "%!PS-AdobeFont-1", 16 )        &&
+             strncmp( (const char*)parser->base_dict,
+                      "%!FontType", 10 )              )  )
+      {
+        FT_TRACE2(( "[not a Type1 font]\n" ));
+        error = T1_Err_Unknown_File_Format;
+      }
+      else
+      {
+        parser->root.base   = parser->base_dict;
+        parser->root.cursor = parser->base_dict;
+        parser->root.limit  = parser->root.cursor + parser->base_len;
+      }
+    }
+
+  Exit:
+    if ( error && !parser->in_memory )
+      FREE( parser->base_dict );
+
+    return error;
+  }
+
+
+  FT_LOCAL_DEF void
+  T1_Finalize_Parser( T1_ParserRec*  parser )
+  {
+    FT_Memory   memory = parser->root.memory;
+
+
+    /* always free the private dictionary */
+    FREE( parser->private_dict );
+
+    /* free the base dictionary only when we have a disk stream */
+    if ( !parser->in_memory )
+      FREE( parser->base_dict );
+
+    parser->root.funcs.done( &parser->root );
+  }
+
+
+  /* return the value of an hexadecimal digit */
+  static int
+  hexa_value( char  c )
+  {
+    unsigned int  d;
+
+
+    d = (unsigned int)( c - '0' );
+    if ( d <= 9 )
+      return (int)d;
+
+    d = (unsigned int)( c - 'a' );
+    if ( d <= 5 )
+      return (int)( d + 10 );
+
+    d = (unsigned int)( c - 'A' );
+    if ( d <= 5 )
+      return (int)( d + 10 );
+
+    return -1;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  T1_Get_Private_Dict( T1_ParserRec*     parser,
+                       PSAux_Interface*  psaux )
+  {
+    FT_Stream  stream = parser->stream;
+    FT_Memory  memory = parser->root.memory;
+    FT_Error   error  = 0;
+    FT_Long    size;
+
+
+    if ( parser->in_pfb )
+    {
+      /* in the case of the PFB format, the private dictionary can be  */
+      /* made of several segments.  We thus first read the number of   */
+      /* segments to compute the total size of the private dictionary  */
+      /* then re-read them into memory.                                */
+      FT_Long    start_pos = FILE_Pos();
+      FT_UShort  tag;
+
+
+      parser->private_len = 0;
+      for (;;)
+      {
+        error = read_pfb_tag( stream, &tag, &size );
+        if ( error )
+          goto Fail;
+
+        if ( tag != 0x8002 )
+          break;
+
+        parser->private_len += size;
+
+        if ( FILE_Skip( size ) )
+          goto Fail;
+      }
+
+      /* Check that we have a private dictionary there */
+      /* and allocate private dictionary buffer        */
+      if ( parser->private_len == 0 )
+      {
+        FT_ERROR(( "T1_Get_Private_Dict:" ));
+        FT_ERROR(( " invalid private dictionary section\n" ));
+        error = T1_Err_Invalid_File_Format;
+        goto Fail;
+      }
+
+      if ( FILE_Seek( start_pos )                             ||
+           ALLOC( parser->private_dict, parser->private_len ) )
+        goto Fail;
+
+      parser->private_len = 0;
+      for (;;)
+      {
+        error = read_pfb_tag( stream, &tag, &size );
+        if ( error || tag != 0x8002 )
+        {
+          error = T1_Err_Ok;
+          break;
+        }
+
+        if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
+          goto Fail;
+
+        parser->private_len += size;
+      }
+    }
+    else
+    {
+      /* we have already `loaded' the whole PFA font file into memory; */
+      /* if this is a memory resource, allocate a new block to hold    */
+      /* the private dict. Otherwise, simply overwrite into the base   */
+      /* dictionary block in the heap.                                 */
+
+      /* first of all, look at the `eexec' keyword */
+      FT_Byte*  cur   = parser->base_dict;
+      FT_Byte*  limit = cur + parser->base_len;
+      FT_Byte   c;
+
+
+      for (;;)
+      {
+        c = cur[0];
+        if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
+                                            /* newline + 4 chars           */
+        {
+          if ( cur[1] == 'e' && cur[2] == 'x' &&
+               cur[3] == 'e' && cur[4] == 'c' )
+          {
+            cur += 6; /* we skip the newling after the `eexec' */
+
+            /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
+            /*      skip the extra \n if we find it                     */
+            if ( cur[0] == '\n' )
+              cur++;
+
+            break;
+          }
+        }
+        cur++;
+        if ( cur >= limit )
+        {
+          FT_ERROR(( "T1_Get_Private_Dict:" ));
+          FT_ERROR(( " could not find `eexec' keyword\n" ));
+          error = T1_Err_Invalid_File_Format;
+          goto Exit;
+        }
+      }
+
+      /* now determine where to write the _encrypted_ binary private  */
+      /* dictionary.  We overwrite the base dictionary for disk-based */
+      /* resources and allocate a new block otherwise                 */
+
+      size = (FT_Long)( parser->base_len - ( cur - parser->base_dict ) );
+
+      if ( parser->in_memory )
+      {
+        /* note that we allocate one more byte to put a terminating `0' */
+        if ( ALLOC( parser->private_dict, size + 1 ) )
+          goto Fail;
+        parser->private_len = size;
+      }
+      else
+      {
+        parser->single_block = 1;
+        parser->private_dict = parser->base_dict;
+        parser->private_len  = size;
+        parser->base_dict    = 0;
+        parser->base_len     = 0;
+      }
+
+      /* now determine whether the private dictionary is encoded in binary */
+      /* or hexadecimal ASCII format -- decode it accordingly              */
+
+      /* we need to access the next 4 bytes (after the final \r following */
+      /* the `eexec' keyword); if they all are hexadecimal digits, then   */
+      /* we have a case of ASCII storage                                  */
+
+      if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
+             hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
+
+        /* binary encoding -- `simply' copy the private dict */
+        MEM_Copy( parser->private_dict, cur, size );
+
+      else
+      {
+        /* ASCII hexadecimal encoding */
+
+        FT_Byte*  write;
+        FT_Int    count;
+
+
+        write = parser->private_dict;
+        count = 0;
+
+        for ( ;cur < limit; cur++ )
+        {
+          int  hex1;
+
+
+          /* check for newline */
+          if ( cur[0] == '\r' || cur[0] == '\n' )
+            continue;
+
+          /* exit if we have a non-hexadecimal digit that isn't a newline */
+          hex1 = hexa_value( cur[0] );
+          if ( hex1 < 0 || cur + 1 >= limit )
+            break;
+
+          /* otherwise, store byte */
+          *write++ = (FT_Byte)( ( hex1 << 4 ) | hexa_value( cur[1] ) );
+          count++;
+          cur++;
+        }
+
+        /* put a safeguard */
+        parser->private_len = (FT_Int)( write - parser->private_dict );
+        *write++ = 0;
+      }
+    }
+
+    /* we now decrypt the encoded binary private dictionary */
+    psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
+    parser->root.base = parser->private_dict;
+    parser->root.cursor = parser->private_dict;
+    parser->root.limit  = parser->root.cursor + parser->private_len;
+
+  Fail:
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/test_bbox.c b/libraries/freetype-2.0.5/test_bbox.c
new file mode 100644 (file)
index 0000000..5ac9894
--- /dev/null
@@ -0,0 +1,160 @@
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_BBOX_H
+
+
+#include <time.h>    /* for clock() */
+
+/* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include <sys/param.h> */
+/* to get the HZ macro which is the equivalent.                         */
+#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4)
+#include <sys/param.h>
+#define CLOCKS_PER_SEC HZ
+#endif
+
+  static long
+  get_time( void )
+  {
+    return clock() * 10000L / CLOCKS_PER_SEC;
+  }
+
+
+
+
+  /* test bbox computations */
+
+#define  XSCALE    65536
+#define  XX(x)     ((FT_Pos)(x*XSCALE))
+#define  XVEC(x,y)  { XX(x), XX(y) }
+#define  XVAL(x)   ((x)/(1.0*XSCALE))
+
+  /* dummy outline #1 */
+  static FT_Vector  dummy_vec_1[4] =
+  {
+#if 1
+    XVEC( 408.9111, 535.3164 ),
+    XVEC( 455.8887, 634.396  ),
+    XVEC( -37.8765, 786.2207 ),
+    XVEC( 164.6074, 535.3164 )
+#else
+    { (FT_Int32)0x0198E93DL , (FT_Int32)0x021750FFL },  /* 408.9111, 535.3164 */
+    { (FT_Int32)0x01C7E312L , (FT_Int32)0x027A6560L },  /* 455.8887, 634.3960 */
+    { (FT_Int32)0xFFDA1F9EL , (FT_Int32)0x0312387FL },  /* -37.8765, 786.2207 */
+    { (FT_Int32)0x00A49B7EL , (FT_Int32)0x021750FFL }   /* 164.6074, 535.3164 */
+#endif
+   };
+
+  static char  dummy_tag_1[4] =
+  {
+    FT_Curve_Tag_On,
+    FT_Curve_Tag_Cubic,
+    FT_Curve_Tag_Cubic,
+    FT_Curve_Tag_On
+  };
+
+  static short  dummy_contour_1[1] =
+  {
+    3
+  };
+
+  static FT_Outline  dummy_outline_1 =
+  {
+    1,
+    4,
+    dummy_vec_1,
+    dummy_tag_1,
+    dummy_contour_1,
+    0
+  };
+
+
+  /* dummy outline #2 */
+  static FT_Vector  dummy_vec_2[4] =
+  {
+    XVEC( 100.0, 100.0 ),
+    XVEC( 100.0, 200.0 ),
+    XVEC( 200.0, 200.0 ),
+    XVEC( 200.0, 133.0 )
+  };
+
+  static FT_Outline  dummy_outline_2 =
+  {
+    1,
+    4,
+    dummy_vec_2,
+    dummy_tag_1,
+    dummy_contour_1,
+    0
+  };
+
+
+  static void
+  dump_outline( FT_Outline*  outline )
+  {
+    FT_BBox  bbox;
+
+    /* compute and display cbox */
+    FT_Outline_Get_CBox( outline, &bbox );
+    printf( "cbox = [%.2f %.2f %.2f %.2f]\n",
+             XVAL( bbox.xMin ),
+             XVAL( bbox.yMin ),
+             XVAL( bbox.xMax ),
+             XVAL( bbox.yMax ) );
+
+    /* compute and display bbox */
+    FT_Outline_Get_BBox( outline, &bbox );
+    printf( "bbox = [%.2f %.2f %.2f %.2f]\n",
+             XVAL( bbox.xMin ),
+             XVAL( bbox.yMin ),
+             XVAL( bbox.xMax ),
+             XVAL( bbox.yMax ) );
+  }
+
+
+
+  static void
+  profile_outline( FT_Outline*   outline,
+                   long          repeat )
+  {
+    FT_BBox  bbox;
+    long     count;
+    long     time0;
+
+    time0 = get_time();
+    for ( count = repeat; count > 0; count-- )
+      FT_Outline_Get_CBox( outline, &bbox );
+
+    time0 = get_time() - time0;
+    printf( "time = %5.2f cbox = [%.2f %.2f %.2f %.2f]\n",
+             ((double)time0/10000.0),
+             XVAL( bbox.xMin ),
+             XVAL( bbox.yMin ),
+             XVAL( bbox.xMax ),
+             XVAL( bbox.yMax ) );
+
+
+    time0 = get_time();
+    for ( count = repeat; count > 0; count-- )
+      FT_Outline_Get_BBox( outline, &bbox );
+
+    time0 = get_time() - time0;
+    printf( "time = %5.2f bbox = [%.2f %.2f %.2f %.2f]\n",
+             ((double)time0/10000.0),
+             XVAL( bbox.xMin ),
+             XVAL( bbox.yMin ),
+             XVAL( bbox.xMax ),
+             XVAL( bbox.yMax ) );
+  }
+
+#define REPEAT  100000L
+
+  int  main( int  argc, char**  argv )
+  {
+    printf( "outline #1\n" );
+    profile_outline( &dummy_outline_1, REPEAT );
+
+    printf( "outline #2\n" );
+    profile_outline( &dummy_outline_2, REPEAT );
+    return 0;
+  }
+
diff --git a/libraries/freetype-2.0.5/test_trig.c b/libraries/freetype-2.0.5/test_trig.c
new file mode 100644 (file)
index 0000000..8c8a544
--- /dev/null
@@ -0,0 +1,236 @@
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TRIGONOMETRY_H
+
+#include <math.h>
+#include <stdio.h>
+
+#define  PI   3.14159265358979323846
+#define  SPI  (PI/FT_ANGLE_PI)
+
+/* the precision in 16.16 fixed float points of the checks. Expect */
+/* between 2 and 5 noise LSB bits during operations, due to        */
+/* rounding errors..                                               */
+#define  THRESHOLD  64
+
+  static  error = 0;
+
+  static void
+  test_cos( void )
+  {
+    FT_Fixed  f1, f2;
+    double    d1, d2;
+    int       i;
+
+    for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 )
+    {
+      f1 = FT_Cos(i);
+      d1 = f1/65536.0;
+      d2 = cos( i*SPI );
+      f2 = (FT_Fixed)(d2*65536.0);
+
+      if ( abs( f2-f1 ) > THRESHOLD )
+      {
+        error = 1;
+        printf( "FT_Cos[%3d] = %.7f  cos[%3d] = %.7f\n",
+                (i >> 16), f1/65536.0, (i >> 16), d2 );
+      }
+    }
+  }
+
+
+
+  static void
+  test_sin( void )
+  {
+    FT_Fixed  f1, f2;
+    double    d1, d2;
+    int       i;
+
+    for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 )
+    {
+      f1 = FT_Sin(i);
+      d1 = f1/65536.0;
+      d2 = sin( i*SPI );
+      f2 = (FT_Fixed)(d2*65536.0);
+
+      if ( abs( f2-f1 ) > THRESHOLD )
+      {
+        error = 1;
+        printf( "FT_Sin[%3d] = %.7f  sin[%3d] = %.7f\n",
+                (i >> 16), f1/65536.0, (i >> 16), d2 );
+      }
+    }
+  }
+
+
+  static void
+  test_tan( void )
+  {
+    FT_Fixed  f1, f2;
+    double    d1, d2;
+    int       i;
+
+    for ( i = 0; i < FT_ANGLE_PI2-0x2000000; i += 0x10000 )
+    {
+      f1 = FT_Tan(i);
+      d1 = f1/65536.0;
+      d2 = tan( i*SPI );
+      f2 = (FT_Fixed)(d2*65536.0);
+
+      if ( abs( f2-f1 ) > THRESHOLD )
+      {
+        error = 1;
+        printf( "FT_Tan[%3d] = %.7f  tan[%3d] = %.7f\n",
+                (i >> 16), f1/65536.0, (i >> 16), d2 );
+      }
+    }
+  }
+
+
+  static void
+  test_atan2( void )
+  {
+    FT_Fixed  c2, s2;
+    double    l, a, c1, s1;
+    int       i, j;
+
+    for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 )
+    {
+      l  = 5.0;
+      a  = i*SPI;
+
+      c1 = l * cos(a);
+      s1 = l * sin(a);
+
+      c2 = (FT_Fixed)(c1*65536.0);
+      s2 = (FT_Fixed)(s1*65536.0);
+
+      j  = FT_Atan2( c2, s2 );
+      if ( j < 0 )
+        j += FT_ANGLE_2PI;
+
+      if ( abs( i - j ) > 1 )
+      {
+        printf( "FT_Atan2( %.7f, %.7f ) = %.5f, atan = %.5f\n",
+                c2/65536.0, s2/65536.0, j/65536.0, i/65536.0 );
+      }
+    }
+  }
+
+  static void
+  test_unit( void )
+  {
+    FT_Vector  v;
+    double     a, c1, s1;
+    FT_Fixed   c2, s2;
+    int        i;
+
+    for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 )
+    {
+      FT_Vector_Unit( &v, i );
+      a  = ( i*SPI );
+      c1 = cos(a);
+      s1 = sin(a);
+      c2 = (FT_Fixed)(c1*65536.0);
+      s2 = (FT_Fixed)(s1*65536.0);
+
+      if ( abs( v.x-c2 ) > THRESHOLD ||
+           abs( v.y-s2 ) > THRESHOLD )
+      {
+        error = 1;
+        printf( "FT_Vector_Unit[%3d] = ( %.7f, %.7f )  vec = ( %.7f, %.7f )\n",
+                (i >> 16),
+                v.x/65536.0, v.y/65536.0,
+                c1, s1 );
+      }
+    }
+  }
+
+
+  static void
+  test_length( void )
+  {
+    FT_Vector  v;
+    FT_Fixed   l, l2;
+    int        i;
+
+    for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 )
+    {
+      l   = (FT_Fixed)(500.0*65536.0);
+      v.x = (FT_Fixed)( l * cos( i*SPI ) );
+      v.y = (FT_Fixed)( l * sin( i*SPI ) );
+      l2  = FT_Vector_Length( &v );
+
+      if ( abs( l2-l ) > THRESHOLD )
+      {
+        error = 1;
+        printf( "FT_Length( %.7f, %.7f ) = %.5f, length = %.5f\n",
+                v.x/65536.0, v.y/65536.0, l2/65536.0, l/65536.0 );
+      }
+    }
+  }
+
+
+  static void
+  test_rotate( void )
+  {
+    FT_Fixed  c2, s2, c4, s4;
+    FT_Vector v;
+    double    l, ra, a, c1, s1, cra, sra, c3, s3;
+    int       i, j, rotate;
+
+    for ( rotate = 0; rotate < FT_ANGLE_2PI; rotate += 0x10000 )
+    {
+      ra  = rotate*SPI;
+      cra = cos( ra );
+      sra = sin( ra );
+
+      for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000 )
+      {
+        l  = 500.0;
+        a  = i*SPI;
+
+        c1 = l * cos(a);
+        s1 = l * sin(a);
+
+        v.x = c2 = (FT_Fixed)(c1*65536.0);
+        v.y = s2 = (FT_Fixed)(s1*65536.0);
+
+        FT_Vector_Rotate( &v, rotate );
+
+        c3 = c1 * cra - s1 * sra;
+        s3 = c1 * sra + s1 * cra;
+
+        c4 = (FT_Fixed)(c3*65536.0);
+        s4 = (FT_Fixed)(s3*65536.0);
+
+        if ( abs( c4 - v.x ) > THRESHOLD ||
+             abs( s4 - v.y ) > THRESHOLD )
+        {
+          error = 1;
+          printf( "FT_Rotate( (%.7f,%.7f), %.5f ) = ( %.7f, %.7f ), rot = ( %.7f, %.7f )\n",
+                  c1, s1, ra,
+                  c2/65536.0, s2/65536.0,
+                  c4/65536.0, s4/65536.0 );
+        }
+      }
+    }
+  }
+
+
+  int main( void )
+  {
+    test_cos();
+    test_sin();
+    test_tan();
+    test_atan2();
+    test_unit();
+    test_length();
+    test_rotate();
+
+    if (!error)
+      printf( "trigonometry test ok !\n" );
+
+    return !error;
+  }
diff --git a/libraries/freetype-2.0.5/truetype.c b/libraries/freetype-2.0.5/truetype.c
new file mode 100644 (file)
index 0000000..1ed3ceb
--- /dev/null
@@ -0,0 +1,32 @@
+/***************************************************************************/
+/*                                                                         */
+/*  truetype.c                                                             */
+/*                                                                         */
+/*    FreeType TrueType driver component (body only).                      */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "ttdriver.c"   /* driver interface */
+#include "ttpload.c"    /* tables loader    */
+#include "ttgload.c"    /* glyph loader     */
+#include "ttobjs.c"     /* object manager   */
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include "ttinterp.c"
+#endif
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ttcmap.c b/libraries/freetype-2.0.5/ttcmap.c
new file mode 100644 (file)
index 0000000..b37faf4
--- /dev/null
@@ -0,0 +1,756 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttcmap.c                                                               */
+/*                                                                         */
+/*    TrueType character mapping table (cmap) support (body).              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include "ttload.h"
+#include "ttcmap.h"
+
+#include "sferrors.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttcmap
+
+
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index0( TT_CMapTable*  charmap,
+                  FT_ULong       char_code );
+
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index2( TT_CMapTable*  charmap,
+                  FT_ULong       char_code );
+
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index4( TT_CMapTable*  charmap,
+                  FT_ULong       char_code );
+
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index6( TT_CMapTable*  charmap,
+                  FT_ULong       char_code );
+
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index8_12( TT_CMapTable*  charmap,
+                     FT_ULong       char_code );
+
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index10( TT_CMapTable*  charmap,
+                   FT_ULong       char_code );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_CharMap_Load                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given TrueType character map into memory.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the parent face object.                      */
+  /*    stream :: A handle to the current stream object.                   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    table  :: A pointer to a cmap object.                              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The function assumes that the stream is already in use (i.e.,      */
+  /*    opened).  In case of error, all partially allocated tables are     */
+  /*    released.                                                          */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_CharMap_Load( TT_Face        face,
+                   TT_CMapTable*  cmap,
+                   FT_Stream      stream )
+  {
+    FT_Error      error;
+    FT_Memory     memory;
+    FT_UShort     num_SH, num_Seg, i;
+    FT_ULong      j, n;
+
+    FT_UShort     u, l;
+
+    TT_CMap0*     cmap0;
+    TT_CMap2*     cmap2;
+    TT_CMap4*     cmap4;
+    TT_CMap6*     cmap6;
+    TT_CMap8_12*  cmap8_12;
+    TT_CMap10*    cmap10;
+
+    TT_CMap2SubHeader*  cmap2sub;
+    TT_CMap4Segment*    segments;
+    TT_CMapGroup*       groups;
+
+
+    if ( cmap->loaded )
+      return SFNT_Err_Ok;
+
+    memory = stream->memory;
+
+    if ( FILE_Seek( cmap->offset ) )
+      return error;
+
+    switch ( cmap->format )
+    {
+    case 0:
+      cmap0 = &cmap->c.cmap0;
+
+      if ( READ_UShort( cmap0->language )         ||
+           ALLOC( cmap0->glyphIdArray, 256L )     ||
+           FILE_Read( cmap0->glyphIdArray, 256L ) )
+        goto Fail;
+
+      cmap->get_index = code_to_index0;
+      break;
+
+    case 2:
+      num_SH = 0;
+      cmap2  = &cmap->c.cmap2;
+
+      /* allocate subheader keys */
+
+      if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, FT_UShort ) ||
+           ACCESS_Frame( 2L + 512L )                           )
+        goto Fail;
+
+      cmap2->language = GET_UShort();
+
+      for ( i = 0; i < 256; i++ )
+      {
+        u = (FT_UShort)( GET_UShort() / 8 );
+        cmap2->subHeaderKeys[i] = u;
+
+        if ( num_SH < u )
+          num_SH = u;
+      }
+
+      FORGET_Frame();
+
+      /* load subheaders */
+
+      cmap2->numGlyphId = l = (FT_UShort)(
+        ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFF ) / 2 );
+
+      if ( ALLOC_ARRAY( cmap2->subHeaders,
+                        num_SH + 1,
+                        TT_CMap2SubHeader )    ||
+           ACCESS_Frame( ( num_SH + 1 ) * 8L ) )
+      {
+        FREE( cmap2->subHeaderKeys );
+        goto Fail;
+      }
+
+      cmap2sub = cmap2->subHeaders;
+
+      for ( i = 0; i <= num_SH; i++ )
+      {
+        cmap2sub->firstCode     = GET_UShort();
+        cmap2sub->entryCount    = GET_UShort();
+        cmap2sub->idDelta       = GET_Short();
+        /* we apply the location offset immediately */
+        cmap2sub->idRangeOffset = (FT_UShort)(
+          GET_UShort() - ( num_SH - i ) * 8 - 2 );
+
+        cmap2sub++;
+      }
+
+      FORGET_Frame();
+
+      /* load glyph IDs */
+
+      if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, FT_UShort ) ||
+           ACCESS_Frame( l * 2L )                           )
+      {
+        FREE( cmap2->subHeaders );
+        FREE( cmap2->subHeaderKeys );
+        goto Fail;
+      }
+
+      for ( i = 0; i < l; i++ )
+        cmap2->glyphIdArray[i] = GET_UShort();
+
+      FORGET_Frame();
+
+      cmap->get_index = code_to_index2;
+      break;
+
+    case 4:
+      cmap4 = &cmap->c.cmap4;
+
+      /* load header */
+
+      if ( ACCESS_Frame( 10L ) )
+        goto Fail;
+
+      cmap4->language      = GET_UShort();
+      cmap4->segCountX2    = GET_UShort();
+      cmap4->searchRange   = GET_UShort();
+      cmap4->entrySelector = GET_UShort();
+      cmap4->rangeShift    = GET_UShort();
+
+      num_Seg = (FT_UShort)( cmap4->segCountX2 / 2 );
+
+      FORGET_Frame();
+
+      /* load segments */
+
+      if ( ALLOC_ARRAY( cmap4->segments,
+                        num_Seg,
+                        TT_CMap4Segment )           ||
+           ACCESS_Frame( ( num_Seg * 4 + 1 ) * 2L ) )
+        goto Fail;
+
+      segments = cmap4->segments;
+
+      for ( i = 0; i < num_Seg; i++ )
+        segments[i].endCount      = GET_UShort();
+
+      (void)GET_UShort();
+
+      for ( i = 0; i < num_Seg; i++ )
+        segments[i].startCount    = GET_UShort();
+
+      for ( i = 0; i < num_Seg; i++ )
+        segments[i].idDelta       = GET_Short();
+
+      for ( i = 0; i < num_Seg; i++ )
+        segments[i].idRangeOffset = GET_UShort();
+
+      FORGET_Frame();
+
+      cmap4->numGlyphId = l = (FT_UShort)(
+        ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFF ) / 2 );
+
+      /* load IDs */
+
+      if ( ALLOC_ARRAY( cmap4->glyphIdArray, l, FT_UShort ) ||
+           ACCESS_Frame( l * 2L )                           )
+      {
+        FREE( cmap4->segments );
+        goto Fail;
+      }
+
+      for ( i = 0; i < l; i++ )
+        cmap4->glyphIdArray[i] = GET_UShort();
+
+      FORGET_Frame();
+
+      cmap4->last_segment = cmap4->segments;
+
+      cmap->get_index = code_to_index4;
+      break;
+
+    case 6:
+      cmap6 = &cmap->c.cmap6;
+
+      if ( ACCESS_Frame( 6L ) )
+        goto Fail;
+
+      cmap6->language   = GET_UShort();
+      cmap6->firstCode  = GET_UShort();
+      cmap6->entryCount = GET_UShort();
+
+      FORGET_Frame();
+
+      l = cmap6->entryCount;
+
+      if ( ALLOC_ARRAY( cmap6->glyphIdArray, l, FT_Short ) ||
+           ACCESS_Frame( l * 2L )                          )
+        goto Fail;
+
+      for ( i = 0; i < l; i++ )
+        cmap6->glyphIdArray[i] = GET_UShort();
+
+      FORGET_Frame();
+      cmap->get_index = code_to_index6;
+      break;
+
+    case 8:
+    case 12:
+      cmap8_12 = &cmap->c.cmap8_12;
+
+      if ( ACCESS_Frame( 8L ) )
+        goto Fail;
+
+      cmap->length       = GET_ULong();
+      cmap8_12->language = GET_ULong();
+
+      FORGET_Frame();
+
+      if ( cmap->format == 8 )
+        if ( FILE_Skip( 8192L ) )
+          goto Fail;
+
+      if ( READ_ULong( cmap8_12->nGroups ) )
+        goto Fail;
+
+      n = cmap8_12->nGroups;
+
+      if ( ALLOC_ARRAY( cmap8_12->groups, n, TT_CMapGroup ) ||
+           ACCESS_Frame( n * 3 * 4L )                       )
+        goto Fail;
+
+      groups = cmap8_12->groups;
+
+      for ( j = 0; j < n; j++ )
+      {
+        groups[j].startCharCode = GET_ULong();
+        groups[j].endCharCode   = GET_ULong();
+        groups[j].startGlyphID  = GET_ULong();
+      }
+
+      FORGET_Frame();
+
+      cmap8_12->last_group = cmap8_12->groups;
+
+      cmap->get_index = code_to_index8_12;
+      break;
+
+    case 10:
+      cmap10 = &cmap->c.cmap10;
+
+      if ( ACCESS_Frame( 16L ) )
+        goto Fail;
+
+      cmap->length          = GET_ULong();
+      cmap10->language      = GET_ULong();
+      cmap10->startCharCode = GET_ULong();
+      cmap10->numChars      = GET_ULong();
+
+      FORGET_Frame();
+
+      n = cmap10->numChars;
+
+      if ( ALLOC_ARRAY( cmap10->glyphs, n, FT_Short ) ||
+           ACCESS_Frame( n * 2L )                     )
+        goto Fail;
+
+      for ( j = 0; j < n; j++ )
+        cmap10->glyphs[j] = GET_UShort();
+
+      FORGET_Frame();
+      cmap->get_index = code_to_index10;
+      break;
+
+    default:   /* corrupt character mapping table */
+      return SFNT_Err_Invalid_CharMap_Format;
+
+    }
+
+    return SFNT_Err_Ok;
+
+  Fail:
+    TT_CharMap_Free( face, cmap );
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_CharMap_Free                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a character mapping table.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the parent face object.                        */
+  /*    cmap :: A handle to a cmap object.                                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_CharMap_Free( TT_Face        face,
+                   TT_CMapTable*  cmap )
+  {
+    FT_Memory  memory;
+
+
+    if ( !cmap )
+      return SFNT_Err_Ok;
+
+    memory = face->root.driver->root.memory;
+
+    switch ( cmap->format )
+    {
+    case 0:
+      FREE( cmap->c.cmap0.glyphIdArray );
+      break;
+
+    case 2:
+      FREE( cmap->c.cmap2.subHeaderKeys );
+      FREE( cmap->c.cmap2.subHeaders );
+      FREE( cmap->c.cmap2.glyphIdArray );
+      break;
+
+    case 4:
+      FREE( cmap->c.cmap4.segments );
+      FREE( cmap->c.cmap4.glyphIdArray );
+      cmap->c.cmap4.segCountX2 = 0;
+      break;
+
+    case 6:
+      FREE( cmap->c.cmap6.glyphIdArray );
+      cmap->c.cmap6.entryCount = 0;
+      break;
+
+    case 8:
+    case 12:
+      FREE( cmap->c.cmap8_12.groups );
+      cmap->c.cmap8_12.nGroups = 0;
+      break;
+
+    case 10:
+      FREE( cmap->c.cmap10.glyphs );
+      cmap->c.cmap10.numChars = 0;
+      break;
+
+    default:
+      /* invalid table format, do nothing */
+      ;
+    }
+
+    cmap->loaded = FALSE;
+    return SFNT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    code_to_index0                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts the character code into a glyph index.  Uses format 0.    */
+  /*    `charCode' must be in the range 0x00-0xFF (otherwise 0 is          */
+  /*    returned).                                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charCode :: The wanted character code.                             */
+  /*    cmap0    :: A pointer to a cmap table in format 0.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
+  /*                                                                       */
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index0( TT_CMapTable*  cmap,
+                  FT_ULong       charCode )
+  {
+    TT_CMap0*  cmap0 = &cmap->c.cmap0;
+
+
+    return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    code_to_index2                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts the character code into a glyph index.  Uses format 2.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charCode :: The wanted character code.                             */
+  /*    cmap2    :: A pointer to a cmap table in format 2.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
+  /*                                                                       */
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index2( TT_CMapTable*  cmap,
+                  FT_ULong       charCode )
+  {
+    FT_UInt             result, index1, offset;
+    FT_UInt             char_lo;
+    FT_ULong            char_hi;
+    TT_CMap2SubHeader*  sh2;
+    TT_CMap2*           cmap2;
+
+
+    cmap2   = &cmap->c.cmap2;
+    result  = 0;
+    char_lo = (FT_UInt)( charCode & 0xFF );
+    char_hi = charCode >> 8;
+
+    if ( char_hi == 0 )
+    {
+      /* an 8-bit character code -- we use the subHeader 0 in this case */
+      /* to test whether the character code is in the charmap           */
+      index1 = cmap2->subHeaderKeys[char_lo];
+      if ( index1 != 0 )
+        return 0;
+    }
+    else
+    {
+      /* a 16-bit character code */
+      index1 = cmap2->subHeaderKeys[char_hi & 0xFF];
+      if ( index1 == 0 )
+        return 0;
+    }
+
+    sh2      = cmap2->subHeaders + index1;
+    char_lo -= sh2->firstCode;
+
+    if ( char_lo < (FT_UInt)sh2->entryCount )
+    {
+      offset = sh2->idRangeOffset / 2 + char_lo;
+      if ( offset < (FT_UInt)cmap2->numGlyphId )
+      {
+        result = cmap2->glyphIdArray[offset];
+        if ( result )
+          result = ( result + sh2->idDelta ) & 0xFFFF;
+      }
+    }
+
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    code_to_index4                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts the character code into a glyph index.  Uses format 4.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charCode :: The wanted character code.                             */
+  /*    cmap4    :: A pointer to a cmap table in format 4.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
+  /*                                                                       */
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index4( TT_CMapTable*  cmap,
+                  FT_ULong       charCode )
+  {
+    FT_UInt          result, index1, segCount;
+    TT_CMap4*        cmap4;
+    TT_CMap4Segment  *seg4, *limit;
+
+
+    cmap4    = &cmap->c.cmap4;
+    result   = 0;
+    segCount = cmap4->segCountX2 / 2;
+    limit    = cmap4->segments + segCount;
+
+    /* first, check against the last used segment */
+
+    seg4 = cmap4->last_segment;
+
+    /* the following is equivalent to performing two tests, as in         */
+    /*                                                                    */
+    /*  if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */
+    /*                                                                    */
+    /* This is a bit strange, but it is faster, and the idea behind the   */
+    /* cache is to significantly speed up charcode to glyph index         */
+    /* conversion.                                                        */
+
+    if ( (FT_ULong)( charCode       - seg4->startCount ) <
+         (FT_ULong)( seg4->endCount - seg4->startCount ) )
+      goto Found1;
+
+    for ( seg4 = cmap4->segments; seg4 < limit; seg4++ )
+    {
+      /* the ranges are sorted in increasing order.  If we are out of */
+      /* the range here, the char code isn't in the charmap, so exit. */
+
+      if ( charCode > (FT_UInt)seg4->endCount )
+        continue;
+
+      if ( charCode >= (FT_UInt)seg4->startCount )
+        goto Found;
+    }
+    return 0;
+
+  Found:
+    cmap4->last_segment = seg4;
+
+  Found1:
+    /* if the idRangeOffset is 0, we can compute the glyph index */
+    /* directly                                                  */
+
+    if ( seg4->idRangeOffset == 0 )
+      result = ( charCode + seg4->idDelta ) & 0xFFFF;
+    else
+    {
+      /* otherwise, we must use the glyphIdArray to do it */
+      index1 = (FT_UInt)( seg4->idRangeOffset / 2
+                          + ( charCode - seg4->startCount )
+                          + ( seg4 - cmap4->segments )
+                          - segCount );
+
+      if ( index1 < (FT_UInt)cmap4->numGlyphId &&
+           cmap4->glyphIdArray[index1] != 0    )
+        result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFF;
+    }
+
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    code_to_index6                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts the character code into a glyph index.  Uses format 6.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charCode :: The wanted character code.                             */
+  /*    cmap6    :: A pointer to a cmap table in format 6.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
+  /*                                                                       */
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index6( TT_CMapTable*  cmap,
+                  FT_ULong       charCode )
+  {
+    TT_CMap6*  cmap6;
+    FT_UInt    result = 0;
+
+
+    cmap6     = &cmap->c.cmap6;
+    charCode -= cmap6->firstCode;
+
+    if ( charCode < (FT_UInt)cmap6->entryCount )
+      result = cmap6->glyphIdArray[charCode];
+
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    code_to_index8_12                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts the (possibly 32bit) character code into a glyph index.   */
+  /*    Uses format 8 or 12.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charCode :: The wanted character code.                             */
+  /*    cmap8_12 :: A pointer to a cmap table in format 8 or 12.           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
+  /*                                                                       */
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index8_12( TT_CMapTable*  cmap,
+                     FT_ULong       charCode )
+  {
+    TT_CMap8_12*  cmap8_12;
+    TT_CMapGroup  *group, *limit;
+
+
+    cmap8_12 = &cmap->c.cmap8_12;
+    limit    = cmap8_12->groups + cmap8_12->nGroups;
+
+    /* first, check against the last used group */
+
+    group = cmap8_12->last_group;
+
+    /* the following is equivalent to performing two tests, as in       */
+    /*                                                                  */
+    /*  if ( charCode >= group->startCharCode &&                        */
+    /*       charCode <= group->endCharCode   )                         */
+    /*                                                                  */
+    /* This is a bit strange, but it is faster, and the idea behind the */
+    /* cache is to significantly speed up charcode to glyph index       */
+    /* conversion.                                                      */
+
+    if ( (FT_ULong)( charCode           - group->startCharCode ) <
+         (FT_ULong)( group->endCharCode - group->startCharCode ) )
+      goto Found1;
+
+    for ( group = cmap8_12->groups; group < limit; group++ )
+    {
+      /* the ranges are sorted in increasing order.  If we are out of */
+      /* the range here, the char code isn't in the charmap, so exit. */
+
+      if ( charCode > group->endCharCode )
+        continue;
+
+      if ( charCode >= group->startCharCode )
+        goto Found;
+    }
+    return 0;
+
+  Found:
+    cmap8_12->last_group = group;
+
+  Found1:
+    return group->startGlyphID + (FT_UInt)( charCode - group->startCharCode );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    code_to_index10                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts the (possibly 32bit) character code into a glyph index.   */
+  /*    Uses format 10.                                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charCode :: The wanted character code.                             */
+  /*    cmap10   :: A pointer to a cmap table in format 10.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index into the glyphs array.  0 if the glyph does not exist. */
+  /*                                                                       */
+  FT_CALLBACK_DEF( FT_UInt )
+  code_to_index10( TT_CMapTable*  cmap,
+                   FT_ULong       charCode )
+  {
+    TT_CMap10*  cmap10;
+    FT_UInt     result = 0;
+
+
+    cmap10    = &cmap->c.cmap10;
+    charCode -= cmap10->startCharCode;
+
+    /* the overflow trick for comparison works here also since the number */
+    /* of glyphs (even if numChars is specified as ULong in the specs) in */
+    /* an OpenType font is limited to 64k                                 */
+
+    if ( charCode < cmap10->numChars )
+      result = cmap10->glyphs[charCode];
+
+    return result;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ttdriver.c b/libraries/freetype-2.0.5/ttdriver.c
new file mode 100644 (file)
index 0000000..85b9d6a
--- /dev/null
@@ -0,0 +1,512 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttdriver.c                                                             */
+/*                                                                         */
+/*    TrueType font driver implementation (body).                          */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_TRUETYPE_IDS_H
+
+#include "ttdriver.h"
+#include "ttgload.h"
+
+#include "tterrors.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttdriver
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                          F A C E S                              ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#undef  PAIR_TAG
+#define PAIR_TAG( left, right )  ( ( (FT_ULong)left << 16 ) | \
+                                     (FT_ULong)right        )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Kerning                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to return the kerning vector between two      */
+  /*    glyphs of the same face.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face        :: A handle to the source face object.                 */
+  /*                                                                       */
+  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
+  /*                                                                       */
+  /*    right_glyph :: The index of the right glyph in the kern pair.      */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    kerning     :: The kerning vector.  This is in font units for      */
+  /*                   scalable formats, and in pixels for fixed-sizes     */
+  /*                   formats.                                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
+  /*    supported by this function.  Other layouts, or more sophisticated  */
+  /*    kernings, are out of scope of this method (the basic driver        */
+  /*    interface is meant to be simple).                                  */
+  /*                                                                       */
+  /*    They can be implemented by format-specific interfaces.             */
+  /*                                                                       */
+  static FT_Error
+  Get_Kerning( TT_Face     face,
+               FT_UInt     left_glyph,
+               FT_UInt     right_glyph,
+               FT_Vector*  kerning )
+  {
+    TT_Kern_0_Pair*  pair;
+
+
+    if ( !face )
+      return TT_Err_Invalid_Face_Handle;
+
+    kerning->x = 0;
+    kerning->y = 0;
+
+    if ( face->kern_pairs )
+    {
+      /* there are some kerning pairs in this font file! */
+      FT_ULong  search_tag = PAIR_TAG( left_glyph, right_glyph );
+      FT_Long   left, right;
+
+
+      left  = 0;
+      right = face->num_kern_pairs - 1;
+
+      while ( left <= right )
+      {
+        FT_Int    middle = left + ( ( right - left ) >> 1 );
+        FT_ULong  cur_pair;
+
+
+        pair     = face->kern_pairs + middle;
+        cur_pair = PAIR_TAG( pair->left, pair->right );
+
+        if ( cur_pair == search_tag )
+          goto Found;
+
+        if ( cur_pair < search_tag )
+          left = middle + 1;
+        else
+          right = middle - 1;
+      }
+    }
+
+  Exit:
+    return TT_Err_Ok;
+
+  Found:
+    kerning->x = pair->value;
+    goto Exit;
+  }
+
+
+#undef PAIR_TAG
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                           S I Z E S                             ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_Char_Sizes                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to reset a size's character sizes (horizontal */
+  /*    and vertical) expressed in fractional points.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    char_width      :: The character width expressed in 26.6           */
+  /*                       fractional points.                              */
+  /*                                                                       */
+  /*    char_height     :: The character height expressed in 26.6          */
+  /*                       fractional points.                              */
+  /*                                                                       */
+  /*    horz_resolution :: The horizontal resolution of the output device. */
+  /*                                                                       */
+  /*    vert_resolution :: The vertical resolution of the output device.   */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size            :: A handle to the target size object.             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  Set_Char_Sizes( TT_Size     size,
+                  FT_F26Dot6  char_width,
+                  FT_F26Dot6  char_height,
+                  FT_UInt     horz_resolution,
+                  FT_UInt     vert_resolution )
+  {
+    FT_Size_Metrics*  metrics = &size->root.metrics;
+    TT_Face           face    = (TT_Face)size->root.face;
+    FT_Long           dim_x, dim_y;
+
+
+    /* This bit flag, when set, indicates that the pixel size must be */
+    /* truncated to an integer.  Nearly all TrueType fonts have this  */
+    /* bit set, as hinting won't work really well otherwise.          */
+    /*                                                                */
+    /* However, for those rare fonts who do not set it, we override   */
+    /* the default computations performed by the base layer.  I       */
+    /* really don't know whether this is useful, but hey, that's the  */
+    /* spec :-)                                                       */
+    /*                                                                */
+    if ( ( face->header.Flags & 8 ) == 0 )
+    {
+      /* Compute pixel sizes in 26.6 units */
+      dim_x = ( char_width  * horz_resolution ) / 72;
+      dim_y = ( char_height * vert_resolution ) / 72;
+
+      metrics->x_scale = FT_DivFix( dim_x, face->root.units_per_EM );
+      metrics->y_scale = FT_DivFix( dim_y, face->root.units_per_EM );
+
+      metrics->x_ppem  = (FT_UShort)( dim_x >> 6 );
+      metrics->y_ppem  = (FT_UShort)( dim_y >> 6 );
+    }
+
+    size->ttmetrics.valid = FALSE;
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+    size->strike_index    = 0xFFFF;
+#endif
+
+    return TT_Reset_Size( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_Pixel_Sizes                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to reset a size's character sizes (horizontal */
+  /*    and vertical) expressed in integer pixels.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    pixel_width  :: The character width expressed in integer pixels.   */
+  /*                                                                       */
+  /*    pixel_height :: The character height expressed in integer pixels.  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size         :: A handle to the target size object.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  Set_Pixel_Sizes( TT_Size  size,
+                   FT_UInt  pixel_width,
+                   FT_UInt  pixel_height )
+  {
+    FT_UNUSED( pixel_width );
+    FT_UNUSED( pixel_height );
+
+    /* many things have been pre-computed by the base layer */
+
+    size->ttmetrics.valid = FALSE;
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+    size->strike_index    = 0xFFFF;
+#endif
+
+    return TT_Reset_Size( size );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Load_Glyph                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A driver method used to load a glyph within a given glyph slot.    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    slot        :: A handle to the target slot object where the glyph  */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    size        :: A handle to the source face size at which the glyph */
+  /*                   must be scaled, loaded, etc.                        */
+  /*                                                                       */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FTLOAD_??? constants can be used to control the     */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  Load_Glyph( TT_GlyphSlot  slot,
+              TT_Size       size,
+              FT_UShort     glyph_index,
+              FT_UInt       load_flags )
+  {
+    FT_Error  error;
+
+
+    if ( !slot )
+      return TT_Err_Invalid_Slot_Handle;
+
+    /* check whether we want a scaled outline or bitmap */
+    if ( !size )
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+    if ( load_flags & FT_LOAD_NO_SCALE )
+      size = NULL;
+
+    /* reset the size object if necessary */
+    if ( size )
+    {
+      /* these two object must have the same parent */
+      if ( size->root.face != slot->face )
+        return TT_Err_Invalid_Face_Handle;
+
+      if ( !size->ttmetrics.valid )
+      {
+        if ( FT_SET_ERROR( TT_Reset_Size( size ) ) )
+          return error;
+      }
+    }
+
+    /* now load the glyph outline if necessary */
+    error = TT_Load_Glyph( size, slot, glyph_index, load_flags );
+
+    /* force drop-out mode to 2 - irrelevant now */
+    /* slot->outline.dropout_mode = 2; */
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****             C H A R A C T E R   M A P P I N G S                 ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Get_Char_Index                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Uses a charmap to return a given character code's glyph index.     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    charmap  :: A handle to the source charmap object.                 */
+  /*    charcode :: The character code.                                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Glyph index.  0 means `undefined character code'.                  */
+  /*                                                                       */
+  static FT_UInt
+  Get_Char_Index( TT_CharMap  charmap,
+                  FT_Long     charcode )
+  {
+    FT_Error       error;
+    TT_Face        face;
+    TT_CMapTable*  cmap;
+
+
+    cmap = &charmap->cmap;
+    face = (TT_Face)charmap->root.face;
+
+    /* Load table if needed */
+    if ( !cmap->loaded )
+    {
+      SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
+
+
+      error = sfnt->load_charmap( face, cmap, face->root.stream );
+      if ( error )
+        return 0;
+
+      cmap->loaded = TRUE;
+    }
+
+    if ( cmap->get_index )
+      return cmap->get_index( cmap, charcode );
+    else
+      return 0;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /****                D R I V E R  I N T E R F A C E                   ****/
+  /****                                                                 ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static FT_Module_Interface
+  tt_get_interface( TT_Driver    driver,
+                    const char*  interface )
+  {
+    FT_Module        sfntd = FT_Get_Module( driver->root.root.library,
+                                            "sfnt" );
+    SFNT_Interface*  sfnt;
+
+
+    /* only return the default interface from the SFNT module */
+    if ( sfntd )
+    {
+      sfnt = (SFNT_Interface*)( sfntd->clazz->module_interface );
+      if ( sfnt )
+        return sfnt->get_interface( FT_MODULE( driver ), interface );
+    }
+
+    return 0;
+  }
+
+
+  /* The FT_DriverInterface structure is defined in ftdriver.h. */
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Driver_Class  tt_driver_class =
+  {
+    {
+      ft_module_font_driver     |
+      ft_module_driver_scalable |
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+      ft_module_driver_has_hinter,
+#else
+      0,
+#endif
+
+      sizeof ( TT_DriverRec ),
+
+      "truetype",      /* driver name                           */
+      0x10000L,        /* driver version == 1.0                 */
+      0x20000L,        /* driver requires FreeType 2.0 or above */
+
+      (void*)0,        /* driver specific interface */
+
+      (FT_Module_Constructor)TT_Init_Driver,
+      (FT_Module_Destructor) TT_Done_Driver,
+      (FT_Module_Requester)  tt_get_interface,
+    },
+
+    sizeof ( TT_FaceRec ),
+    sizeof ( TT_SizeRec ),
+    sizeof ( FT_GlyphSlotRec ),
+
+
+    (FTDriver_initFace)     TT_Init_Face,
+    (FTDriver_doneFace)     TT_Done_Face,
+    (FTDriver_initSize)     TT_Init_Size,
+    (FTDriver_doneSize)     TT_Done_Size,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) Set_Char_Sizes,
+    (FTDriver_setPixelSizes)Set_Pixel_Sizes,
+    (FTDriver_loadGlyph)    Load_Glyph,
+    (FTDriver_getCharIndex) Get_Char_Index,
+
+    (FTDriver_getKerning)   Get_Kerning,
+    (FTDriver_attachFile)   0,
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverClass                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the TrueType driver as a      */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+  FT_EXPORT_DEF( const FT_Driver_Class* )
+  getDriverClass( void )
+  {
+    return &tt_driver_class;
+  }
+
+
+#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ttgload.c b/libraries/freetype-2.0.5/ttgload.c
new file mode 100644 (file)
index 0000000..3f89fa7
--- /dev/null
@@ -0,0 +1,1490 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttgload.c                                                              */
+/*                                                                         */
+/*    TrueType Glyph Loader (body).                                        */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_OUTLINE_H
+
+#include "ttgload.h"
+
+#include "tterrors.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttgload
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Composite font flags.                                                 */
+  /*                                                                       */
+#define ARGS_ARE_WORDS       0x001
+#define ARGS_ARE_XY_VALUES   0x002
+#define ROUND_XY_TO_GRID     0x004
+#define WE_HAVE_A_SCALE      0x008
+/* reserved                  0x010 */
+#define MORE_COMPONENTS      0x020
+#define WE_HAVE_AN_XY_SCALE  0x040
+#define WE_HAVE_A_2X2        0x080
+#define WE_HAVE_INSTR        0x100
+#define USE_MY_METRICS       0x200
+
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Get_Metrics                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the horizontal or vertical metrics in font units for a     */
+  /*    given glyph.  The metrics are the left side bearing (resp. top     */
+  /*    side bearing) and advance width (resp. advance height).            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    header  :: A pointer to either the horizontal or vertical metrics  */
+  /*               structure.                                              */
+  /*                                                                       */
+  /*    index   :: The glyph index.                                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    bearing :: The bearing, either left side or top side.              */
+  /*                                                                       */
+  /*    advance :: The advance width resp. advance height.                 */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This function will much probably move to another component in the  */
+  /*    near future, but I haven't decided which yet.                      */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  TT_Get_Metrics( TT_HoriHeader*  header,
+                  FT_UInt         index,
+                  FT_Short*       bearing,
+                  FT_UShort*      advance )
+  {
+    TT_LongMetrics*  longs_m;
+    FT_UShort        k = header->number_Of_HMetrics;
+
+
+    if ( index < (FT_UInt)k )
+    {
+      longs_m  = (TT_LongMetrics*)header->long_metrics + index;
+      *bearing = longs_m->bearing;
+      *advance = longs_m->advance;
+    }
+    else
+    {
+      *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
+      *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Returns the horizontal metrics in font units for a given glyph.  If   */
+  /* `check' is true, take care of monospaced fonts by returning the       */
+  /* advance width maximum.                                                */
+  /*                                                                       */
+  static void
+  Get_HMetrics( TT_Face     face,
+                FT_UInt     index,
+                FT_Bool     check,
+                FT_Short*   lsb,
+                FT_UShort*  aw )
+  {
+    TT_Get_Metrics( &face->horizontal, index, lsb, aw );
+
+    if ( check && face->postscript.isFixedPitch )
+      *aw = face->horizontal.advance_Width_Max;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*    Returns the advance width table for a given pixel size if it is    */
+  /*    found in the font's `hdmx' table (if any).                         */
+  /*                                                                       */
+  static FT_Byte*
+  Get_Advance_Widths( TT_Face    face,
+                      FT_UShort  ppem )
+  {
+    FT_UShort  n;
+
+    for ( n = 0; n < face->hdmx.num_records; n++ )
+      if ( face->hdmx.records[n].ppem == ppem )
+        return face->hdmx.records[n].widths;
+
+    return NULL;
+  }
+
+
+#define cur_to_org( n, zone ) \
+          MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( FT_Vector ) )
+
+#define org_to_cur( n, zone ) \
+          MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( FT_Vector ) )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*    Translates an array of coordinates.                                */
+  /*                                                                       */
+  static void
+  translate_array( FT_UInt     n,
+                   FT_Vector*  coords,
+                   FT_Pos      delta_x,
+                   FT_Pos      delta_y )
+  {
+    FT_UInt  k;
+
+
+    if ( delta_x )
+      for ( k = 0; k < n; k++ )
+        coords[k].x += delta_x;
+
+    if ( delta_y )
+      for ( k = 0; k < n; k++ )
+        coords[k].y += delta_y;
+  }
+
+
+  static void
+  tt_prepare_zone( TT_GlyphZone*  zone,
+                   FT_GlyphLoad*  load,
+                   FT_UInt        start_point,
+                   FT_UInt        start_contour )
+  {
+    zone->n_points   = (FT_UShort)( load->outline.n_points - start_point );
+    zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour );
+    zone->org        = load->extra_points + start_point;
+    zone->cur        = load->outline.points + start_point;
+    zone->tags       = (FT_Byte*)load->outline.tags + start_point;
+    zone->contours   = (FT_UShort*)load->outline.contours + start_contour;
+  }
+
+
+#undef  IS_HINTED
+#define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  The following functions are used by default with TrueType fonts.     */
+  /*  However, they can be replaced by alternatives if we need to support  */
+  /*  TrueType-compressed formats (like MicroType) in the future.          */
+  /*                                                                       */
+  /*************************************************************************/
+
+  FT_CALLBACK_DEF( FT_Error )
+  TT_Access_Glyph_Frame( TT_Loader*  loader,
+                         FT_UInt     glyph_index,
+                         FT_ULong    offset,
+                         FT_UInt     byte_count )
+  {
+    FT_Error   error;
+    FT_Stream  stream = loader->stream;
+
+    /* for non-debug mode */
+    FT_UNUSED( glyph_index );
+
+
+    FT_TRACE5(( "Glyph %ld\n", glyph_index ));
+
+    /* the following line sets the `error' variable through macros! */
+    if ( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) )
+      return error;
+
+    return TT_Err_Ok;
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  TT_Forget_Glyph_Frame( TT_Loader*  loader )
+  {
+    FT_Stream  stream = loader->stream;
+
+
+    FORGET_Frame();
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  TT_Load_Glyph_Header( TT_Loader*  loader )
+  {
+    FT_Stream   stream = loader->stream;
+
+
+    loader->n_contours = GET_Short();
+
+    loader->bbox.xMin = GET_Short();
+    loader->bbox.yMin = GET_Short();
+    loader->bbox.xMax = GET_Short();
+    loader->bbox.yMax = GET_Short();
+
+    FT_TRACE5(( "  # of contours: %d\n", loader->n_contours ));
+    FT_TRACE5(( "  xMin: %4d  xMax: %4d\n", loader->bbox.xMin,
+                                            loader->bbox.xMax ));
+    FT_TRACE5(( "  yMin: %4d  yMax: %4d\n", loader->bbox.yMin,
+                                            loader->bbox.yMax ));
+
+    return TT_Err_Ok;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  TT_Load_Simple_Glyph( TT_Loader*  load )
+  {
+    FT_Error         error;
+    FT_Stream        stream     = load->stream;
+    FT_GlyphLoader*  gloader    = load->gloader;
+    FT_Int           n_contours = load->n_contours;
+    FT_Outline*      outline;
+    TT_Face          face    = (TT_Face)load->face;
+    TT_GlyphSlot     slot    = (TT_GlyphSlot)load->glyph;
+    FT_UShort        n_ins;
+    FT_Int           n, n_points;
+
+
+    /* reading the contours endpoints & number of points */
+    {
+      short*  cur   = gloader->current.outline.contours;
+      short*  limit = cur + n_contours;
+
+
+      for ( ; cur < limit; cur++ )
+        cur[0] = GET_UShort();
+
+      n_points = 0;
+      if ( n_contours > 0 )
+        n_points = cur[-1] + 1;
+
+      error = FT_GlyphLoader_Check_Points( gloader, n_points + 2, 0 );
+      if ( error )
+        goto Fail;
+
+      outline = &gloader->current.outline;
+    }
+
+    /* reading the bytecode instructions */
+    slot->control_len  = 0;
+    slot->control_data = 0;
+
+    n_ins = GET_UShort();
+
+    FT_TRACE5(( "  Instructions size: %d\n", n_ins ));
+
+    if ( n_ins > face->max_profile.maxSizeOfInstructions )
+    {
+      FT_TRACE0(( "ERROR: Too many instructions!\n" ));
+      error = TT_Err_Too_Many_Hints;
+      goto Fail;
+    }
+
+    if ( stream->cursor + n_ins > stream->limit )
+    {
+      FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
+      error = TT_Err_Too_Many_Hints;
+      goto Fail;
+    }
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    if ( ( load->load_flags                        &
+         ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
+           load->instructions )
+    {
+      slot->control_len  = n_ins;
+      slot->control_data = load->instructions;
+
+      MEM_Copy( load->instructions, stream->cursor, n_ins );
+    }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    stream->cursor += n_ins;
+
+    /* reading the point tags */
+
+    {
+      FT_Byte*  flag  = (FT_Byte*)outline->tags;
+      FT_Byte*  limit = flag + n_points;
+      FT_Byte   c, count;
+
+
+      for ( ; flag < limit; flag++ )
+      {
+        *flag = c = GET_Byte();
+        if ( c & 8 )
+        {
+          for ( count = GET_Byte(); count > 0; count-- )
+            *++flag = c;
+        }
+      }
+    }
+
+    /* reading the X coordinates */
+
+    {
+      FT_Vector*  vec   = outline->points;
+      FT_Vector*  limit = vec + n_points;
+      FT_Byte*    flag  = (FT_Byte*)outline->tags;
+      FT_Pos      x     = 0;
+
+
+      for ( ; vec < limit; vec++, flag++ )
+      {
+        FT_Pos  y = 0;
+
+
+        if ( *flag & 2 )
+        {
+          y = GET_Byte();
+          if ( ( *flag & 16 ) == 0 )
+            y = -y;
+        }
+        else if ( ( *flag & 16 ) == 0 )
+          y = GET_Short();
+
+        x     += y;
+        vec->x = x;
+      }
+    }
+
+    /* reading the Y coordinates */
+
+    {
+      FT_Vector*  vec   = gloader->current.outline.points;
+      FT_Vector*  limit = vec + n_points;
+      FT_Byte*    flag  = (FT_Byte*)outline->tags;
+      FT_Pos      x     = 0;
+
+
+      for ( ; vec < limit; vec++, flag++ )
+      {
+        FT_Pos  y = 0;
+
+
+        if ( *flag & 4 )
+        {
+          y = GET_Byte();
+          if ( ( *flag & 32 ) == 0 )
+            y = -y;
+        }
+        else if ( ( *flag & 32 ) == 0 )
+          y = GET_Short();
+
+        x     += y;
+        vec->y = x;
+      }
+    }
+
+    /* clear the touch tags */
+    for ( n = 0; n < n_points; n++ )
+      outline->tags[n] &= FT_Curve_Tag_On;
+
+    outline->n_points   = (FT_UShort)n_points;
+    outline->n_contours = (FT_Short) n_contours;
+
+  Fail:
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  TT_Load_Composite_Glyph( TT_Loader*  loader )
+  {
+    FT_Error         error;
+    FT_Stream        stream  = loader->stream;
+    FT_GlyphLoader*  gloader = loader->gloader;
+    FT_SubGlyph*     subglyph;
+    FT_UInt          num_subglyphs;
+
+
+    num_subglyphs = 0;
+
+    do
+    {
+      FT_Fixed  xx, xy, yy, yx;
+
+
+      /* check that we can load a new subglyph */
+      error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs + 1 );
+      if ( error )
+        goto Fail;
+
+      subglyph = gloader->current.subglyphs + num_subglyphs;
+
+      subglyph->arg1 = subglyph->arg2 = 0;
+
+      subglyph->flags = GET_UShort();
+      subglyph->index = GET_UShort();
+
+      /* read arguments */
+      if ( subglyph->flags & ARGS_ARE_WORDS )
+      {
+        subglyph->arg1 = GET_Short();
+        subglyph->arg2 = GET_Short();
+      }
+      else
+      {
+        subglyph->arg1 = GET_Char();
+        subglyph->arg2 = GET_Char();
+      }
+
+      /* read transform */
+      xx = yy = 0x10000L;
+      xy = yx = 0;
+
+      if ( subglyph->flags & WE_HAVE_A_SCALE )
+      {
+        xx = (FT_Fixed)GET_Short() << 2;
+        yy = xx;
+      }
+      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
+      {
+        xx = (FT_Fixed)GET_Short() << 2;
+        yy = (FT_Fixed)GET_Short() << 2;
+      }
+      else if ( subglyph->flags & WE_HAVE_A_2X2 )
+      {
+        xx = (FT_Fixed)GET_Short() << 2;
+        xy = (FT_Fixed)GET_Short() << 2;
+        yx = (FT_Fixed)GET_Short() << 2;
+        yy = (FT_Fixed)GET_Short() << 2;
+      }
+
+      subglyph->transform.xx = xx;
+      subglyph->transform.xy = xy;
+      subglyph->transform.yx = yx;
+      subglyph->transform.yy = yy;
+
+      num_subglyphs++;
+
+    } while ( subglyph->flags & MORE_COMPONENTS );
+
+    gloader->current.num_subglyphs = num_subglyphs;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+    {
+      /* we must undo the ACCESS_Frame in order to point to the */
+      /* composite instructions, if we find some.               */
+      /* we will process them later...                          */
+      /*                                                        */
+      loader->ins_pos = (FT_ULong)( FILE_Pos() +
+                                    stream->cursor - stream->limit );
+    }
+#endif
+
+  Fail:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF void
+  TT_Init_Glyph_Loading( TT_Face  face )
+  {
+    face->access_glyph_frame   = TT_Access_Glyph_Frame;
+    face->read_glyph_header    = TT_Load_Glyph_Header;
+    face->read_simple_glyph    = TT_Load_Simple_Glyph;
+    face->read_composite_glyph = TT_Load_Composite_Glyph;
+    face->forget_glyph_frame   = TT_Forget_Glyph_Frame;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Process_Simple_Glyph                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Once a simple glyph has been loaded, it needs to be processed.     */
+  /*    Usually, this means scaling and hinting through bytecode           */
+  /*    interpretation.                                                    */
+  /*                                                                       */
+  static FT_Error
+  TT_Process_Simple_Glyph( TT_Loader*  load,
+                           FT_Bool     debug )
+  {
+    FT_GlyphLoader*  gloader  = load->gloader;
+    FT_Outline*      outline  = &gloader->current.outline;
+    FT_UInt          n_points = outline->n_points;
+    FT_UInt          n_ins;
+    TT_GlyphZone*    zone     = &load->zone;
+    FT_Error         error    = TT_Err_Ok;
+
+    FT_UNUSED( debug );  /* used by truetype interpreter only */
+
+
+    n_ins = load->glyph->control_len;
+
+    /* add shadow points */
+
+    /* Now add the two shadow points at n and n + 1.    */
+    /* We need the left side bearing and advance width. */
+
+    {
+      FT_Vector*  pp1;
+      FT_Vector*  pp2;
+
+
+      /* pp1 = xMin - lsb */
+      pp1    = outline->points + n_points;
+      pp1->x = load->bbox.xMin - load->left_bearing;
+      pp1->y = 0;
+
+      /* pp2 = pp1 + aw */
+      pp2    = pp1 + 1;
+      pp2->x = pp1->x + load->advance;
+      pp2->y = 0;
+
+      outline->tags[n_points    ] = 0;
+      outline->tags[n_points + 1] = 0;
+    }
+
+    /* Note that we return two more points that are not */
+    /* part of the glyph outline.                       */
+
+    n_points += 2;
+
+    /* set up zone for hinting */
+    tt_prepare_zone( zone, &gloader->current, 0, 0 );
+
+    /* eventually scale the glyph */
+    if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
+    {
+      FT_Vector*  vec     = zone->cur;
+      FT_Vector*  limit   = vec + n_points;
+      FT_Fixed    x_scale = load->size->metrics.x_scale;
+      FT_Fixed    y_scale = load->size->metrics.y_scale;
+
+
+      /* first scale the glyph points */
+      for ( ; vec < limit; vec++ )
+      {
+        vec->x = FT_MulFix( vec->x, x_scale );
+        vec->y = FT_MulFix( vec->y, y_scale );
+      }
+    }
+
+    cur_to_org( n_points, zone );
+
+    /* eventually hint the glyph */
+    if ( IS_HINTED( load->load_flags ) )
+    {
+      FT_Pos  x = zone->org[n_points-2].x;
+
+
+      x = ( ( x + 32 ) & -64 ) - x;
+      translate_array( n_points, zone->org, x, 0 );
+
+      org_to_cur( n_points, zone );
+
+      zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+      /* now consider hinting */
+      if ( n_ins > 0 )
+      {
+        error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
+                                  load->exec->glyphIns, n_ins );
+        if ( error )
+          goto Exit;
+
+        load->exec->is_composite     = FALSE;
+        load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
+                                                  FT_LOAD_PEDANTIC );
+        load->exec->pts              = *zone;
+        load->exec->pts.n_points    += 2;
+
+        error = TT_Run_Context( load->exec, debug );
+        if ( error && load->exec->pedantic_hinting )
+          goto Exit;
+
+        error = TT_Err_Ok;  /* ignore bytecode errors in non-pedantic mode */
+      }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    }
+
+    /* save glyph phantom points */
+    if ( !load->preserve_pps )
+    {
+      load->pp1 = zone->cur[n_points - 2];
+      load->pp2 = zone->cur[n_points - 1];
+    }
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+  Exit:
+#endif
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    load_truetype_glyph                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given truetype glyph.  Handles composites and uses a       */
+  /*    TT_Loader object.                                                  */
+  /*                                                                       */
+  static FT_Error
+  load_truetype_glyph( TT_Loader*  loader,
+                       FT_UInt     glyph_index )
+  {
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+    FT_Stream        stream = loader->stream;
+#endif
+
+    FT_Error         error;
+    TT_Face          face   = (TT_Face)loader->face;
+    FT_ULong         offset;
+    FT_Int           contours_count;
+    FT_UInt          index, num_points, count;
+    FT_Fixed         x_scale, y_scale;
+    FT_GlyphLoader*  gloader = loader->gloader;
+    FT_Bool          opened_frame = 0;
+
+
+    /* check glyph index */
+    index = glyph_index;
+    if ( index >= (FT_UInt)face->root.num_glyphs )
+    {
+      error = TT_Err_Invalid_Glyph_Index;
+      goto Exit;
+    }
+
+    loader->glyph_index = glyph_index;
+    num_points   = 0;
+
+    x_scale = 0x10000L;
+    y_scale = 0x10000L;
+    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+    {
+      x_scale = loader->size->metrics.x_scale;
+      y_scale = loader->size->metrics.y_scale;
+    }
+
+    /* get horizontal metrics */
+    {
+      FT_Short   left_bearing;
+      FT_UShort  advance_width;
+
+
+      Get_HMetrics( face, index,
+                    (FT_Bool)!(loader->load_flags &
+                                FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
+                    &left_bearing,
+                    &advance_width );
+
+      loader->left_bearing = left_bearing;
+      loader->advance      = advance_width;
+
+      if ( !loader->linear_def )
+      {
+        loader->linear_def = 1;
+        loader->linear     = advance_width;
+      }
+    }
+
+    offset = face->glyph_locations[index];
+    count  = 0;
+
+    if ( index < (FT_UInt)face->num_locations - 1 )
+       count = face->glyph_locations[index + 1] - offset;
+
+    if ( count == 0 )
+    {
+      /* as described by Frederic Loyer, these are spaces, and */
+      /* not the unknown glyph.                                */
+      loader->bbox.xMin = 0;
+      loader->bbox.xMax = 0;
+      loader->bbox.yMin = 0;
+      loader->bbox.yMax = 0;
+
+      loader->pp1.x = 0;
+      loader->pp2.x = loader->advance;
+
+      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+      if ( loader->exec )
+        loader->exec->glyphSize = 0;
+
+#endif
+
+      error = TT_Err_Ok;
+      goto Exit;
+    }
+
+    offset = loader->glyf_offset + offset;
+
+    /* access glyph frame */
+    error = face->access_glyph_frame( loader, glyph_index, offset, count );
+    if ( error )
+      goto Exit;
+
+    opened_frame = 1;
+
+    /* read first glyph header */
+    error = face->read_glyph_header( loader );
+    if ( error )
+      goto Fail;
+
+    contours_count = loader->n_contours;
+
+    count -= 10;
+
+    loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
+    loader->pp1.y = 0;
+    loader->pp2.x = loader->pp1.x + loader->advance;
+    loader->pp2.y = 0;
+
+    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+    {
+      loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
+      loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+    }
+
+    /***********************************************************************/
+    /***********************************************************************/
+    /***********************************************************************/
+
+    /* if it is a simple glyph, load it */
+
+    if ( contours_count >= 0 )
+    {
+      /* check that we can add the contours to the glyph */
+      error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count );
+      if ( error )
+        goto Fail;
+
+      error = face->read_simple_glyph( loader );
+      if ( error )
+        goto Fail;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+      {
+        TT_Size size = (TT_Size)loader->size;
+
+
+        error = TT_Process_Simple_Glyph( loader,
+                                         (FT_Bool)( size && size->debug ) );
+      }
+
+#else
+
+      error = TT_Process_Simple_Glyph( loader, 0 );
+
+#endif
+
+      if ( error )
+        goto Fail;
+
+      FT_GlyphLoader_Add( gloader );
+
+      /* Note: We could have put the simple loader source there */
+      /*       but the code is fat enough already :-)           */
+    }
+
+    /***********************************************************************/
+    /***********************************************************************/
+    /***********************************************************************/
+
+    /* otherwise, load a composite! */
+    else
+    {
+      TT_GlyphSlot  glyph = (TT_GlyphSlot)loader->glyph;
+      FT_UInt       start_point, start_contour;
+      FT_ULong      ins_pos;  /* position of composite instructions, if any */
+
+
+      /* for each subglyph, read composite header */
+      start_point   = gloader->base.outline.n_points;
+      start_contour = gloader->base.outline.n_contours;
+
+      error = face->read_composite_glyph( loader );
+      if ( error )
+        goto Fail;
+
+      ins_pos = loader->ins_pos;
+      face->forget_glyph_frame( loader );
+      opened_frame = 0;
+
+      /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
+      /* `as is' in the glyph slot (the client application will be     */
+      /* responsible for interpreting this data)...                    */
+      /*                                                               */
+      if ( loader->load_flags & FT_LOAD_NO_RECURSE )
+      {
+        /* set up remaining glyph fields */
+        FT_GlyphLoader_Add( gloader );
+
+        glyph->num_subglyphs  = gloader->base.num_subglyphs;
+        glyph->format         = ft_glyph_format_composite;
+        glyph->subglyphs      = gloader->base.subglyphs;
+
+        goto Exit;
+      }
+
+      /*********************************************************************/
+      /*********************************************************************/
+      /*********************************************************************/
+
+      /* Now, read each subglyph independently. */
+      {
+        FT_Int        n, num_base_points, num_new_points;
+        FT_SubGlyph*  subglyph = 0;
+
+        FT_UInt num_subglyphs  = gloader->current.num_subglyphs;
+        FT_UInt num_base_subgs = gloader->base.num_subglyphs;
+
+
+        FT_GlyphLoader_Add( gloader );
+
+        for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
+        {
+          FT_Vector  pp1, pp2;
+          FT_Pos     x, y;
+
+
+          /* Each time we call load_truetype_glyph in this loop, the   */
+          /* value of `gloader.base.subglyphs' can change due to table */
+          /* reallocations.  We thus need to recompute the subglyph    */
+          /* pointer on each iteration.                                */
+          subglyph = gloader->base.subglyphs + num_base_subgs + n;
+
+          pp1 = loader->pp1;
+          pp2 = loader->pp2;
+
+          num_base_points = gloader->base.outline.n_points;
+
+          error = load_truetype_glyph( loader, subglyph->index );
+          if ( error )
+            goto Fail;
+
+          /* restore subglyph pointer */
+          subglyph = gloader->base.subglyphs + num_base_subgs + n;
+
+          if ( subglyph->flags & USE_MY_METRICS )
+          {
+            pp1 = loader->pp1;
+            pp2 = loader->pp2;
+          }
+          else
+          {
+            loader->pp1 = pp1;
+            loader->pp2 = pp2;
+          }
+
+          num_points = gloader->base.outline.n_points;
+
+          num_new_points = num_points - num_base_points;
+
+          /* now perform the transform required for this subglyph */
+
+          if ( subglyph->flags & ( WE_HAVE_A_SCALE     |
+                                   WE_HAVE_AN_XY_SCALE |
+                                   WE_HAVE_A_2X2       ) )
+          {
+            FT_Vector*  cur   = gloader->base.outline.points +
+                                  num_base_points;
+            FT_Vector*  org   = gloader->base.extra_points +
+                                  num_base_points;
+            FT_Vector*  limit = cur + num_new_points;
+
+
+            for ( ; cur < limit; cur++, org++ )
+            {
+              FT_Vector_Transform( cur, &subglyph->transform );
+              FT_Vector_Transform( org, &subglyph->transform );
+            }
+          }
+
+          /* apply offset */
+
+          if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
+          {
+            FT_UInt     k = subglyph->arg1;
+            FT_UInt     l = subglyph->arg2;
+            FT_Vector*  p1;
+            FT_Vector*  p2;
+
+
+            if ( start_point + k >= (FT_UInt)num_base_points ||
+                               l >= (FT_UInt)num_new_points  )
+            {
+              error = TT_Err_Invalid_Composite;
+              goto Fail;
+            }
+
+            l += num_base_points;
+
+            p1 = gloader->base.outline.points + start_point + k;
+            p2 = gloader->base.outline.points + start_point + l;
+
+            x = p1->x - p2->x;
+            y = p1->y - p2->y;
+          }
+          else
+          {
+            x = subglyph->arg1;
+            y = subglyph->arg2;
+
+            if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
+            {
+              x = FT_MulFix( x, x_scale );
+              y = FT_MulFix( y, y_scale );
+
+              if ( subglyph->flags & ROUND_XY_TO_GRID )
+              {
+                x = ( x + 32 ) & -64;
+                y = ( y + 32 ) & -64;
+              }
+            }
+          }
+
+          if ( x | y )
+          {
+            translate_array( num_new_points,
+                             gloader->base.outline.points + num_base_points,
+                             x, y );
+
+            translate_array( num_new_points,
+                             gloader->base.extra_points + num_base_points,
+                             x, y );
+          }
+        }
+
+        /*******************************************************************/
+        /*******************************************************************/
+        /*******************************************************************/
+
+        /* we have finished loading all sub-glyphs; now, look for */
+        /* instructions for this composite!                       */
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+        if ( num_subglyphs > 0               &&
+             loader->exec                    &&
+             ins_pos         > 0             &&
+             subglyph->flags & WE_HAVE_INSTR )
+        {
+          FT_UShort       n_ins;
+          TT_ExecContext  exec = loader->exec;
+          TT_GlyphZone*   pts;
+          FT_Vector*      pp1;
+
+
+          /* read size of instructions */
+          if ( FILE_Seek( ins_pos ) ||
+               READ_UShort( n_ins ) )
+            goto Fail;
+          FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
+
+          /* in some fonts? */
+          if ( n_ins == 0xFFFF )
+            n_ins = 0;
+
+          /* check it */
+          if ( n_ins > face->max_profile.maxSizeOfInstructions )
+          {
+            FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
+                        n_ins, subglyph->index ));
+            return TT_Err_Too_Many_Hints;
+          }
+
+          /* read the instructions */
+          if ( FILE_Read( exec->glyphIns, n_ins ) )
+            goto Fail;
+
+          glyph->control_data = exec->glyphIns;
+          glyph->control_len  = n_ins;
+
+          error = TT_Set_CodeRange( exec,
+                                    tt_coderange_glyph,
+                                    exec->glyphIns,
+                                    n_ins );
+          if ( error )
+            goto Fail;
+
+          /* prepare the execution context */
+          tt_prepare_zone( &exec->pts, &gloader->base,
+                           start_point, start_contour );
+          pts = &exec->pts;
+
+          pts->n_points   = (short)(num_points + 2);
+          pts->n_contours = gloader->base.outline.n_contours;
+
+          /* add phantom points */
+          pp1    = pts->cur + num_points;
+          pp1[0] = loader->pp1;
+          pp1[1] = loader->pp2;
+
+          pts->tags[num_points    ] = 0;
+          pts->tags[num_points + 1] = 0;
+
+          /* if hinting, round the phantom points */
+          if ( IS_HINTED( loader->load_flags ) )
+          {
+            pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 );
+            pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 );
+          }
+
+          {
+            FT_UInt  k;
+
+
+            for ( k = 0; k < num_points; k++ )
+              pts->tags[k] &= FT_Curve_Tag_On;
+          }
+
+          cur_to_org( num_points + 2, pts );
+
+          /* now consider hinting */
+          if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
+          {
+            exec->is_composite     = TRUE;
+            exec->pedantic_hinting =
+              (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC );
+
+            error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
+            if ( error && exec->pedantic_hinting )
+              goto Fail;
+          }
+
+          /* save glyph origin and advance points */
+          loader->pp1 = pp1[0];
+          loader->pp2 = pp1[1];
+        }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+      }
+      /* end of composite loading */
+    }
+
+    /***********************************************************************/
+    /***********************************************************************/
+    /***********************************************************************/
+
+  Fail:
+    if ( opened_frame )
+      face->forget_glyph_frame( loader );
+
+  Exit:
+    return error;
+  }
+
+
+  static void
+  compute_glyph_metrics( TT_Loader*  loader,
+                         FT_UInt     glyph_index )
+  {
+    FT_BBox       bbox;
+    TT_Face       face = (TT_Face)loader->face;
+    FT_Fixed      y_scale;
+    TT_GlyphSlot  glyph = loader->glyph;
+    TT_Size       size = (TT_Size)loader->size;
+
+
+    y_scale = 0x10000L;
+    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+      y_scale = size->root.metrics.y_scale;
+
+    if ( glyph->format != ft_glyph_format_composite )
+    {
+      glyph->outline.flags &= ~ft_outline_single_pass;
+
+      /* copy outline to our glyph slot */
+      FT_GlyphLoader_Copy_Points( glyph->internal->loader, loader->gloader );
+      glyph->outline = glyph->internal->loader->base.outline;
+
+      /* translate array so that (0,0) is the glyph's origin */
+      FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
+
+      FT_Outline_Get_CBox( &glyph->outline, &bbox );
+
+      if ( IS_HINTED( loader->load_flags ) )
+      {
+        /* grid-fit the bounding box */
+        bbox.xMin &= -64;
+        bbox.yMin &= -64;
+        bbox.xMax  = ( bbox.xMax + 63 ) & -64;
+        bbox.yMax  = ( bbox.yMax + 63 ) & -64;
+      }
+    }
+    else
+      bbox = loader->bbox;
+
+    /* get the device-independent horizontal advance.  It is scaled later */
+    /* by the base layer.                                                 */
+    {
+      FT_Pos  advance = loader->linear;
+
+
+      /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
+      /* correctly support DynaLab fonts, which have an incorrect       */
+      /* `advance_Width_Max' field!  It is used, to my knowledge,       */
+      /* exclusively in the X-TrueType font server.                     */
+      /*                                                                */
+      if ( face->postscript.isFixedPitch                                    &&
+           ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
+        advance = face->horizontal.advance_Width_Max;
+
+      /* we need to return the advance in font units in linearHoriAdvance, */
+      /* it will be scaled later by the base layer.                        */
+      glyph->linearHoriAdvance = advance;
+    }
+
+    glyph->metrics.horiBearingX = bbox.xMin;
+    glyph->metrics.horiBearingY = bbox.yMax;
+    glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
+
+    /* Now take care of vertical metrics.  In the case where there is    */
+    /* no vertical information within the font (relatively common), make */
+    /* up some metrics by `hand'...                                      */
+
+    {
+      FT_Short   top_bearing;    /* vertical top side bearing (EM units) */
+      FT_UShort  advance_height; /* vertical advance height   (EM units) */
+
+      FT_Pos  left;     /* scaled vertical left side bearing         */
+      FT_Pos  top;      /* scaled vertical top side bearing          */
+      FT_Pos  advance;  /* scaled vertical advance height            */
+
+
+      /* Get the unscaled `tsb' and `ah' */
+      if ( face->vertical_info                   &&
+           face->vertical.number_Of_VMetrics > 0 )
+      {
+        /* Don't assume that both the vertical header and vertical */
+        /* metrics are present in the same font :-)                */
+
+        TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
+                        glyph_index,
+                        &top_bearing,
+                        &advance_height );
+      }
+      else
+      {
+        /* Make up the distances from the horizontal header.   */
+
+        /* NOTE: The OS/2 values are the only `portable' ones, */
+        /*       which is why we use them, if there is an OS/2 */
+        /*       table in the font.  Otherwise, we use the     */
+        /*       values defined in the horizontal header.      */
+        /*                                                     */
+        /* NOTE2: The sTypoDescender is negative, which is why */
+        /*        we compute the baseline-to-baseline distance */
+        /*        here with:                                   */
+        /*             ascender - descender + linegap          */
+        /*                                                     */
+        if ( face->os2.version != 0xFFFF )
+        {
+          top_bearing    = (FT_Short)( face->os2.sTypoLineGap / 2 );
+          advance_height = (FT_UShort)( face->os2.sTypoAscender -
+                                        face->os2.sTypoDescender +
+                                        face->os2.sTypoLineGap );
+        }
+        else
+        {
+          top_bearing    = (FT_Short)( face->horizontal.Line_Gap / 2 );
+          advance_height = (FT_UShort)( face->horizontal.Ascender  +
+                                        face->horizontal.Descender +
+                                        face->horizontal.Line_Gap );
+        }
+      }
+
+      /* We must adjust the top_bearing value from the bounding box given */
+      /* in the glyph header to te bounding box calculated with           */
+      /* FT_Get_Outline_CBox().                                           */
+
+      /* scale the metrics */
+      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
+      {
+        top     = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
+                    - bbox.yMax;
+        advance = FT_MulFix( advance_height, y_scale );
+      }
+      else
+      {
+        top     = top_bearing + loader->bbox.yMax - bbox.yMax;
+        advance = advance_height;
+      }
+
+      /* set the advance height in design units.  It is scaled later by */
+      /* the base layer.                                                */
+      glyph->linearVertAdvance = advance_height;
+
+      /* XXX: for now, we have no better algorithm for the lsb, but it */
+      /*      should work fine.                                        */
+      /*                                                               */
+      left = ( bbox.xMin - bbox.xMax ) / 2;
+
+      /* grid-fit them if necessary */
+      if ( IS_HINTED( loader->load_flags ) )
+      {
+        left   &= -64;
+        top     = ( top + 63     ) & -64;
+        advance = ( advance + 32 ) & -64;
+      }
+
+      glyph->metrics.vertBearingX = left;
+      glyph->metrics.vertBearingY = top;
+      glyph->metrics.vertAdvance  = advance;
+    }
+
+    /* adjust advance width to the value contained in the hdmx table */
+    if ( !face->postscript.isFixedPitch && size &&
+         IS_HINTED( loader->load_flags )        )
+    {
+      FT_Byte* widths = Get_Advance_Widths( face,
+                                            size->root.metrics.x_ppem );
+
+
+      if ( widths )
+        glyph->metrics.horiAdvance = widths[glyph_index] << 6;
+    }
+
+    /* set glyph dimensions */
+    glyph->metrics.width  = bbox.xMax - bbox.xMin;
+    glyph->metrics.height = bbox.yMax - bbox.yMin;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    A function used to load a single glyph within a given glyph slot,  */
+  /*    for a given size.                                                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph       :: A handle to a target slot object where the glyph    */
+  /*                   will be loaded.                                     */
+  /*                                                                       */
+  /*    size        :: A handle to the source face size at which the glyph */
+  /*                   must be scaled/loaded.                              */
+  /*                                                                       */
+  /*    glyph_index :: The index of the glyph in the font file.            */
+  /*                                                                       */
+  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
+  /*                   FT_LOAD_XXX constants can be used to control the    */
+  /*                   glyph loading process (e.g., whether the outline    */
+  /*                   should be scaled, whether to load bitmaps or not,   */
+  /*                   whether to hint the outline, etc).                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Glyph( TT_Size       size,
+                 TT_GlyphSlot  glyph,
+                 FT_UShort     glyph_index,
+                 FT_UInt       load_flags )
+  {
+    SFNT_Interface*  sfnt;
+    TT_Face          face;
+    FT_Stream        stream;
+    FT_Error         error;
+    TT_Loader        loader;
+
+
+    face   = (TT_Face)glyph->face;
+    sfnt   = (SFNT_Interface*)face->sfnt;
+    stream = face->root.stream;
+    error  = 0;
+
+    if ( !size || ( load_flags & FT_LOAD_NO_SCALE )   ||
+                  ( load_flags & FT_LOAD_NO_RECURSE ) )
+    {
+      size        = NULL;
+      load_flags |= FT_LOAD_NO_SCALE   |
+                    FT_LOAD_NO_HINTING |
+                    FT_LOAD_NO_BITMAP;
+    }
+
+    glyph->num_subglyphs = 0;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    /* try to load embedded bitmap if any              */
+    /*                                                 */
+    /* XXX: The convention should be emphasized in     */
+    /*      the documents because it can be confusing. */
+    if ( size                                    &&
+         size->strike_index != 0xFFFF            &&
+         sfnt->load_sbits                        &&
+         ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
+
+    {
+      TT_SBit_Metrics  metrics;
+
+
+      error = sfnt->load_sbit_image( face,
+                                     size->strike_index,
+                                     glyph_index,
+                                     load_flags,
+                                     stream,
+                                     &glyph->bitmap,
+                                     &metrics );
+      if ( !error )
+      {
+        glyph->outline.n_points   = 0;
+        glyph->outline.n_contours = 0;
+
+        glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
+        glyph->metrics.height = (FT_Pos)metrics.height << 6;
+
+        glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
+        glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
+        glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
+
+        glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
+        glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
+        glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
+
+        glyph->format = ft_glyph_format_bitmap;
+        if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+        {
+          glyph->bitmap_left = metrics.vertBearingX;
+          glyph->bitmap_top  = metrics.vertBearingY;
+        }
+        else
+        {
+          glyph->bitmap_left = metrics.horiBearingX;
+          glyph->bitmap_top  = metrics.horiBearingY;
+        }
+        return error;
+      }
+    }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    /* seek to the beginning of the glyph table.  For Type 42 fonts      */
+    /* the table might be accessed from a Postscript stream or something */
+    /* else...                                                           */
+
+    error = face->goto_table( face, TTAG_glyf, stream, 0 );
+    if ( error )
+    {
+      FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
+      goto Exit;
+    }
+
+    MEM_Set( &loader, 0, sizeof ( loader ) );
+
+    /* update the glyph zone bounds */
+    {
+      FT_GlyphLoader*  gloader = FT_FACE_DRIVER(face)->glyph_loader;
+
+
+      loader.gloader = gloader;
+
+      FT_GlyphLoader_Rewind( gloader );
+
+      tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
+      tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
+    }
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    if ( size )
+    {
+      /* query new execution context */
+      loader.exec = size->debug ? size->context : TT_New_Context( face );
+      if ( !loader.exec )
+        return TT_Err_Could_Not_Find_Context;
+
+      TT_Load_Context( loader.exec, face, size );
+      loader.instructions = loader.exec->glyphIns;
+
+      /* load default graphics state - if needed */
+      if ( size->GS.instruct_control & 2 )
+        loader.exec->GS = tt_default_graphics_state;
+    }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    /* clear all outline flags, except the `owner' one */
+    glyph->outline.flags = 0;
+
+    if ( size && size->root.metrics.y_ppem < 24 )
+      glyph->outline.flags |= ft_outline_high_precision;
+
+    /* let's initialize the rest of our loader now */
+
+    loader.load_flags    = load_flags;
+
+    loader.face   = (FT_Face)face;
+    loader.size   = (FT_Size)size;
+    loader.glyph  = (FT_GlyphSlot)glyph;
+    loader.stream = stream;
+
+    loader.glyf_offset  = FILE_Pos();
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    /* if the cvt program has disabled hinting, the argument */
+    /* is ignored.                                           */
+    if ( size && ( size->GS.instruct_control & 1 ) )
+      loader.load_flags |= FT_LOAD_NO_HINTING;
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    /* Main loading loop */
+    glyph->format        = ft_glyph_format_outline;
+    glyph->num_subglyphs = 0;
+    error = load_truetype_glyph( &loader, glyph_index );
+    if ( !error )
+      compute_glyph_metrics( &loader, glyph_index );
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    if ( !size || !size->debug )
+      TT_Done_Context( loader.exec );
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ttinterp.c b/libraries/freetype-2.0.5/ttinterp.c
new file mode 100644 (file)
index 0000000..9748e9a
--- /dev/null
@@ -0,0 +1,7397 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttinterp.c                                                             */
+/*                                                                         */
+/*    TrueType bytecode interpreter (body).                                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_TRIGONOMETRY_H
+#include FT_SYSTEM_H
+
+#include "ttinterp.h"
+
+#include "tterrors.h"
+
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+
+#define TT_MULFIX  FT_MulFix
+#define TT_MULDIV  FT_MulDiv
+#define TT_INT64   FT_Int64
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttinterp
+
+#undef  NO_APPLE_PATENT
+#define APPLE_THRESHOLD  0x4000000L
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* In order to detect infinite loops in the code, we set up a counter    */
+  /* within the run loop.  A single stroke of interpretation is now        */
+  /* limitet to a maximal number of opcodes defined below.                 */
+  /*                                                                       */
+#define MAX_RUNNABLE_OPCODES  1000000L
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* There are two kinds of implementations:                               */
+  /*                                                                       */
+  /* a. static implementation                                              */
+  /*                                                                       */
+  /*    The current execution context is a static variable, which fields   */
+  /*    are accessed directly by the interpreter during execution.  The    */
+  /*    context is named `cur'.                                            */
+  /*                                                                       */
+  /*    This version is non-reentrant, of course.                          */
+  /*                                                                       */
+  /* b. indirect implementation                                            */
+  /*                                                                       */
+  /*    The current execution context is passed to _each_ function as its  */
+  /*    first argument, and each field is thus accessed indirectly.        */
+  /*                                                                       */
+  /*    This version is fully re-entrant.                                  */
+  /*                                                                       */
+  /* The idea is that an indirect implementation may be slower to execute  */
+  /* on low-end processors that are used in some systems (like 386s or     */
+  /* even 486s).                                                           */
+  /*                                                                       */
+  /* As a consequence, the indirect implementation is now the default, as  */
+  /* its performance costs can be considered negligible in our context.    */
+  /* Note, however, that we kept the same source with macros because:      */
+  /*                                                                       */
+  /* - The code is kept very close in design to the Pascal code used for   */
+  /*   development.                                                        */
+  /*                                                                       */
+  /* - It's much more readable that way!                                   */
+  /*                                                                       */
+  /* - It's still open to experimentation and tuning.                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER     /* indirect implementation */
+
+#define CUR  (*exc)                             /* see ttobjs.h */
+
+#else                                           /* static implementation */
+
+#define CUR  cur
+
+  static
+  TT_ExecContextRec  cur;   /* static exec. context variable */
+
+  /* apparently, we have a _lot_ of direct indexing when accessing  */
+  /* the static `cur', which makes the code bigger (due to all the  */
+  /* four bytes addresses).                                         */
+
+#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The instruction argument stack.                                       */
+  /*                                                                       */
+#define INS_ARG  EXEC_OP_ FT_Long*  args    /* see ttobjs.h for EXEC_OP_ */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This macro is used whenever `exec' is unused in a function, to avoid  */
+  /* stupid warnings from pedantic compilers.                              */
+  /*                                                                       */
+#define FT_UNUSED_EXEC  FT_UNUSED( CUR )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This macro is used whenever `args' is unused in a function, to avoid  */
+  /* stupid warnings from pedantic compilers.                              */
+  /*                                                                       */
+#define FT_UNUSED_ARG  FT_UNUSED_EXEC; FT_UNUSED( args )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to        */
+  /* increase readabilty of the code.                                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define SKIP_Code() \
+          SkipCode( EXEC_ARG )
+
+#define GET_ShortIns() \
+          GetShortIns( EXEC_ARG )
+
+#define NORMalize( x, y, v ) \
+          Normalize( EXEC_ARG_ x, y, v )
+
+#define SET_SuperRound( scale, flags ) \
+          SetSuperRound( EXEC_ARG_ scale, flags )
+
+#define ROUND_None( d, c ) \
+          Round_None( EXEC_ARG_ d, c )
+
+#define INS_Goto_CodeRange( range, ip ) \
+          Ins_Goto_CodeRange( EXEC_ARG_ range, ip )
+
+#define CUR_Func_project( x, y ) \
+          CUR.func_project( EXEC_ARG_ x, y )
+
+#define CUR_Func_move( z, p, d ) \
+          CUR.func_move( EXEC_ARG_ z, p, d )
+
+#define CUR_Func_dualproj( x, y ) \
+          CUR.func_dualproj( EXEC_ARG_ x, y )
+
+#define CUR_Func_freeProj( x, y ) \
+          CUR.func_freeProj( EXEC_ARG_ x, y )
+
+#define CUR_Func_round( d, c ) \
+          CUR.func_round( EXEC_ARG_ d, c )
+
+#define CUR_Func_read_cvt( index ) \
+          CUR.func_read_cvt( EXEC_ARG_ index )
+
+#define CUR_Func_write_cvt( index, val ) \
+          CUR.func_write_cvt( EXEC_ARG_ index, val )
+
+#define CUR_Func_move_cvt( index, val ) \
+          CUR.func_move_cvt( EXEC_ARG_ index, val )
+
+#define CURRENT_Ratio() \
+          Current_Ratio( EXEC_ARG )
+
+#define CURRENT_Ppem() \
+          Current_Ppem( EXEC_ARG )
+
+#define CUR_Ppem() \
+          Cur_PPEM( EXEC_ARG )
+
+#define INS_SxVTL( a, b, c, d ) \
+          Ins_SxVTL( EXEC_ARG_ a, b, c, d )
+
+#define COMPUTE_Funcs() \
+          Compute_Funcs( EXEC_ARG )
+
+#define COMPUTE_Round( a ) \
+          Compute_Round( EXEC_ARG_ a )
+
+#define COMPUTE_Point_Displacement( a, b, c, d ) \
+          Compute_Point_Displacement( EXEC_ARG_ a, b, c, d )
+
+#define MOVE_Zp2_Point( a, b, c, t ) \
+          Move_Zp2_Point( EXEC_ARG_ a, b, c, t )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Instruction dispatch function, as used by the interpreter.            */
+  /*                                                                       */
+  typedef void  (*TInstruction_Function)( INS_ARG );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A simple bounds-checking macro.                                       */
+  /*                                                                       */
+#define BOUNDS( x, n )  ( (FT_UInt)(x) >= (FT_UInt)(n) )
+
+
+#undef  SUCCESS
+#define SUCCESS  0
+
+#undef  FAILURE
+#define FAILURE  1
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                        CODERANGE FUNCTIONS                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Goto_CodeRange                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Switches to a new code range (updates the code related elements in */
+  /*    `exec', and `IP').                                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range :: The new execution code range.                             */
+  /*                                                                       */
+  /*    IP    :: The new IP in the new code range.                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    exec  :: The target execution context.                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Goto_CodeRange( TT_ExecContext  exec,
+                     FT_Int          range,
+                     FT_Long         IP )
+  {
+    TT_CodeRange*  coderange;
+
+
+    FT_Assert( range >= 1 && range <= 3 );
+
+    coderange = &exec->codeRangeTable[range - 1];
+
+    FT_Assert( coderange->base != NULL );
+
+    /* NOTE: Because the last instruction of a program may be a CALL */
+    /*       which will return to the first byte *after* the code    */
+    /*       range, we test for IP <= Size instead of IP < Size.     */
+    /*                                                               */
+    FT_Assert( (FT_ULong)IP <= coderange->size );
+
+    exec->code     = coderange->base;
+    exec->codeSize = coderange->size;
+    exec->IP       = IP;
+    exec->curRange = range;
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Set_CodeRange                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets a code range.                                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range  :: The code range index.                                    */
+  /*                                                                       */
+  /*    base   :: The new code base.                                       */
+  /*                                                                       */
+  /*    length :: The range size in bytes.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    exec   :: The target execution context.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Set_CodeRange( TT_ExecContext  exec,
+                    FT_Int          range,
+                    void*           base,
+                    FT_Long         length )
+  {
+    FT_Assert( range >= 1 && range <= 3 );
+
+    exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
+    exec->codeRangeTable[range - 1].size = length;
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Clear_CodeRange                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Clears a code range.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range :: The code range index.                                     */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    exec  :: The target execution context.                             */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Does not set the Error variable.                                   */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Clear_CodeRange( TT_ExecContext  exec,
+                      FT_Int          range )
+  {
+    FT_Assert( range >= 1 && range <= 3 );
+
+    exec->codeRangeTable[range - 1].base = NULL;
+    exec->codeRangeTable[range - 1].size = 0;
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                   EXECUTION CONTEXT ROUTINES                          */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Destroy_Context                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Destroys a given context.                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    exec   :: A handle to the target execution context.                */
+  /*                                                                       */
+  /*    memory :: A handle to the parent memory object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Destroy_Context( TT_ExecContext  exec,
+                      FT_Memory       memory )
+  {
+    /* free composite load stack */
+    FREE( exec->loadStack );
+    exec->loadSize = 0;
+
+    /* points zone */
+    exec->maxPoints   = 0;
+    exec->maxContours = 0;
+
+    /* free stack */
+    FREE( exec->stack );
+    exec->stackSize = 0;
+
+    /* free call stack */
+    FREE( exec->callStack );
+    exec->callSize = 0;
+    exec->callTop  = 0;
+
+    /* free glyph code range */
+    FREE( exec->glyphIns );
+    exec->glyphSize = 0;
+
+    exec->size = NULL;
+    exec->face = NULL;
+
+    FREE( exec );
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Init_Context                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a context object.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory :: A handle to the parent memory object.                    */
+  /*                                                                       */
+  /*    face   :: A handle to the source TrueType face object.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    exec   :: A handle to the target execution context.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  Init_Context( TT_ExecContext  exec,
+                TT_Face         face,
+                FT_Memory       memory )
+  {
+    FT_Error  error;
+
+
+    FT_TRACE1(( "Init_Context: new object at 0x%08p, parent = 0x%08p\n",
+                exec, face ));
+
+    exec->memory   = memory;
+    exec->callSize = 32;
+
+    if ( ALLOC_ARRAY( exec->callStack, exec->callSize, TT_CallRec ) )
+      goto Fail_Memory;
+
+    /* all values in the context are set to 0 already, but this is */
+    /* here as a remainder                                         */
+    exec->maxPoints   = 0;
+    exec->maxContours = 0;
+
+    exec->stackSize = 0;
+    exec->loadSize  = 0;
+    exec->glyphSize = 0;
+
+    exec->stack     = NULL;
+    exec->loadStack = NULL;
+    exec->glyphIns  = NULL;
+
+    exec->face = face;
+    exec->size = NULL;
+
+    return TT_Err_Ok;
+
+  Fail_Memory:
+    FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
+               (FT_Long)exec ));
+    TT_Destroy_Context( exec, memory );
+
+    return error;
+ }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Update_Max                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Checks the size of a buffer and reallocates it if necessary.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory     :: A handle to the parent memory object.                */
+  /*                                                                       */
+  /*    multiplier :: The size in bytes of each element in the buffer.     */
+  /*                                                                       */
+  /*    new_max    :: The new capacity (size) of the buffer.               */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size       :: The address of the buffer's current size expressed   */
+  /*                  in elements.                                         */
+  /*                                                                       */
+  /*    buff       :: The address of the buffer base pointer.              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  Update_Max( FT_Memory  memory,
+              FT_ULong*  size,
+              FT_Long    multiplier,
+              void**     buff,
+              FT_ULong   new_max )
+  {
+    FT_Error  error;
+
+
+    if ( *size < new_max )
+    {
+      FREE( *buff );
+      if ( ALLOC( *buff, new_max * multiplier ) )
+        return error;
+      *size = new_max;
+    }
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Context                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Prepare an execution context for glyph hinting.                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the source face object.                        */
+  /*                                                                       */
+  /*    size :: A handle to the source size object.                        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    exec :: A handle to the target execution context.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Context( TT_ExecContext  exec,
+                   TT_Face         face,
+                   TT_Size         size )
+  {
+    FT_Int          i;
+    FT_ULong        tmp;
+    TT_MaxProfile*  maxp;
+    FT_Error        error;
+
+
+    exec->face = face;
+    maxp       = &face->max_profile;
+    exec->size = size;
+
+    if ( size )
+    {
+      exec->numFDefs   = size->num_function_defs;
+      exec->maxFDefs   = size->max_function_defs;
+      exec->numIDefs   = size->num_instruction_defs;
+      exec->maxIDefs   = size->max_instruction_defs;
+      exec->FDefs      = size->function_defs;
+      exec->IDefs      = size->instruction_defs;
+      exec->tt_metrics = size->ttmetrics;
+      exec->metrics    = size->root.metrics;
+
+      exec->maxFunc    = size->max_func;
+      exec->maxIns     = size->max_ins;
+
+      for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
+        exec->codeRangeTable[i] = size->codeRangeTable[i];
+
+      /* set graphics state */
+      exec->GS = size->GS;
+
+      exec->cvtSize = size->cvt_size;
+      exec->cvt     = size->cvt;
+
+      exec->storeSize = size->storage_size;
+      exec->storage   = size->storage;
+
+      exec->twilight  = size->twilight;
+    }
+
+    error = Update_Max( exec->memory,
+                        &exec->loadSize,
+                        sizeof ( TT_SubGlyphRec ),
+                        (void**)&exec->loadStack,
+                        exec->face->max_components + 1 );
+    if ( error )
+      return error;
+
+    /* XXX: We reserve a little more elements on the stack to deal safely */
+    /*      with broken fonts like arialbs, courbs, timesbs, etc.         */
+    tmp = exec->stackSize;
+    error = Update_Max( exec->memory,
+                        &tmp,
+                        sizeof ( FT_F26Dot6 ),
+                        (void**)&exec->stack,
+                        maxp->maxStackElements + 32 );
+    exec->stackSize = (FT_UInt)tmp;
+    if ( error )
+      return error;
+
+    tmp = exec->glyphSize;
+    error = Update_Max( exec->memory,
+                        &tmp,
+                        sizeof ( FT_Byte ),
+                        (void**)&exec->glyphIns,
+                        maxp->maxSizeOfInstructions );
+    exec->glyphSize = (FT_UShort)tmp;
+    if ( error )
+      return error;
+
+    exec->pts.n_points   = 0;
+    exec->pts.n_contours = 0;
+
+    exec->instruction_trap = FALSE;
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Save_Context                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Saves the code ranges in a `size' object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    exec :: A handle to the source execution context.                  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Save_Context( TT_ExecContext  exec,
+                   TT_Size         size )
+  {
+    FT_Int  i;
+
+
+    /* XXXX: Will probably disappear soon with all the code range */
+    /*       management, which is now rather obsolete.            */
+    /*                                                            */
+    size->num_function_defs    = exec->numFDefs;
+    size->num_instruction_defs = exec->numIDefs;
+
+    size->max_func = exec->maxFunc;
+    size->max_ins  = exec->maxIns;
+
+    for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
+      size->codeRangeTable[i] = exec->codeRangeTable[i];
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Run_Context                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Executes one or more instructions in the execution context.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    debug :: A Boolean flag.  If set, the function sets some internal  */
+  /*             variables and returns immediately, otherwise TT_RunIns()  */
+  /*             is called.                                                */
+  /*                                                                       */
+  /*             This is commented out currently.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    exec  :: A handle to the target execution context.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    TrueTyoe error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Run_Context( TT_ExecContext  exec,
+                  FT_Bool         debug )
+  {
+    FT_Error  error;
+
+
+    if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0  ) )
+           != TT_Err_Ok )
+      return error;
+
+    exec->zp0 = exec->pts;
+    exec->zp1 = exec->pts;
+    exec->zp2 = exec->pts;
+
+    exec->GS.gep0 = 1;
+    exec->GS.gep1 = 1;
+    exec->GS.gep2 = 1;
+
+    exec->GS.projVector.x = 0x4000;
+    exec->GS.projVector.y = 0x0000;
+
+    exec->GS.freeVector = exec->GS.projVector;
+    exec->GS.dualVector = exec->GS.projVector;
+
+    exec->GS.round_state = 1;
+    exec->GS.loop        = 1;
+
+    /* some glyphs leave something on the stack. so we clean it */
+    /* before a new execution.                                  */
+    exec->top     = 0;
+    exec->callTop = 0;
+
+#if 1
+    FT_UNUSED( debug );
+
+    return exec->face->interpreter( exec );
+#else
+    if ( !debug )
+      return TT_RunIns( exec );
+    else
+      return TT_Err_Ok;
+#endif
+  }
+
+
+  const TT_GraphicsState  tt_default_graphics_state =
+  {
+    0, 0, 0,
+    { 0x4000, 0 },
+    { 0x4000, 0 },
+    { 0x4000, 0 },
+    1, 64, 1,
+    TRUE, 68, 0, 0, 9, 3,
+    0, FALSE, 2, 1, 1, 1
+  };
+
+
+  /* documentation is in ttinterp.h */
+
+  FT_EXPORT_DEF( TT_ExecContext )
+  TT_New_Context( TT_Face  face )
+  {
+    TT_Driver       driver;
+    TT_ExecContext  exec;
+    FT_Memory       memory;
+
+
+    if ( !face )
+      return 0;
+
+    driver = (TT_Driver)face->root.driver;
+
+    memory = driver->root.root.memory;
+    exec   = driver->context;
+
+    if ( !driver->context )
+    {
+      FT_Error  error;
+
+
+      /* allocate object */
+      if ( ALLOC( exec, sizeof ( *exec ) ) )
+        goto Exit;
+
+      /* initialize it */
+      error = Init_Context( exec, face, memory );
+      if ( error )
+        goto Fail;
+
+      /* store it into the driver */
+      driver->context = exec;
+    }
+
+  Exit:
+    return driver->context;
+
+  Fail:
+    FREE( exec );
+
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_Context                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Discards an execution context.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    exec :: A handle to the target execution context.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Only the glyph loader and debugger should call this function.      */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Done_Context( TT_ExecContext  exec )
+  {
+    /* Nothing at all for now */
+    FT_UNUSED( exec );
+
+    return TT_Err_Ok;
+  }
+
+
+ /* return length of given vector */
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+  static FT_F26Dot6
+  Norm( FT_F26Dot6  X,
+        FT_F26Dot6  Y )
+  {
+    TT_INT64  T1, T2;
+
+
+    MUL_64( X, X, T1 );
+    MUL_64( Y, Y, T2 );
+
+    ADD_64( T1, T2, T1 );
+
+    return (FT_F26Dot6)SQRT_64( T1 );
+  }
+
+#else  /* !FT_CONFIG_OPTION_OLD_CALCS */
+
+  static FT_F26Dot6
+  Norm( FT_F26Dot6  X,
+        FT_F26Dot6  Y )
+  {
+    FT_Vector  v;
+
+    v.x = X;
+    v.y = Y;
+    return FT_Vector_Length( &v );
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Before an opcode is executed, the interpreter verifies that there are */
+  /* enough arguments on the stack, with the help of the Pop_Push_Count    */
+  /* table.                                                                */
+  /*                                                                       */
+  /* For each opcode, the first column gives the number of arguments that  */
+  /* are popped from the stack; the second one gives the number of those   */
+  /* that are pushed in result.                                            */
+  /*                                                                       */
+  /* Note that for opcodes with a varying number of parameters, either 0   */
+  /* or 1 arg is verified before execution, depending on the nature of the */
+  /* instruction:                                                          */
+  /*                                                                       */
+  /* - if the number of arguments is given by the bytecode stream or the   */
+  /*   loop variable, 0 is chosen.                                         */
+  /*                                                                       */
+  /* - if the first argument is a count n that is followed by arguments    */
+  /*   a1 .. an, then 1 is chosen.                                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#undef  PACK
+#define PACK( x, y )  ( ( x << 4 ) | y )
+
+
+  static
+  const FT_Byte  Pop_Push_Count[256] =
+  {
+    /* opcodes are gathered in groups of 16 */
+    /* please keep the spaces as they are   */
+
+    /*  SVTCA  y  */  PACK( 0, 0 ),
+    /*  SVTCA  x  */  PACK( 0, 0 ),
+    /*  SPvTCA y  */  PACK( 0, 0 ),
+    /*  SPvTCA x  */  PACK( 0, 0 ),
+    /*  SFvTCA y  */  PACK( 0, 0 ),
+    /*  SFvTCA x  */  PACK( 0, 0 ),
+    /*  SPvTL //  */  PACK( 2, 0 ),
+    /*  SPvTL +   */  PACK( 2, 0 ),
+    /*  SFvTL //  */  PACK( 2, 0 ),
+    /*  SFvTL +   */  PACK( 2, 0 ),
+    /*  SPvFS     */  PACK( 2, 0 ),
+    /*  SFvFS     */  PACK( 2, 0 ),
+    /*  GPV       */  PACK( 0, 2 ),
+    /*  GFV       */  PACK( 0, 2 ),
+    /*  SFvTPv    */  PACK( 0, 0 ),
+    /*  ISECT     */  PACK( 5, 0 ),
+
+    /*  SRP0      */  PACK( 1, 0 ),
+    /*  SRP1      */  PACK( 1, 0 ),
+    /*  SRP2      */  PACK( 1, 0 ),
+    /*  SZP0      */  PACK( 1, 0 ),
+    /*  SZP1      */  PACK( 1, 0 ),
+    /*  SZP2      */  PACK( 1, 0 ),
+    /*  SZPS      */  PACK( 1, 0 ),
+    /*  SLOOP     */  PACK( 1, 0 ),
+    /*  RTG       */  PACK( 0, 0 ),
+    /*  RTHG      */  PACK( 0, 0 ),
+    /*  SMD       */  PACK( 1, 0 ),
+    /*  ELSE      */  PACK( 0, 0 ),
+    /*  JMPR      */  PACK( 1, 0 ),
+    /*  SCvTCi    */  PACK( 1, 0 ),
+    /*  SSwCi     */  PACK( 1, 0 ),
+    /*  SSW       */  PACK( 1, 0 ),
+
+    /*  DUP       */  PACK( 1, 2 ),
+    /*  POP       */  PACK( 1, 0 ),
+    /*  CLEAR     */  PACK( 0, 0 ),
+    /*  SWAP      */  PACK( 2, 2 ),
+    /*  DEPTH     */  PACK( 0, 1 ),
+    /*  CINDEX    */  PACK( 1, 1 ),
+    /*  MINDEX    */  PACK( 1, 0 ),
+    /*  AlignPTS  */  PACK( 2, 0 ),
+    /*  INS_$28   */  PACK( 0, 0 ),
+    /*  UTP       */  PACK( 1, 0 ),
+    /*  LOOPCALL  */  PACK( 2, 0 ),
+    /*  CALL      */  PACK( 1, 0 ),
+    /*  FDEF      */  PACK( 1, 0 ),
+    /*  ENDF      */  PACK( 0, 0 ),
+    /*  MDAP[0]   */  PACK( 1, 0 ),
+    /*  MDAP[1]   */  PACK( 1, 0 ),
+
+    /*  IUP[0]    */  PACK( 0, 0 ),
+    /*  IUP[1]    */  PACK( 0, 0 ),
+    /*  SHP[0]    */  PACK( 0, 0 ),
+    /*  SHP[1]    */  PACK( 0, 0 ),
+    /*  SHC[0]    */  PACK( 1, 0 ),
+    /*  SHC[1]    */  PACK( 1, 0 ),
+    /*  SHZ[0]    */  PACK( 1, 0 ),
+    /*  SHZ[1]    */  PACK( 1, 0 ),
+    /*  SHPIX     */  PACK( 1, 0 ),
+    /*  IP        */  PACK( 0, 0 ),
+    /*  MSIRP[0]  */  PACK( 2, 0 ),
+    /*  MSIRP[1]  */  PACK( 2, 0 ),
+    /*  AlignRP   */  PACK( 0, 0 ),
+    /*  RTDG      */  PACK( 0, 0 ),
+    /*  MIAP[0]   */  PACK( 2, 0 ),
+    /*  MIAP[1]   */  PACK( 2, 0 ),
+
+    /*  NPushB    */  PACK( 0, 0 ),
+    /*  NPushW    */  PACK( 0, 0 ),
+    /*  WS        */  PACK( 2, 0 ),
+    /*  RS        */  PACK( 1, 1 ),
+    /*  WCvtP     */  PACK( 2, 0 ),
+    /*  RCvt      */  PACK( 1, 1 ),
+    /*  GC[0]     */  PACK( 1, 1 ),
+    /*  GC[1]     */  PACK( 1, 1 ),
+    /*  SCFS      */  PACK( 2, 0 ),
+    /*  MD[0]     */  PACK( 2, 1 ),
+    /*  MD[1]     */  PACK( 2, 1 ),
+    /*  MPPEM     */  PACK( 0, 1 ),
+    /*  MPS       */  PACK( 0, 1 ),
+    /*  FlipON    */  PACK( 0, 0 ),
+    /*  FlipOFF   */  PACK( 0, 0 ),
+    /*  DEBUG     */  PACK( 1, 0 ),
+
+    /*  LT        */  PACK( 2, 1 ),
+    /*  LTEQ      */  PACK( 2, 1 ),
+    /*  GT        */  PACK( 2, 1 ),
+    /*  GTEQ      */  PACK( 2, 1 ),
+    /*  EQ        */  PACK( 2, 1 ),
+    /*  NEQ       */  PACK( 2, 1 ),
+    /*  ODD       */  PACK( 1, 1 ),
+    /*  EVEN      */  PACK( 1, 1 ),
+    /*  IF        */  PACK( 1, 0 ),
+    /*  EIF       */  PACK( 0, 0 ),
+    /*  AND       */  PACK( 2, 1 ),
+    /*  OR        */  PACK( 2, 1 ),
+    /*  NOT       */  PACK( 1, 1 ),
+    /*  DeltaP1   */  PACK( 1, 0 ),
+    /*  SDB       */  PACK( 1, 0 ),
+    /*  SDS       */  PACK( 1, 0 ),
+
+    /*  ADD       */  PACK( 2, 1 ),
+    /*  SUB       */  PACK( 2, 1 ),
+    /*  DIV       */  PACK( 2, 1 ),
+    /*  MUL       */  PACK( 2, 1 ),
+    /*  ABS       */  PACK( 1, 1 ),
+    /*  NEG       */  PACK( 1, 1 ),
+    /*  FLOOR     */  PACK( 1, 1 ),
+    /*  CEILING   */  PACK( 1, 1 ),
+    /*  ROUND[0]  */  PACK( 1, 1 ),
+    /*  ROUND[1]  */  PACK( 1, 1 ),
+    /*  ROUND[2]  */  PACK( 1, 1 ),
+    /*  ROUND[3]  */  PACK( 1, 1 ),
+    /*  NROUND[0] */  PACK( 1, 1 ),
+    /*  NROUND[1] */  PACK( 1, 1 ),
+    /*  NROUND[2] */  PACK( 1, 1 ),
+    /*  NROUND[3] */  PACK( 1, 1 ),
+
+    /*  WCvtF     */  PACK( 2, 0 ),
+    /*  DeltaP2   */  PACK( 1, 0 ),
+    /*  DeltaP3   */  PACK( 1, 0 ),
+    /*  DeltaCn[0] */ PACK( 1, 0 ),
+    /*  DeltaCn[1] */ PACK( 1, 0 ),
+    /*  DeltaCn[2] */ PACK( 1, 0 ),
+    /*  SROUND    */  PACK( 1, 0 ),
+    /*  S45Round  */  PACK( 1, 0 ),
+    /*  JROT      */  PACK( 2, 0 ),
+    /*  JROF      */  PACK( 2, 0 ),
+    /*  ROFF      */  PACK( 0, 0 ),
+    /*  INS_$7B   */  PACK( 0, 0 ),
+    /*  RUTG      */  PACK( 0, 0 ),
+    /*  RDTG      */  PACK( 0, 0 ),
+    /*  SANGW     */  PACK( 1, 0 ),
+    /*  AA        */  PACK( 1, 0 ),
+
+    /*  FlipPT    */  PACK( 0, 0 ),
+    /*  FlipRgON  */  PACK( 2, 0 ),
+    /*  FlipRgOFF */  PACK( 2, 0 ),
+    /*  INS_$83   */  PACK( 0, 0 ),
+    /*  INS_$84   */  PACK( 0, 0 ),
+    /*  ScanCTRL  */  PACK( 1, 0 ),
+    /*  SDVPTL[0] */  PACK( 2, 0 ),
+    /*  SDVPTL[1] */  PACK( 2, 0 ),
+    /*  GetINFO   */  PACK( 1, 1 ),
+    /*  IDEF      */  PACK( 1, 0 ),
+    /*  ROLL      */  PACK( 3, 3 ),
+    /*  MAX       */  PACK( 2, 1 ),
+    /*  MIN       */  PACK( 2, 1 ),
+    /*  ScanTYPE  */  PACK( 1, 0 ),
+    /*  InstCTRL  */  PACK( 2, 0 ),
+    /*  INS_$8F   */  PACK( 0, 0 ),
+
+    /*  INS_$90  */   PACK( 0, 0 ),
+    /*  INS_$91  */   PACK( 0, 0 ),
+    /*  INS_$92  */   PACK( 0, 0 ),
+    /*  INS_$93  */   PACK( 0, 0 ),
+    /*  INS_$94  */   PACK( 0, 0 ),
+    /*  INS_$95  */   PACK( 0, 0 ),
+    /*  INS_$96  */   PACK( 0, 0 ),
+    /*  INS_$97  */   PACK( 0, 0 ),
+    /*  INS_$98  */   PACK( 0, 0 ),
+    /*  INS_$99  */   PACK( 0, 0 ),
+    /*  INS_$9A  */   PACK( 0, 0 ),
+    /*  INS_$9B  */   PACK( 0, 0 ),
+    /*  INS_$9C  */   PACK( 0, 0 ),
+    /*  INS_$9D  */   PACK( 0, 0 ),
+    /*  INS_$9E  */   PACK( 0, 0 ),
+    /*  INS_$9F  */   PACK( 0, 0 ),
+
+    /*  INS_$A0  */   PACK( 0, 0 ),
+    /*  INS_$A1  */   PACK( 0, 0 ),
+    /*  INS_$A2  */   PACK( 0, 0 ),
+    /*  INS_$A3  */   PACK( 0, 0 ),
+    /*  INS_$A4  */   PACK( 0, 0 ),
+    /*  INS_$A5  */   PACK( 0, 0 ),
+    /*  INS_$A6  */   PACK( 0, 0 ),
+    /*  INS_$A7  */   PACK( 0, 0 ),
+    /*  INS_$A8  */   PACK( 0, 0 ),
+    /*  INS_$A9  */   PACK( 0, 0 ),
+    /*  INS_$AA  */   PACK( 0, 0 ),
+    /*  INS_$AB  */   PACK( 0, 0 ),
+    /*  INS_$AC  */   PACK( 0, 0 ),
+    /*  INS_$AD  */   PACK( 0, 0 ),
+    /*  INS_$AE  */   PACK( 0, 0 ),
+    /*  INS_$AF  */   PACK( 0, 0 ),
+
+    /*  PushB[0]  */  PACK( 0, 1 ),
+    /*  PushB[1]  */  PACK( 0, 2 ),
+    /*  PushB[2]  */  PACK( 0, 3 ),
+    /*  PushB[3]  */  PACK( 0, 4 ),
+    /*  PushB[4]  */  PACK( 0, 5 ),
+    /*  PushB[5]  */  PACK( 0, 6 ),
+    /*  PushB[6]  */  PACK( 0, 7 ),
+    /*  PushB[7]  */  PACK( 0, 8 ),
+    /*  PushW[0]  */  PACK( 0, 1 ),
+    /*  PushW[1]  */  PACK( 0, 2 ),
+    /*  PushW[2]  */  PACK( 0, 3 ),
+    /*  PushW[3]  */  PACK( 0, 4 ),
+    /*  PushW[4]  */  PACK( 0, 5 ),
+    /*  PushW[5]  */  PACK( 0, 6 ),
+    /*  PushW[6]  */  PACK( 0, 7 ),
+    /*  PushW[7]  */  PACK( 0, 8 ),
+
+    /*  MDRP[00]  */  PACK( 1, 0 ),
+    /*  MDRP[01]  */  PACK( 1, 0 ),
+    /*  MDRP[02]  */  PACK( 1, 0 ),
+    /*  MDRP[03]  */  PACK( 1, 0 ),
+    /*  MDRP[04]  */  PACK( 1, 0 ),
+    /*  MDRP[05]  */  PACK( 1, 0 ),
+    /*  MDRP[06]  */  PACK( 1, 0 ),
+    /*  MDRP[07]  */  PACK( 1, 0 ),
+    /*  MDRP[08]  */  PACK( 1, 0 ),
+    /*  MDRP[09]  */  PACK( 1, 0 ),
+    /*  MDRP[10]  */  PACK( 1, 0 ),
+    /*  MDRP[11]  */  PACK( 1, 0 ),
+    /*  MDRP[12]  */  PACK( 1, 0 ),
+    /*  MDRP[13]  */  PACK( 1, 0 ),
+    /*  MDRP[14]  */  PACK( 1, 0 ),
+    /*  MDRP[15]  */  PACK( 1, 0 ),
+
+    /*  MDRP[16]  */  PACK( 1, 0 ),
+    /*  MDRP[17]  */  PACK( 1, 0 ),
+    /*  MDRP[18]  */  PACK( 1, 0 ),
+    /*  MDRP[19]  */  PACK( 1, 0 ),
+    /*  MDRP[20]  */  PACK( 1, 0 ),
+    /*  MDRP[21]  */  PACK( 1, 0 ),
+    /*  MDRP[22]  */  PACK( 1, 0 ),
+    /*  MDRP[23]  */  PACK( 1, 0 ),
+    /*  MDRP[24]  */  PACK( 1, 0 ),
+    /*  MDRP[25]  */  PACK( 1, 0 ),
+    /*  MDRP[26]  */  PACK( 1, 0 ),
+    /*  MDRP[27]  */  PACK( 1, 0 ),
+    /*  MDRP[28]  */  PACK( 1, 0 ),
+    /*  MDRP[29]  */  PACK( 1, 0 ),
+    /*  MDRP[30]  */  PACK( 1, 0 ),
+    /*  MDRP[31]  */  PACK( 1, 0 ),
+
+    /*  MIRP[00]  */  PACK( 2, 0 ),
+    /*  MIRP[01]  */  PACK( 2, 0 ),
+    /*  MIRP[02]  */  PACK( 2, 0 ),
+    /*  MIRP[03]  */  PACK( 2, 0 ),
+    /*  MIRP[04]  */  PACK( 2, 0 ),
+    /*  MIRP[05]  */  PACK( 2, 0 ),
+    /*  MIRP[06]  */  PACK( 2, 0 ),
+    /*  MIRP[07]  */  PACK( 2, 0 ),
+    /*  MIRP[08]  */  PACK( 2, 0 ),
+    /*  MIRP[09]  */  PACK( 2, 0 ),
+    /*  MIRP[10]  */  PACK( 2, 0 ),
+    /*  MIRP[11]  */  PACK( 2, 0 ),
+    /*  MIRP[12]  */  PACK( 2, 0 ),
+    /*  MIRP[13]  */  PACK( 2, 0 ),
+    /*  MIRP[14]  */  PACK( 2, 0 ),
+    /*  MIRP[15]  */  PACK( 2, 0 ),
+
+    /*  MIRP[16]  */  PACK( 2, 0 ),
+    /*  MIRP[17]  */  PACK( 2, 0 ),
+    /*  MIRP[18]  */  PACK( 2, 0 ),
+    /*  MIRP[19]  */  PACK( 2, 0 ),
+    /*  MIRP[20]  */  PACK( 2, 0 ),
+    /*  MIRP[21]  */  PACK( 2, 0 ),
+    /*  MIRP[22]  */  PACK( 2, 0 ),
+    /*  MIRP[23]  */  PACK( 2, 0 ),
+    /*  MIRP[24]  */  PACK( 2, 0 ),
+    /*  MIRP[25]  */  PACK( 2, 0 ),
+    /*  MIRP[26]  */  PACK( 2, 0 ),
+    /*  MIRP[27]  */  PACK( 2, 0 ),
+    /*  MIRP[28]  */  PACK( 2, 0 ),
+    /*  MIRP[29]  */  PACK( 2, 0 ),
+    /*  MIRP[30]  */  PACK( 2, 0 ),
+    /*  MIRP[31]  */  PACK( 2, 0 )
+  };
+
+
+  static
+  const FT_Char  opcode_length[256] =
+  {
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+
+   -1,-1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    2, 3, 4, 5,  6, 7, 8, 9,  3, 5, 7, 9, 11,13,15,17,
+
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
+    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1
+  };
+
+  static
+  const FT_Vector  Null_Vector = {0,0};
+
+
+#undef PACK
+
+
+#undef  NULL_Vector
+#define NULL_Vector  (FT_Vector*)&Null_Vector
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Current_Ratio                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns the current aspect ratio scaling factor depending on the   */
+  /*    projection vector's state and device resolutions.                  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The aspect ratio in 16.16 format, always <= 1.0 .                  */
+  /*                                                                       */
+  static FT_Long
+  Current_Ratio( EXEC_OP )
+  {
+    if ( CUR.tt_metrics.ratio )
+      return CUR.tt_metrics.ratio;
+
+    if ( CUR.GS.projVector.y == 0 )
+      CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio;
+
+    else if ( CUR.GS.projVector.x == 0 )
+      CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio;
+
+    else
+    {
+      FT_Long  x, y;
+
+      x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x4000 );
+      y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x4000 );
+      CUR.tt_metrics.ratio = Norm( x, y );
+    }
+
+    return CUR.tt_metrics.ratio;
+  }
+
+
+  static FT_Long
+  Current_Ppem( EXEC_OP )
+  {
+    return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Functions related to the control value table (CVT).                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  FT_CALLBACK_DEF( FT_F26Dot6 )
+  Read_CVT( EXEC_OP_ FT_ULong  index )
+  {
+    return CUR.cvt[index];
+  }
+
+
+  FT_CALLBACK_DEF( FT_F26Dot6 )
+  Read_CVT_Stretched( EXEC_OP_ FT_ULong  index )
+  {
+    return TT_MULFIX( CUR.cvt[index], CURRENT_Ratio() );
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  Write_CVT( EXEC_OP_ FT_ULong    index,
+                      FT_F26Dot6  value )
+  {
+    CUR.cvt[index] = value;
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  Write_CVT_Stretched( EXEC_OP_ FT_ULong    index,
+                                FT_F26Dot6  value )
+  {
+    CUR.cvt[index] = FT_DivFix( value, CURRENT_Ratio() );
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  Move_CVT( EXEC_OP_ FT_ULong    index,
+                     FT_F26Dot6  value )
+  {
+    CUR.cvt[index] += value;
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  Move_CVT_Stretched( EXEC_OP_ FT_ULong    index,
+                               FT_F26Dot6  value )
+  {
+    CUR.cvt[index] += FT_DivFix( value, CURRENT_Ratio() );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    GetShortIns                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Returns a short integer taken from the instruction stream at       */
+  /*    address IP.                                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Short read at code[IP].                                            */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This one could become a macro.                                     */
+  /*                                                                       */
+  static FT_Short
+  GetShortIns( EXEC_OP )
+  {
+    /* Reading a byte stream so there is no endianess (DaveP) */
+    CUR.IP += 2;
+    return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) +
+                         CUR.code[CUR.IP - 1]      );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Ins_Goto_CodeRange                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Goes to a certain code range in the instruction stream.            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    aRange :: The index of the code range.                             */
+  /*                                                                       */
+  /*    aIP    :: The new IP address in the code range.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS or FAILURE.                                                */
+  /*                                                                       */
+  static FT_Bool
+  Ins_Goto_CodeRange( EXEC_OP_ FT_Int    aRange,
+                               FT_ULong  aIP )
+  {
+    TT_CodeRange*  range;
+
+
+    if ( aRange < 1 || aRange > 3 )
+    {
+      CUR.error = TT_Err_Bad_Argument;
+      return FAILURE;
+    }
+
+    range = &CUR.codeRangeTable[aRange - 1];
+
+    if ( range->base == NULL )     /* invalid coderange */
+    {
+      CUR.error = TT_Err_Invalid_CodeRange;
+      return FAILURE;
+    }
+
+    /* NOTE: Because the last instruction of a program may be a CALL */
+    /*       which will return to the first byte *after* the code    */
+    /*       range, we test for AIP <= Size, instead of AIP < Size.  */
+
+    if ( aIP > range->size )
+    {
+      CUR.error = TT_Err_Code_Overflow;
+      return FAILURE;
+    }
+
+    CUR.code     = range->base;
+    CUR.codeSize = range->size;
+    CUR.IP       = aIP;
+    CUR.curRange = aRange;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Direct_Move                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Moves a point by a given distance along the freedom vector.  The   */
+  /*    point will be `touched'.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    point    :: The index of the point to move.                        */
+  /*                                                                       */
+  /*    distance :: The distance to apply.                                 */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    zone     :: The affected glyph zone.                               */
+  /*                                                                       */
+  static void
+  Direct_Move( EXEC_OP_ TT_GlyphZone*  zone,
+                        FT_UShort      point,
+                        FT_F26Dot6     distance )
+  {
+    FT_F26Dot6 v;
+
+
+    v = CUR.GS.freeVector.x;
+
+    if ( v != 0 )
+    {
+
+#ifdef NO_APPLE_PATENT
+
+      if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
+        zone->cur[point].x += distance;
+
+#else
+
+      zone->cur[point].x += TT_MULDIV( distance,
+                                       v * 0x10000L,
+                                       CUR.F_dot_P );
+
+#endif
+
+      zone->tags[point] |= FT_Curve_Tag_Touch_X;
+    }
+
+    v = CUR.GS.freeVector.y;
+
+    if ( v != 0 )
+    {
+
+#ifdef NO_APPLE_PATENT
+
+      if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD )
+        zone->cur[point].y += distance;
+
+#else
+
+      zone->cur[point].y += TT_MULDIV( distance,
+                                       v * 0x10000L,
+                                       CUR.F_dot_P );
+
+#endif
+
+      zone->tags[point] |= FT_Curve_Tag_Touch_Y;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Special versions of Direct_Move()                                     */
+  /*                                                                       */
+  /*   The following versions are used whenever both vectors are both      */
+  /*   along one of the coordinate unit vectors, i.e. in 90% of the cases. */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  static void
+  Direct_Move_X( EXEC_OP_ TT_GlyphZone*  zone,
+                          FT_UShort      point,
+                          FT_F26Dot6     distance )
+  {
+    FT_UNUSED_EXEC;
+
+    zone->cur[point].x += distance;
+    zone->tags[point]  |= FT_Curve_Tag_Touch_X;
+  }
+
+
+  static void
+  Direct_Move_Y( EXEC_OP_ TT_GlyphZone*  zone,
+                          FT_UShort      point,
+                          FT_F26Dot6     distance )
+  {
+    FT_UNUSED_EXEC;
+
+    zone->cur[point].y += distance;
+    zone->tags[point]  |= FT_Curve_Tag_Touch_Y;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_None                                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Does not round, but adds engine compensation.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance (not) to round.                       */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The compensated distance.                                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The TrueType specification says very few about the relationship    */
+  /*    between rounding and engine compensation.  However, it seems from  */
+  /*    the description of super round that we should add the compensation */
+  /*    before rounding.                                                   */
+  /*                                                                       */
+  static FT_F26Dot6
+  Round_None( EXEC_OP_ FT_F26Dot6  distance,
+                       FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( distance >= 0 )
+    {
+      val = distance + compensation;
+      if ( val < 0 )
+        val = 0;
+    }
+    else {
+      val = distance - compensation;
+      if ( val > 0 )
+        val = 0;
+    }
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_To_Grid                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Rounds value to grid after adding engine compensation.             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  static FT_F26Dot6
+  Round_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
+                          FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( distance >= 0 )
+    {
+      val = distance + compensation + 32;
+      if ( val > 0 )
+        val &= ~63;
+      else
+        val = 0;
+    }
+    else
+    {
+      val = -( ( compensation - distance + 32 ) & -64 );
+      if ( val > 0 )
+        val = 0;
+    }
+
+    return  val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_To_Half_Grid                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Rounds value to half grid after adding engine compensation.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  static FT_F26Dot6
+  Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6  distance,
+                               FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( distance >= 0 )
+    {
+      val = ( ( distance + compensation ) & -64 ) + 32;
+      if ( val < 0 )
+        val = 0;
+    }
+    else
+    {
+      val = -( ( (compensation - distance) & -64 ) + 32 );
+      if ( val > 0 )
+        val = 0;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_Down_To_Grid                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Rounds value down to grid after adding engine compensation.        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  static FT_F26Dot6
+  Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
+                               FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( distance >= 0 )
+    {
+      val = distance + compensation;
+      if ( val > 0 )
+        val &= ~63;
+      else
+        val = 0;
+    }
+    else
+    {
+      val = -( ( compensation - distance ) & -64 );
+      if ( val > 0 )
+        val = 0;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_Up_To_Grid                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Rounds value up to grid after adding engine compensation.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  static FT_F26Dot6
+  Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6  distance,
+                             FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+
+    FT_UNUSED_EXEC;
+
+    if ( distance >= 0 )
+    {
+      val = distance + compensation + 63;
+      if ( val > 0 )
+        val &= ~63;
+      else
+        val = 0;
+    }
+    else
+    {
+      val = -( ( compensation - distance + 63 ) & -64 );
+      if ( val > 0 )
+        val = 0;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_To_Double_Grid                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Rounds value to double grid after adding engine compensation.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  static FT_F26Dot6
+  Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6  distance,
+                                 FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6 val;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( distance >= 0 )
+    {
+      val = distance + compensation + 16;
+      if ( val > 0 )
+        val &= ~31;
+      else
+        val = 0;
+    }
+    else
+    {
+      val = -( ( compensation - distance + 16 ) & -32 );
+      if ( val > 0 )
+        val = 0;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_Super                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Super-rounds value to grid after adding engine compensation.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The TrueType specification says very few about the relationship    */
+  /*    between rounding and engine compensation.  However, it seems from  */
+  /*    the description of super round that we should add the compensation */
+  /*    before rounding.                                                   */
+  /*                                                                       */
+  static FT_F26Dot6
+  Round_Super( EXEC_OP_ FT_F26Dot6  distance,
+                        FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+
+    if ( distance >= 0 )
+    {
+      val = ( distance - CUR.phase + CUR.threshold + compensation ) &
+              -CUR.period;
+      if ( val < 0 )
+        val = 0;
+      val += CUR.phase;
+    }
+    else
+    {
+      val = -( ( CUR.threshold - CUR.phase - distance + compensation ) &
+               -CUR.period );
+      if ( val > 0 )
+        val = 0;
+      val -= CUR.phase;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Round_Super_45                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Super-rounds value to grid after adding engine compensation.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    distance     :: The distance to round.                             */
+  /*                                                                       */
+  /*    compensation :: The engine compensation.                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Rounded distance.                                                  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    There is a separate function for Round_Super_45() as we may need   */
+  /*    greater precision.                                                 */
+  /*                                                                       */
+  static FT_F26Dot6
+  Round_Super_45( EXEC_OP_ FT_F26Dot6  distance,
+                           FT_F26Dot6  compensation )
+  {
+    FT_F26Dot6  val;
+
+
+    if ( distance >= 0 )
+    {
+      val = ( ( distance - CUR.phase + CUR.threshold + compensation ) /
+                CUR.period ) * CUR.period;
+      if ( val < 0 )
+        val = 0;
+      val += CUR.phase;
+    }
+    else
+    {
+      val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) /
+                   CUR.period ) * CUR.period );
+      if ( val > 0 )
+        val = 0;
+      val -= CUR.phase;
+    }
+
+    return val;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Compute_Round                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets the rounding mode.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    round_mode :: The rounding mode to be used.                        */
+  /*                                                                       */
+  static void
+  Compute_Round( EXEC_OP_ FT_Byte  round_mode )
+  {
+    switch ( round_mode )
+    {
+    case TT_Round_Off:
+      CUR.func_round = (TT_Round_Func)Round_None;
+      break;
+
+    case TT_Round_To_Grid:
+      CUR.func_round = (TT_Round_Func)Round_To_Grid;
+      break;
+
+    case TT_Round_Up_To_Grid:
+      CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
+      break;
+
+    case TT_Round_Down_To_Grid:
+      CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
+      break;
+
+    case TT_Round_To_Half_Grid:
+      CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
+      break;
+
+    case TT_Round_To_Double_Grid:
+      CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
+      break;
+
+    case TT_Round_Super:
+      CUR.func_round = (TT_Round_Func)Round_Super;
+      break;
+
+    case TT_Round_Super_45:
+      CUR.func_round = (TT_Round_Func)Round_Super_45;
+      break;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    SetSuperRound                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets Super Round parameters.                                       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    GridPeriod :: Grid period                                          */
+  /*    selector   :: SROUND opcode                                        */
+  /*                                                                       */
+  static void
+  SetSuperRound( EXEC_OP_ FT_F26Dot6  GridPeriod,
+                          FT_Long     selector )
+  {
+    switch ( (FT_Int)( selector & 0xC0 ) )
+    {
+      case 0:
+        CUR.period = GridPeriod / 2;
+        break;
+
+      case 0x40:
+        CUR.period = GridPeriod;
+        break;
+
+      case 0x80:
+        CUR.period = GridPeriod * 2;
+        break;
+
+      /* This opcode is reserved, but... */
+
+      case 0xC0:
+        CUR.period = GridPeriod;
+        break;
+    }
+
+    switch ( (FT_Int)( selector & 0x30 ) )
+    {
+    case 0:
+      CUR.phase = 0;
+      break;
+
+    case 0x10:
+      CUR.phase = CUR.period / 4;
+      break;
+
+    case 0x20:
+      CUR.phase = CUR.period / 2;
+      break;
+
+    case 0x30:
+      CUR.phase = GridPeriod * 3 / 4;
+      break;
+    }
+
+    if ( (selector & 0x0F) == 0 )
+      CUR.threshold = CUR.period - 1;
+    else
+      CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8;
+
+    CUR.period    /= 256;
+    CUR.phase     /= 256;
+    CUR.threshold /= 256;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Project                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection of vector given by (v2-v1) along the       */
+  /*    current projection vector.                                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    v1 :: First input vector.                                          */
+  /*    v2 :: Second input vector.                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The distance in F26dot6 format.                                    */
+  /*                                                                       */
+  static FT_F26Dot6
+  Project( EXEC_OP_ FT_Vector*  v1,
+                    FT_Vector*  v2 )
+  {
+    return TT_MULDIV( v1->x - v2->x, CUR.GS.projVector.x, 0x4000 ) +
+           TT_MULDIV( v1->y - v2->y, CUR.GS.projVector.y, 0x4000 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Dual_Project                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection of the vector given by (v2-v1) along the   */
+  /*    current dual vector.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    v1 :: First input vector.                                          */
+  /*    v2 :: Second input vector.                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The distance in F26dot6 format.                                    */
+  /*                                                                       */
+  static FT_F26Dot6
+  Dual_Project( EXEC_OP_ FT_Vector*  v1,
+                         FT_Vector*  v2 )
+  {
+    return TT_MULDIV( v1->x - v2->x, CUR.GS.dualVector.x, 0x4000 ) +
+           TT_MULDIV( v1->y - v2->y, CUR.GS.dualVector.y, 0x4000 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Free_Project                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection of the vector given by (v2-v1) along the   */
+  /*    current freedom vector.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    v1 :: First input vector.                                          */
+  /*    v2 :: Second input vector.                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The distance in F26dot6 format.                                    */
+  /*                                                                       */
+  static FT_F26Dot6
+  Free_Project( EXEC_OP_ FT_Vector*  v1,
+                         FT_Vector*  v2 )
+  {
+    return TT_MULDIV( v1->x - v2->x, CUR.GS.freeVector.x, 0x4000 ) +
+           TT_MULDIV( v1->y - v2->y, CUR.GS.freeVector.y, 0x4000 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Project_x                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection of the vector given by (v2-v1) along the   */
+  /*    horizontal axis.                                                   */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    v1 :: First input vector.                                          */
+  /*    v2 :: Second input vector.                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The distance in F26dot6 format.                                    */
+  /*                                                                       */
+  static FT_F26Dot6
+  Project_x( EXEC_OP_ FT_Vector*  v1,
+                      FT_Vector*  v2 )
+  {
+    FT_UNUSED_EXEC;
+
+    return ( v1->x - v2->x );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Project_y                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection of the vector given by (v2-v1) along the   */
+  /*    vertical axis.                                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    v1 :: First input vector.                                          */
+  /*    v2 :: Second input vector.                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The distance in F26dot6 format.                                    */
+  /*                                                                       */
+  static FT_F26Dot6
+  Project_y( EXEC_OP_ FT_Vector*  v1,
+                      FT_Vector*  v2 )
+  {
+    FT_UNUSED_EXEC;
+
+   return ( v1->y - v2->y );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Compute_Funcs                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the projection and movement function pointers according   */
+  /*    to the current graphics state.                                     */
+  /*                                                                       */
+  static void
+  Compute_Funcs( EXEC_OP )
+  {
+    if ( CUR.GS.freeVector.x == 0x4000 )
+    {
+      CUR.func_freeProj = (TT_Project_Func)Project_x;
+      CUR.F_dot_P       = CUR.GS.projVector.x * 0x10000L;
+    }
+    else
+    {
+      if ( CUR.GS.freeVector.y == 0x4000 )
+      {
+        CUR.func_freeProj = (TT_Project_Func)Project_y;
+        CUR.F_dot_P       = CUR.GS.projVector.y * 0x10000L;
+      }
+      else
+      {
+        CUR.func_freeProj = (TT_Project_Func)Free_Project;
+        CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
+                      (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
+      }
+    }
+
+    if ( CUR.GS.projVector.x == 0x4000 )
+      CUR.func_project = (TT_Project_Func)Project_x;
+    else
+    {
+      if ( CUR.GS.projVector.y == 0x4000 )
+        CUR.func_project = (TT_Project_Func)Project_y;
+      else
+        CUR.func_project = (TT_Project_Func)Project;
+    }
+
+    if ( CUR.GS.dualVector.x == 0x4000 )
+      CUR.func_dualproj = (TT_Project_Func)Project_x;
+    else
+    {
+      if ( CUR.GS.dualVector.y == 0x4000 )
+        CUR.func_dualproj = (TT_Project_Func)Project_y;
+      else
+        CUR.func_dualproj = (TT_Project_Func)Dual_Project;
+    }
+
+    CUR.func_move = (TT_Move_Func)Direct_Move;
+
+    if ( CUR.F_dot_P == 0x40000000L )
+    {
+      if ( CUR.GS.freeVector.x == 0x4000 )
+        CUR.func_move = (TT_Move_Func)Direct_Move_X;
+      else
+      {
+        if ( CUR.GS.freeVector.y == 0x4000 )
+          CUR.func_move = (TT_Move_Func)Direct_Move_Y;
+      }
+    }
+
+    /* at small sizes, F_dot_P can become too small, resulting   */
+    /* in overflows and `spikes' in a number of glyphs like `w'. */
+
+    if ( ABS( CUR.F_dot_P ) < 0x4000000L )
+      CUR.F_dot_P = 0x40000000L;
+
+    /* Disable cached aspect ratio */
+    CUR.tt_metrics.ratio = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Normalize                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Norms a vector.                                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    Vx :: The horizontal input vector coordinate.                      */
+  /*    Vy :: The vertical input vector coordinate.                        */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    R  :: The normed unit vector.                                      */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Returns FAILURE if a vector parameter is zero.                     */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and  */
+  /*    R is undefined.                                                    */
+  /*                                                                       */
+
+#ifdef FT_CONFIG_OPTION_OLD_CALCS
+
+  static FT_Bool
+  Normalize( EXEC_OP_ FT_F26Dot6      Vx,
+                      FT_F26Dot6      Vy,
+                      FT_UnitVector*  R )
+  {
+    FT_F26Dot6  W;
+    FT_Bool     S1, S2;
+
+    FT_UNUSED_EXEC;
+
+
+    if ( ABS( Vx ) < 0x10000L && ABS( Vy ) < 0x10000L )
+    {
+      Vx *= 0x100;
+      Vy *= 0x100;
+
+      W = Norm( Vx, Vy );
+
+      if ( W == 0 )
+      {
+        /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
+        /*      to normalize the vector (0,0).  Return immediately. */
+        return SUCCESS;
+      }
+
+      R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
+      R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
+
+      return SUCCESS;
+    }
+
+    W = Norm( Vx, Vy );
+
+    Vx = FT_MulDiv( Vx, 0x4000L, W );
+    Vy = FT_MulDiv( Vy, 0x4000L, W );
+
+    W = Vx * Vx + Vy * Vy;
+
+    /* Now, we want that Sqrt( W ) = 0x4000 */
+    /* Or 0x1000000 <= W < 0x1004000        */
+
+    if ( Vx < 0 )
+    {
+      Vx = -Vx;
+      S1 = TRUE;
+    }
+    else
+      S1 = FALSE;
+
+    if ( Vy < 0 )
+    {
+      Vy = -Vy;
+      S2 = TRUE;
+    }
+    else
+      S2 = FALSE;
+
+    while ( W < 0x1000000L )
+    {
+      /* We need to increase W by a minimal amount */
+      if ( Vx < Vy )
+        Vx++;
+      else
+        Vy++;
+
+      W = Vx * Vx + Vy * Vy;
+    }
+
+    while ( W >= 0x1004000L )
+    {
+      /* We need to decrease W by a minimal amount */
+      if ( Vx < Vy )
+        Vx--;
+      else
+        Vy--;
+
+      W = Vx * Vx + Vy * Vy;
+    }
+
+    /* Note that in various cases, we can only  */
+    /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
+
+    if ( S1 )
+      Vx = -Vx;
+
+    if ( S2 )
+      Vy = -Vy;
+
+    R->x = (FT_F2Dot14)Vx;   /* Type conversion */
+    R->y = (FT_F2Dot14)Vy;   /* Type conversion */
+
+    return SUCCESS;
+  }
+
+#else
+
+  static FT_Bool
+  Normalize( EXEC_OP_ FT_F26Dot6      Vx,
+                      FT_F26Dot6      Vy,
+                      FT_UnitVector*  R )
+  {
+    FT_Vector  v;
+    FT_Angle   angle;
+
+    FT_UNUSED_EXEC;
+
+    angle = FT_Atan2( Vx, Vy );
+
+    FT_Vector_Unit( &v, angle );
+
+    R->x = (short)(v.x >> 2);
+    R->y = (short)(v.y >> 2);
+
+    return SUCCESS;
+  }
+
+#endif /* FT_CONFIG_OPTION_OLD_CALCS */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Here we start with the implementation of the various opcodes.         */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  static FT_Bool
+  Ins_SxVTL( EXEC_OP_ FT_UShort       aIdx1,
+                      FT_UShort       aIdx2,
+                      FT_Int          aOpc,
+                      FT_UnitVector*  Vec )
+  {
+    FT_Long     A, B, C;
+    FT_Vector*  p1;
+    FT_Vector*  p2;
+
+
+    if ( BOUNDS( aIdx1, CUR.zp2.n_points ) ||
+         BOUNDS( aIdx2, CUR.zp1.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return FAILURE;
+    }
+
+    p1 = CUR.zp1.cur + aIdx2;
+    p2 = CUR.zp2.cur + aIdx1;
+
+    A = p1->x - p2->x;
+    B = p1->y - p2->y;
+
+    if ( ( aOpc & 1 ) != 0 )
+    {
+      C =  B;   /* counter clockwise rotation */
+      B =  A;
+      A = -C;
+    }
+
+    NORMalize( A, B, Vec );
+
+    return SUCCESS;
+  }
+
+
+  /* When not using the big switch statements, the interpreter uses a */
+  /* call table defined later below in this source.  Each opcode must */
+  /* thus have a corresponding function, even trivial ones.           */
+  /*                                                                  */
+  /* They are all defined there.                                      */
+
+#define DO_SVTCA                            \
+  {                                         \
+    FT_Short  A, B;                         \
+                                            \
+                                            \
+    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+    B = A ^ (FT_Short)0x4000;               \
+                                            \
+    CUR.GS.freeVector.x = A;                \
+    CUR.GS.projVector.x = A;                \
+    CUR.GS.dualVector.x = A;                \
+                                            \
+    CUR.GS.freeVector.y = B;                \
+    CUR.GS.projVector.y = B;                \
+    CUR.GS.dualVector.y = B;                \
+                                            \
+    COMPUTE_Funcs();                        \
+  }
+
+
+#define DO_SPVTCA                           \
+  {                                         \
+    FT_Short  A, B;                         \
+                                            \
+                                            \
+    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+    B = A ^ (FT_Short)0x4000;               \
+                                            \
+    CUR.GS.projVector.x = A;                \
+    CUR.GS.dualVector.x = A;                \
+                                            \
+    CUR.GS.projVector.y = B;                \
+    CUR.GS.dualVector.y = B;                \
+                                            \
+    COMPUTE_Funcs();                        \
+  }
+
+
+#define DO_SFVTCA                           \
+  {                                         \
+    FT_Short  A, B;                         \
+                                            \
+                                            \
+    A = (FT_Short)( CUR.opcode & 1 ) << 14; \
+    B = A ^ (FT_Short)0x4000;               \
+                                            \
+    CUR.GS.freeVector.x = A;                \
+    CUR.GS.freeVector.y = B;                \
+                                            \
+    COMPUTE_Funcs();                        \
+  }
+
+
+#define DO_SPVTL                                      \
+    if ( INS_SxVTL( (FT_UShort)args[1],               \
+                    (FT_UShort)args[0],               \
+                    CUR.opcode,                       \
+                    &CUR.GS.projVector ) == SUCCESS ) \
+    {                                                 \
+      CUR.GS.dualVector = CUR.GS.projVector;          \
+      COMPUTE_Funcs();                                \
+    }
+
+
+#define DO_SFVTL                                      \
+    if ( INS_SxVTL( (FT_UShort)args[1],               \
+                    (FT_UShort)args[0],               \
+                    CUR.opcode,                       \
+                    &CUR.GS.freeVector ) == SUCCESS ) \
+      COMPUTE_Funcs();
+
+
+#define DO_SFVTPV                          \
+    CUR.GS.freeVector = CUR.GS.projVector; \
+    COMPUTE_Funcs();
+
+
+#define DO_SPVFS                                \
+  {                                             \
+    FT_Short  S;                                \
+    FT_Long   X, Y;                             \
+                                                \
+                                                \
+    /* Only use low 16bits, then sign extend */ \
+    S = (FT_Short)args[1];                      \
+    Y = (FT_Long)S;                             \
+    S = (FT_Short)args[0];                      \
+    X = (FT_Long)S;                             \
+                                                \
+    NORMalize( X, Y, &CUR.GS.projVector );      \
+                                                \
+    CUR.GS.dualVector = CUR.GS.projVector;      \
+    COMPUTE_Funcs();                            \
+  }
+
+
+#define DO_SFVFS                                \
+  {                                             \
+    FT_Short  S;                                \
+    FT_Long   X, Y;                             \
+                                                \
+                                                \
+    /* Only use low 16bits, then sign extend */ \
+    S = (FT_Short)args[1];                      \
+    Y = (FT_Long)S;                             \
+    S = (FT_Short)args[0];                      \
+    X = S;                                      \
+                                                \
+    NORMalize( X, Y, &CUR.GS.freeVector );      \
+    COMPUTE_Funcs();                            \
+  }
+
+
+#define DO_GPV                     \
+    args[0] = CUR.GS.projVector.x; \
+    args[1] = CUR.GS.projVector.y;
+
+
+#define DO_GFV                     \
+    args[0] = CUR.GS.freeVector.x; \
+    args[1] = CUR.GS.freeVector.y;
+
+
+#define DO_SRP0                      \
+    CUR.GS.rp0 = (FT_UShort)args[0];
+
+
+#define DO_SRP1                      \
+    CUR.GS.rp1 = (FT_UShort)args[0];
+
+
+#define DO_SRP2                      \
+    CUR.GS.rp2 = (FT_UShort)args[0];
+
+
+#define DO_RTHG                                         \
+    CUR.GS.round_state = TT_Round_To_Half_Grid;         \
+    CUR.func_round = (TT_Round_Func)Round_To_Half_Grid;
+
+
+#define DO_RTG                                     \
+    CUR.GS.round_state = TT_Round_To_Grid;         \
+    CUR.func_round = (TT_Round_Func)Round_To_Grid;
+
+
+#define DO_RTDG                                           \
+    CUR.GS.round_state = TT_Round_To_Double_Grid;         \
+    CUR.func_round = (TT_Round_Func)Round_To_Double_Grid;
+
+
+#define DO_RUTG                                       \
+    CUR.GS.round_state = TT_Round_Up_To_Grid;         \
+    CUR.func_round = (TT_Round_Func)Round_Up_To_Grid;
+
+
+#define DO_RDTG                                         \
+    CUR.GS.round_state = TT_Round_Down_To_Grid;         \
+    CUR.func_round = (TT_Round_Func)Round_Down_To_Grid;
+
+
+#define DO_ROFF                                 \
+    CUR.GS.round_state = TT_Round_Off;          \
+    CUR.func_round = (TT_Round_Func)Round_None;
+
+
+#define DO_SROUND                                \
+    SET_SuperRound( 0x4000, args[0] );           \
+    CUR.GS.round_state = TT_Round_Super;         \
+    CUR.func_round = (TT_Round_Func)Round_Super;
+
+
+#define DO_S45ROUND                                 \
+    SET_SuperRound( 0x2D41, args[0] );              \
+    CUR.GS.round_state = TT_Round_Super_45;         \
+    CUR.func_round = (TT_Round_Func)Round_Super_45;
+
+
+#define DO_SLOOP                       \
+    if ( args[0] < 0 )                 \
+      CUR.error = TT_Err_Bad_Argument; \
+    else                               \
+      CUR.GS.loop = args[0];
+
+
+#define DO_SMD                         \
+    CUR.GS.minimum_distance = args[0];
+
+
+#define DO_SCVTCI                                     \
+    CUR.GS.control_value_cutin = (FT_F26Dot6)args[0];
+
+
+#define DO_SSWCI                                     \
+    CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
+
+
+    /* XXX: UNDOCUMENTED! or bug in the Windows engine? */
+    /*                                                  */
+    /* It seems that the value that is read here is     */
+    /* expressed in 16.16 format rather than in font    */
+    /* units.                                           */
+    /*                                                  */
+#define DO_SSW                                                 \
+    CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
+
+
+#define DO_FLIPON            \
+    CUR.GS.auto_flip = TRUE;
+
+
+#define DO_FLIPOFF            \
+    CUR.GS.auto_flip = FALSE;
+
+
+#define DO_SDB                             \
+    CUR.GS.delta_base = (FT_Short)args[0];
+
+
+#define DO_SDS                              \
+    CUR.GS.delta_shift = (FT_Short)args[0];
+
+
+#define DO_MD  /* nothing */
+
+
+#define DO_MPPEM              \
+    args[0] = CURRENT_Ppem();
+
+
+  /* Note: The pointSize should be irrelevant in a given font program; */
+  /*       we thus decide to return only the ppem.                     */
+#if 0
+
+#define DO_MPS                       \
+    args[0] = CUR.metrics.pointSize;
+
+#else
+
+#define DO_MPS                \
+    args[0] = CURRENT_Ppem();
+
+#endif /* 0 */
+
+
+#define DO_DUP         \
+    args[1] = args[0];
+
+
+#define DO_CLEAR     \
+    CUR.new_top = 0;
+
+
+#define DO_SWAP        \
+  {                    \
+    FT_Long  L;        \
+                       \
+                       \
+    L       = args[0]; \
+    args[0] = args[1]; \
+    args[1] = L;       \
+  }
+
+
+#define DO_DEPTH       \
+    args[0] = CUR.top;
+
+
+#define DO_CINDEX                           \
+  {                                         \
+    FT_Long  L;                             \
+                                            \
+                                            \
+    L = args[0];                            \
+                                            \
+    if ( L <= 0 || L > CUR.args )           \
+      CUR.error = TT_Err_Invalid_Reference; \
+    else                                    \
+      args[0] = CUR.stack[CUR.args - L];    \
+  }
+
+
+#define DO_JROT               \
+    if ( args[1] != 0 )       \
+    {                         \
+      CUR.IP      += args[0]; \
+      CUR.step_ins = FALSE;   \
+    }
+
+
+#define DO_JMPR             \
+    CUR.IP      += args[0]; \
+    CUR.step_ins = FALSE;
+
+
+#define DO_JROF               \
+    if ( args[1] == 0 )       \
+    {                         \
+      CUR.IP      += args[0]; \
+      CUR.step_ins = FALSE;   \
+    }
+
+
+#define DO_LT                        \
+    args[0] = ( args[0] < args[1] );
+
+
+#define DO_LTEQ                       \
+    args[0] = ( args[0] <= args[1] );
+
+
+#define DO_GT                        \
+    args[0] = ( args[0] > args[1] );
+
+
+#define DO_GTEQ                       \
+    args[0] = ( args[0] >= args[1] );
+
+
+#define DO_EQ                         \
+    args[0] = ( args[0] == args[1] );
+
+
+#define DO_NEQ                        \
+    args[0] = ( args[0] != args[1] );
+
+
+#define DO_ODD                                                  \
+    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 );
+
+
+#define DO_EVEN                                                \
+    args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 );
+
+
+#define DO_AND                        \
+    args[0] = ( args[0] && args[1] );
+
+
+#define DO_OR                         \
+    args[0] = ( args[0] || args[1] );
+
+
+#define DO_NOT          \
+    args[0] = !args[0];
+
+
+#define DO_ADD          \
+    args[0] += args[1];
+
+
+#define DO_SUB          \
+    args[0] -= args[1];
+
+
+#define DO_DIV                                      \
+    if ( args[1] == 0 )                             \
+      CUR.error = TT_Err_Divide_By_Zero;            \
+    else                                            \
+      args[0] = TT_MULDIV( args[0], 64L, args[1] );
+
+
+#define DO_MUL                                    \
+    args[0] = TT_MULDIV( args[0], args[1], 64L );
+
+
+#define DO_ABS                \
+    args[0] = ABS( args[0] );
+
+
+#define DO_NEG          \
+    args[0] = -args[0];
+
+
+#define DO_FLOOR    \
+    args[0] &= -64;
+
+
+#define DO_CEILING                    \
+    args[0] = ( args[0] + 63 ) & -64;
+
+
+#define DO_RS                          \
+   {                                   \
+     FT_ULong  I = (FT_ULong)args[0];  \
+                                       \
+                                       \
+     if ( BOUNDS( I, CUR.storeSize ) ) \
+     {                                 \
+       if ( CUR.pedantic_hinting )     \
+       {                               \
+         ARRAY_BOUND_ERROR;            \
+       }                               \
+       else                            \
+         args[0] = 0;                  \
+     }                                 \
+     else                              \
+       args[0] = CUR.storage[I];       \
+   }
+
+
+#define DO_WS                          \
+   {                                   \
+     FT_ULong  I = (FT_ULong)args[0];  \
+                                       \
+                                       \
+     if ( BOUNDS( I, CUR.storeSize ) ) \
+     {                                 \
+       if ( CUR.pedantic_hinting )     \
+       {                               \
+         ARRAY_BOUND_ERROR;            \
+       }                               \
+     }                                 \
+     else                              \
+       CUR.storage[I] = args[1];       \
+   }
+
+
+#define DO_RCVT                          \
+   {                                     \
+     FT_ULong  I = (FT_ULong)args[0];    \
+                                         \
+                                         \
+     if ( BOUNDS( I, CUR.cvtSize ) )     \
+     {                                   \
+       if ( CUR.pedantic_hinting )       \
+       {                                 \
+         ARRAY_BOUND_ERROR;              \
+       }                                 \
+       else                              \
+         args[0] = 0;                    \
+     }                                   \
+     else                                \
+       args[0] = CUR_Func_read_cvt( I ); \
+   }
+
+
+#define DO_WCVTP                         \
+   {                                     \
+     FT_ULong  I = (FT_ULong)args[0];    \
+                                         \
+                                         \
+     if ( BOUNDS( I, CUR.cvtSize ) )     \
+     {                                   \
+       if ( CUR.pedantic_hinting )       \
+       {                                 \
+         ARRAY_BOUND_ERROR;              \
+       }                                 \
+     }                                   \
+     else                                \
+       CUR_Func_write_cvt( I, args[1] ); \
+   }
+
+
+#define DO_WCVTF                                                \
+   {                                                            \
+     FT_ULong  I = (FT_ULong)args[0];                           \
+                                                                \
+                                                                \
+     if ( BOUNDS( I, CUR.cvtSize ) )                            \
+     {                                                          \
+       if ( CUR.pedantic_hinting )                              \
+       {                                                        \
+         ARRAY_BOUND_ERROR;                                     \
+       }                                                        \
+     }                                                          \
+     else                                                       \
+       CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
+   }
+
+
+#define DO_DEBUG                     \
+    CUR.error = TT_Err_Debug_OpCode;
+
+
+#define DO_ROUND                                                   \
+    args[0] = CUR_Func_round(                                      \
+                args[0],                                           \
+                CUR.tt_metrics.compensations[CUR.opcode - 0x68] );
+
+
+#define DO_NROUND                                                            \
+    args[0] = ROUND_None( args[0],                                           \
+                          CUR.tt_metrics.compensations[CUR.opcode - 0x6C] );
+
+
+#define DO_MAX               \
+    if ( args[1] > args[0] ) \
+      args[0] = args[1];
+
+
+#define DO_MIN               \
+    if ( args[1] < args[0] ) \
+      args[0] = args[1];
+
+
+#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+#undef  ARRAY_BOUND_ERROR
+#define ARRAY_BOUND_ERROR                   \
+    {                                       \
+      CUR.error = TT_Err_Invalid_Reference; \
+      return;                               \
+    }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SVTCA[a]:     Set (F and P) Vectors to Coordinate Axis                */
+  /* Opcode range: 0x00-0x01                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_SVTCA( INS_ARG )
+  {
+    DO_SVTCA
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SPVTCA[a]:    Set PVector to Coordinate Axis                          */
+  /* Opcode range: 0x02-0x03                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_SPVTCA( INS_ARG )
+  {
+    DO_SPVTCA
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFVTCA[a]:    Set FVector to Coordinate Axis                          */
+  /* Opcode range: 0x04-0x05                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_SFVTCA( INS_ARG )
+  {
+    DO_SFVTCA
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SPVTL[a]:     Set PVector To Line                                     */
+  /* Opcode range: 0x06-0x07                                               */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_SPVTL( INS_ARG )
+  {
+    DO_SPVTL
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFVTL[a]:     Set FVector To Line                                     */
+  /* Opcode range: 0x08-0x09                                               */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_SFVTL( INS_ARG )
+  {
+    DO_SFVTL
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFVTPV[]:     Set FVector To PVector                                  */
+  /* Opcode range: 0x0E                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_SFVTPV( INS_ARG )
+  {
+    DO_SFVTPV
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SPVFS[]:      Set PVector From Stack                                  */
+  /* Opcode range: 0x0A                                                    */
+  /* Stack:        f2.14 f2.14 -->                                         */
+  /*                                                                       */
+  static void
+  Ins_SPVFS( INS_ARG )
+  {
+    DO_SPVFS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SFVFS[]:      Set FVector From Stack                                  */
+  /* Opcode range: 0x0B                                                    */
+  /* Stack:        f2.14 f2.14 -->                                         */
+  /*                                                                       */
+  static void
+  Ins_SFVFS( INS_ARG )
+  {
+    DO_SFVFS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GPV[]:        Get Projection Vector                                   */
+  /* Opcode range: 0x0C                                                    */
+  /* Stack:        ef2.14 --> ef2.14                                       */
+  /*                                                                       */
+  static void
+  Ins_GPV( INS_ARG )
+  {
+    DO_GPV
+  }
+
+
+  /*************************************************************************/
+  /* GFV[]:        Get Freedom Vector                                      */
+  /* Opcode range: 0x0D                                                    */
+  /* Stack:        ef2.14 --> ef2.14                                       */
+  /*                                                                       */
+  static void
+  Ins_GFV( INS_ARG )
+  {
+    DO_GFV
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SRP0[]:       Set Reference Point 0                                   */
+  /* Opcode range: 0x10                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SRP0( INS_ARG )
+  {
+    DO_SRP0
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SRP1[]:       Set Reference Point 1                                   */
+  /* Opcode range: 0x11                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SRP1( INS_ARG )
+  {
+    DO_SRP1
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SRP2[]:       Set Reference Point 2                                   */
+  /* Opcode range: 0x12                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SRP2( INS_ARG )
+  {
+    DO_SRP2
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RTHG[]:       Round To Half Grid                                      */
+  /* Opcode range: 0x19                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_RTHG( INS_ARG )
+  {
+    DO_RTHG
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RTG[]:        Round To Grid                                           */
+  /* Opcode range: 0x18                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_RTG( INS_ARG )
+  {
+    DO_RTG
+  }
+
+
+  /*************************************************************************/
+  /* RTDG[]:       Round To Double Grid                                    */
+  /* Opcode range: 0x3D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_RTDG( INS_ARG )
+  {
+    DO_RTDG
+  }
+
+
+  /*************************************************************************/
+  /* RUTG[]:       Round Up To Grid                                        */
+  /* Opcode range: 0x7C                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_RUTG( INS_ARG )
+  {
+    DO_RUTG
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RDTG[]:       Round Down To Grid                                      */
+  /* Opcode range: 0x7D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_RDTG( INS_ARG )
+  {
+    DO_RDTG
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ROFF[]:       Round OFF                                               */
+  /* Opcode range: 0x7A                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_ROFF( INS_ARG )
+  {
+    DO_ROFF
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SROUND[]:     Super ROUND                                             */
+  /* Opcode range: 0x76                                                    */
+  /* Stack:        Eint8 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_SROUND( INS_ARG )
+  {
+    DO_SROUND
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* S45ROUND[]:   Super ROUND 45 degrees                                  */
+  /* Opcode range: 0x77                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_S45ROUND( INS_ARG )
+  {
+    DO_S45ROUND
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SLOOP[]:      Set LOOP variable                                       */
+  /* Opcode range: 0x17                                                    */
+  /* Stack:        int32? -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SLOOP( INS_ARG )
+  {
+    DO_SLOOP
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SMD[]:        Set Minimum Distance                                    */
+  /* Opcode range: 0x1A                                                    */
+  /* Stack:        f26.6 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_SMD( INS_ARG )
+  {
+    DO_SMD
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SCVTCI[]:     Set Control Value Table Cut In                          */
+  /* Opcode range: 0x1D                                                    */
+  /* Stack:        f26.6 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_SCVTCI( INS_ARG )
+  {
+    DO_SCVTCI
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SSWCI[]:      Set Single Width Cut In                                 */
+  /* Opcode range: 0x1E                                                    */
+  /* Stack:        f26.6 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_SSWCI( INS_ARG )
+  {
+    DO_SSWCI
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SSW[]:        Set Single Width                                        */
+  /* Opcode range: 0x1F                                                    */
+  /* Stack:        int32? -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SSW( INS_ARG )
+  {
+    DO_SSW
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPON[]:     Set auto-FLIP to ON                                     */
+  /* Opcode range: 0x4D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_FLIPON( INS_ARG )
+  {
+    DO_FLIPON
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPOFF[]:    Set auto-FLIP to OFF                                    */
+  /* Opcode range: 0x4E                                                    */
+  /* Stack: -->                                                            */
+  /*                                                                       */
+  static void
+  Ins_FLIPOFF( INS_ARG )
+  {
+    DO_FLIPOFF
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SANGW[]:      Set ANGle Weight                                        */
+  /* Opcode range: 0x7E                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SANGW( INS_ARG )
+  {
+    /* instruction not supported anymore */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SDB[]:        Set Delta Base                                          */
+  /* Opcode range: 0x5E                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SDB( INS_ARG )
+  {
+    DO_SDB
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SDS[]:        Set Delta Shift                                         */
+  /* Opcode range: 0x5F                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SDS( INS_ARG )
+  {
+    DO_SDS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MPPEM[]:      Measure Pixel Per EM                                    */
+  /* Opcode range: 0x4B                                                    */
+  /* Stack:        --> Euint16                                             */
+  /*                                                                       */
+  static void
+  Ins_MPPEM( INS_ARG )
+  {
+    DO_MPPEM
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MPS[]:        Measure Point Size                                      */
+  /* Opcode range: 0x4C                                                    */
+  /* Stack:        --> Euint16                                             */
+  /*                                                                       */
+  static void
+  Ins_MPS( INS_ARG )
+  {
+    DO_MPS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DUP[]:        DUPlicate the top stack's element                       */
+  /* Opcode range: 0x20                                                    */
+  /* Stack:        StkElt --> StkElt StkElt                                */
+  /*                                                                       */
+  static void
+  Ins_DUP( INS_ARG )
+  {
+    DO_DUP
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* POP[]:        POP the stack's top element                             */
+  /* Opcode range: 0x21                                                    */
+  /* Stack:        StkElt -->                                              */
+  /*                                                                       */
+  static void
+  Ins_POP( INS_ARG )
+  {
+    /* nothing to do */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* CLEAR[]:      CLEAR the entire stack                                  */
+  /* Opcode range: 0x22                                                    */
+  /* Stack:        StkElt... -->                                           */
+  /*                                                                       */
+  static void
+  Ins_CLEAR( INS_ARG )
+  {
+    DO_CLEAR
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SWAP[]:       SWAP the stack's top two elements                       */
+  /* Opcode range: 0x23                                                    */
+  /* Stack:        2 * StkElt --> 2 * StkElt                               */
+  /*                                                                       */
+  static void
+  Ins_SWAP( INS_ARG )
+  {
+    DO_SWAP
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DEPTH[]:      return the stack DEPTH                                  */
+  /* Opcode range: 0x24                                                    */
+  /* Stack:        --> uint32                                              */
+  /*                                                                       */
+  static void
+  Ins_DEPTH( INS_ARG )
+  {
+    DO_DEPTH
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* CINDEX[]:     Copy INDEXed element                                    */
+  /* Opcode range: 0x25                                                    */
+  /* Stack:        int32 --> StkElt                                        */
+  /*                                                                       */
+  static void
+  Ins_CINDEX( INS_ARG )
+  {
+    DO_CINDEX
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* EIF[]:        End IF                                                  */
+  /* Opcode range: 0x59                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_EIF( INS_ARG )
+  {
+    /* nothing to do */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* JROT[]:       Jump Relative On True                                   */
+  /* Opcode range: 0x78                                                    */
+  /* Stack:        StkElt int32 -->                                        */
+  /*                                                                       */
+  static void
+  Ins_JROT( INS_ARG )
+  {
+    DO_JROT
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* JMPR[]:       JuMP Relative                                           */
+  /* Opcode range: 0x1C                                                    */
+  /* Stack:        int32 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_JMPR( INS_ARG )
+  {
+    DO_JMPR
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* JROF[]:       Jump Relative On False                                  */
+  /* Opcode range: 0x79                                                    */
+  /* Stack:        StkElt int32 -->                                        */
+  /*                                                                       */
+  static void
+  Ins_JROF( INS_ARG )
+  {
+    DO_JROF
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* LT[]:         Less Than                                               */
+  /* Opcode range: 0x50                                                    */
+  /* Stack:        int32? int32? --> bool                                  */
+  /*                                                                       */
+  static void
+  Ins_LT( INS_ARG )
+  {
+    DO_LT
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* LTEQ[]:       Less Than or EQual                                      */
+  /* Opcode range: 0x51                                                    */
+  /* Stack:        int32? int32? --> bool                                  */
+  /*                                                                       */
+  static void
+  Ins_LTEQ( INS_ARG )
+  {
+    DO_LTEQ
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GT[]:         Greater Than                                            */
+  /* Opcode range: 0x52                                                    */
+  /* Stack:        int32? int32? --> bool                                  */
+  /*                                                                       */
+  static void
+  Ins_GT( INS_ARG )
+  {
+    DO_GT
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GTEQ[]:       Greater Than or EQual                                   */
+  /* Opcode range: 0x53                                                    */
+  /* Stack:        int32? int32? --> bool                                  */
+  /*                                                                       */
+  static void
+  Ins_GTEQ( INS_ARG )
+  {
+    DO_GTEQ
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* EQ[]:         EQual                                                   */
+  /* Opcode range: 0x54                                                    */
+  /* Stack:        StkElt StkElt --> bool                                  */
+  /*                                                                       */
+  static void
+  Ins_EQ( INS_ARG )
+  {
+    DO_EQ
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NEQ[]:        Not EQual                                               */
+  /* Opcode range: 0x55                                                    */
+  /* Stack:        StkElt StkElt --> bool                                  */
+  /*                                                                       */
+  static void
+  Ins_NEQ( INS_ARG )
+  {
+    DO_NEQ
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ODD[]:        Is ODD                                                  */
+  /* Opcode range: 0x56                                                    */
+  /* Stack:        f26.6 --> bool                                          */
+  /*                                                                       */
+  static void
+  Ins_ODD( INS_ARG )
+  {
+    DO_ODD
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* EVEN[]:       Is EVEN                                                 */
+  /* Opcode range: 0x57                                                    */
+  /* Stack:        f26.6 --> bool                                          */
+  /*                                                                       */
+  static void
+  Ins_EVEN( INS_ARG )
+  {
+    DO_EVEN
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* AND[]:        logical AND                                             */
+  /* Opcode range: 0x5A                                                    */
+  /* Stack:        uint32 uint32 --> uint32                                */
+  /*                                                                       */
+  static void
+  Ins_AND( INS_ARG )
+  {
+    DO_AND
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* OR[]:         logical OR                                              */
+  /* Opcode range: 0x5B                                                    */
+  /* Stack:        uint32 uint32 --> uint32                                */
+  /*                                                                       */
+  static void
+  Ins_OR( INS_ARG )
+  {
+    DO_OR
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NOT[]:        logical NOT                                             */
+  /* Opcode range: 0x5C                                                    */
+  /* Stack:        StkElt --> uint32                                       */
+  /*                                                                       */
+  static void
+  Ins_NOT( INS_ARG )
+  {
+    DO_NOT
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ADD[]:        ADD                                                     */
+  /* Opcode range: 0x60                                                    */
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */
+  /*                                                                       */
+  static void
+  Ins_ADD( INS_ARG )
+  {
+    DO_ADD
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SUB[]:        SUBtract                                                */
+  /* Opcode range: 0x61                                                    */
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */
+  /*                                                                       */
+  static void
+  Ins_SUB( INS_ARG )
+  {
+    DO_SUB
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DIV[]:        DIVide                                                  */
+  /* Opcode range: 0x62                                                    */
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */
+  /*                                                                       */
+  static void
+  Ins_DIV( INS_ARG )
+  {
+    DO_DIV
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MUL[]:        MULtiply                                                */
+  /* Opcode range: 0x63                                                    */
+  /* Stack:        f26.6 f26.6 --> f26.6                                   */
+  /*                                                                       */
+  static void
+  Ins_MUL( INS_ARG )
+  {
+    DO_MUL
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ABS[]:        ABSolute value                                          */
+  /* Opcode range: 0x64                                                    */
+  /* Stack:        f26.6 --> f26.6                                         */
+  /*                                                                       */
+  static void
+  Ins_ABS( INS_ARG )
+  {
+    DO_ABS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NEG[]:        NEGate                                                  */
+  /* Opcode range: 0x65                                                    */
+  /* Stack: f26.6 --> f26.6                                                */
+  /*                                                                       */
+  static void
+  Ins_NEG( INS_ARG )
+  {
+    DO_NEG
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLOOR[]:      FLOOR                                                   */
+  /* Opcode range: 0x66                                                    */
+  /* Stack:        f26.6 --> f26.6                                         */
+  /*                                                                       */
+  static void
+  Ins_FLOOR( INS_ARG )
+  {
+    DO_FLOOR
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* CEILING[]:    CEILING                                                 */
+  /* Opcode range: 0x67                                                    */
+  /* Stack:        f26.6 --> f26.6                                         */
+  /*                                                                       */
+  static void
+  Ins_CEILING( INS_ARG )
+  {
+    DO_CEILING
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RS[]:         Read Store                                              */
+  /* Opcode range: 0x43                                                    */
+  /* Stack:        uint32 --> uint32                                       */
+  /*                                                                       */
+  static void
+  Ins_RS( INS_ARG )
+  {
+    DO_RS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* WS[]:         Write Store                                             */
+  /* Opcode range: 0x42                                                    */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_WS( INS_ARG )
+  {
+    DO_WS
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* WCVTP[]:      Write CVT in Pixel units                                */
+  /* Opcode range: 0x44                                                    */
+  /* Stack:        f26.6 uint32 -->                                        */
+  /*                                                                       */
+  static void
+  Ins_WCVTP( INS_ARG )
+  {
+    DO_WCVTP
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* WCVTF[]:      Write CVT in Funits                                     */
+  /* Opcode range: 0x70                                                    */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_WCVTF( INS_ARG )
+  {
+    DO_WCVTF
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RCVT[]:       Read CVT                                                */
+  /* Opcode range: 0x45                                                    */
+  /* Stack:        uint32 --> f26.6                                        */
+  /*                                                                       */
+  static void
+  Ins_RCVT( INS_ARG )
+  {
+    DO_RCVT
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* AA[]:         Adjust Angle                                            */
+  /* Opcode range: 0x7F                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_AA( INS_ARG )
+  {
+    /* intentionally no longer supported */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DEBUG[]:      DEBUG.  Unsupported.                                    */
+  /* Opcode range: 0x4F                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  /* Note: The original instruction pops a value from the stack.           */
+  /*                                                                       */
+  static void
+  Ins_DEBUG( INS_ARG )
+  {
+    DO_DEBUG
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ROUND[ab]:    ROUND value                                             */
+  /* Opcode range: 0x68-0x6B                                               */
+  /* Stack:        f26.6 --> f26.6                                         */
+  /*                                                                       */
+  static void
+  Ins_ROUND( INS_ARG )
+  {
+    DO_ROUND
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NROUND[ab]:   No ROUNDing of value                                    */
+  /* Opcode range: 0x6C-0x6F                                               */
+  /* Stack:        f26.6 --> f26.6                                         */
+  /*                                                                       */
+  static void
+  Ins_NROUND( INS_ARG )
+  {
+    DO_NROUND
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MAX[]:        MAXimum                                                 */
+  /* Opcode range: 0x68                                                    */
+  /* Stack:        int32? int32? --> int32                                 */
+  /*                                                                       */
+  static void
+  Ins_MAX( INS_ARG )
+  {
+    DO_MAX
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MIN[]:        MINimum                                                 */
+  /* Opcode range: 0x69                                                    */
+  /* Stack:        int32? int32? --> int32                                 */
+  /*                                                                       */
+  static void
+  Ins_MIN( INS_ARG )
+  {
+    DO_MIN
+  }
+
+
+#endif  /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The following functions are called as is within the switch statement. */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MINDEX[]:     Move INDEXed element                                    */
+  /* Opcode range: 0x26                                                    */
+  /* Stack:        int32? --> StkElt                                       */
+  /*                                                                       */
+  static void
+  Ins_MINDEX( INS_ARG )
+  {
+    FT_Long  L, K;
+
+
+    L = args[0];
+
+    if ( L <= 0 || L > CUR.args )
+    {
+      CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    K = CUR.stack[CUR.args - L];
+
+    MEM_Move( &CUR.stack[CUR.args - L    ],
+              &CUR.stack[CUR.args - L + 1],
+              ( L - 1 ) * sizeof ( FT_Long ) );
+
+    CUR.stack[CUR.args - 1] = K;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ROLL[]:       ROLL top three elements                                 */
+  /* Opcode range: 0x8A                                                    */
+  /* Stack:        3 * StkElt --> 3 * StkElt                               */
+  /*                                                                       */
+  static void
+  Ins_ROLL( INS_ARG )
+  {
+    FT_Long  A, B, C;
+
+    FT_UNUSED_EXEC;
+
+
+    A = args[2];
+    B = args[1];
+    C = args[0];
+
+    args[2] = C;
+    args[1] = A;
+    args[0] = B;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MANAGING THE FLOW OF CONTROL                                          */
+  /*                                                                       */
+  /*   Instructions appear in the specification's order.                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  static FT_Bool
+  SkipCode( EXEC_OP )
+  {
+    CUR.IP += CUR.length;
+
+    if ( CUR.IP < CUR.codeSize )
+    {
+      CUR.opcode = CUR.code[CUR.IP];
+
+      CUR.length = opcode_length[CUR.opcode];
+      if ( CUR.length < 0 )
+      {
+        if ( CUR.IP + 1 > CUR.codeSize )
+          goto Fail_Overflow;
+        CUR.length = CUR.code[CUR.IP + 1] + 2;
+      }
+
+      if ( CUR.IP + CUR.length <= CUR.codeSize )
+        return SUCCESS;
+    }
+
+  Fail_Overflow:
+    CUR.error = TT_Err_Code_Overflow;
+    return FAILURE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IF[]:         IF test                                                 */
+  /* Opcode range: 0x58                                                    */
+  /* Stack:        StkElt -->                                              */
+  /*                                                                       */
+  static void
+  Ins_IF( INS_ARG )
+  {
+    FT_Int   nIfs;
+    FT_Bool  Out;
+
+
+    if ( args[0] != 0 )
+      return;
+
+    nIfs = 1;
+    Out = 0;
+
+    do
+    {
+      if ( SKIP_Code() == FAILURE )
+        return;
+
+      switch ( CUR.opcode )
+      {
+      case 0x58:      /* IF */
+        nIfs++;
+        break;
+
+      case 0x1B:      /* ELSE */
+        Out = FT_BOOL( nIfs == 1 );
+        break;
+
+      case 0x59:      /* EIF */
+        nIfs--;
+        Out = FT_BOOL( nIfs == 0 );
+        break;
+      }
+    } while ( Out == 0 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ELSE[]:       ELSE                                                    */
+  /* Opcode range: 0x1B                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_ELSE( INS_ARG )
+  {
+    FT_Int  nIfs;
+
+    FT_UNUSED_ARG;
+
+
+    nIfs = 1;
+
+    do
+    {
+      if ( SKIP_Code() == FAILURE )
+        return;
+
+      switch ( CUR.opcode )
+      {
+      case 0x58:    /* IF */
+        nIfs++;
+        break;
+
+      case 0x59:    /* EIF */
+        nIfs--;
+        break;
+      }
+    } while ( nIfs != 0 );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS                         */
+  /*                                                                       */
+  /*   Instructions appear in the specification's order.                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FDEF[]:       Function DEFinition                                     */
+  /* Opcode range: 0x2C                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_FDEF( INS_ARG )
+  {
+    FT_ULong       n;
+    TT_DefRecord*  rec;
+    TT_DefRecord*  limit;
+
+
+    /* some font programs are broken enough to redefine functions! */
+    /* We will then parse the current table.                       */
+
+    rec   = CUR.FDefs;
+    limit = rec + CUR.numFDefs;
+    n     = args[0];
+
+    for ( ; rec < limit; rec++ )
+    {
+      if ( rec->opc == n )
+        break;
+    }
+
+    if ( rec == limit )
+    {
+      /* check that there is enough room for new functions */
+      if ( CUR.numFDefs >= CUR.maxFDefs )
+      {
+        CUR.error = TT_Err_Too_Many_Function_Defs;
+        return;
+      }
+      CUR.numFDefs++;
+    }
+
+    rec->range  = CUR.curRange;
+    rec->opc    = n;
+    rec->start  = CUR.IP + 1;
+    rec->active = TRUE;
+
+    if ( n > CUR.maxFunc )
+      CUR.maxFunc = n;
+
+    /* Now skip the whole function definition. */
+    /* We don't allow nested IDEFS & FDEFs.    */
+
+    while ( SKIP_Code() == SUCCESS )
+    {
+      switch ( CUR.opcode )
+      {
+      case 0x89:    /* IDEF */
+      case 0x2C:    /* FDEF */
+        CUR.error = TT_Err_Nested_DEFS;
+        return;
+
+      case 0x2D:   /* ENDF */
+        return;
+      }
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ENDF[]:       END Function definition                                 */
+  /* Opcode range: 0x2D                                                    */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_ENDF( INS_ARG )
+  {
+    TT_CallRec*  pRec;
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.callTop <= 0 )     /* We encountered an ENDF without a call */
+    {
+      CUR.error = TT_Err_ENDF_In_Exec_Stream;
+      return;
+    }
+
+    CUR.callTop--;
+
+    pRec = &CUR.callStack[CUR.callTop];
+
+    pRec->Cur_Count--;
+
+    CUR.step_ins = FALSE;
+
+    if ( pRec->Cur_Count > 0 )
+    {
+      CUR.callTop++;
+      CUR.IP = pRec->Cur_Restart;
+    }
+    else
+      /* Loop through the current function */
+      INS_Goto_CodeRange( pRec->Caller_Range,
+                          pRec->Caller_IP );
+
+    /* Exit the current call frame.                      */
+
+    /* NOTE: If the last intruction of a program is a    */
+    /*       CALL or LOOPCALL, the return address is     */
+    /*       always out of the code range.  This is a    */
+    /*       valid address, and it is why we do not test */
+    /*       the result of Ins_Goto_CodeRange() here!    */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* CALL[]:       CALL function                                           */
+  /* Opcode range: 0x2B                                                    */
+  /* Stack:        uint32? -->                                             */
+  /*                                                                       */
+  static void
+  Ins_CALL( INS_ARG )
+  {
+    FT_ULong       F;
+    TT_CallRec*    pCrec;
+    TT_DefRecord*  def;
+
+
+    /* first of all, check the index */
+
+    F = args[0];
+    if ( BOUNDS( F, CUR.maxFunc + 1 ) )
+      goto Fail;
+
+    /* Except for some old Apple fonts, all functions in a TrueType */
+    /* font are defined in increasing order, starting from 0.  This */
+    /* means that we normally have                                  */
+    /*                                                              */
+    /*    CUR.maxFunc+1 == CUR.numFDefs                             */
+    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
+    /*                                                              */
+    /* If this isn't true, we need to look up the function table.   */
+
+    def = CUR.FDefs + F;
+    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+    {
+      /* look up the FDefs table */
+      TT_DefRecord*  limit;
+
+
+      def   = CUR.FDefs;
+      limit = def + CUR.numFDefs;
+
+      while ( def < limit && def->opc != F )
+        def++;
+
+      if ( def == limit )
+        goto Fail;
+    }
+
+    /* check that the function is active */
+    if ( !def->active )
+      goto Fail;
+
+    /* check the call stack */
+    if ( CUR.callTop >= CUR.callSize )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    pCrec = CUR.callStack + CUR.callTop;
+
+    pCrec->Caller_Range = CUR.curRange;
+    pCrec->Caller_IP    = CUR.IP + 1;
+    pCrec->Cur_Count    = 1;
+    pCrec->Cur_Restart  = def->start;
+
+    CUR.callTop++;
+
+    INS_Goto_CodeRange( def->range,
+                        def->start );
+
+    CUR.step_ins = FALSE;
+    return;
+
+  Fail:
+    CUR.error = TT_Err_Invalid_Reference;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* LOOPCALL[]:   LOOP and CALL function                                  */
+  /* Opcode range: 0x2A                                                    */
+  /* Stack:        uint32? Eint16? -->                                     */
+  /*                                                                       */
+  static void
+  Ins_LOOPCALL( INS_ARG )
+  {
+    FT_ULong       F;
+    TT_CallRec*    pCrec;
+    TT_DefRecord*  def;
+
+
+    /* first of all, check the index */
+    F = args[1];
+    if ( BOUNDS( F, CUR.maxFunc + 1 ) )
+      goto Fail;
+
+    /* Except for some old Apple fonts, all functions in a TrueType */
+    /* font are defined in increasing order, starting from 0.  This */
+    /* means that we normally have                                  */
+    /*                                                              */
+    /*    CUR.maxFunc+1 == CUR.numFDefs                             */
+    /*    CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc             */
+    /*                                                              */
+    /* If this isn't true, we need to look up the function table.   */
+
+    def = CUR.FDefs + F;
+    if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F )
+    {
+      /* look up the FDefs table */
+      TT_DefRecord*  limit;
+
+
+      def   = CUR.FDefs;
+      limit = def + CUR.numFDefs;
+
+      while ( def < limit && def->opc != F )
+        def++;
+
+      if ( def == limit )
+        goto Fail;
+    }
+
+    /* check that the function is active */
+    if ( !def->active )
+      goto Fail;
+
+    /* check stack */
+    if ( CUR.callTop >= CUR.callSize )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    if ( args[0] > 0 )
+    {
+      pCrec = CUR.callStack + CUR.callTop;
+
+      pCrec->Caller_Range = CUR.curRange;
+      pCrec->Caller_IP    = CUR.IP + 1;
+      pCrec->Cur_Count    = (FT_Int)args[0];
+      pCrec->Cur_Restart  = def->start;
+
+      CUR.callTop++;
+
+      INS_Goto_CodeRange( def->range, def->start );
+
+      CUR.step_ins = FALSE;
+    }
+    return;
+
+  Fail:
+    CUR.error = TT_Err_Invalid_Reference;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IDEF[]:       Instruction DEFinition                                  */
+  /* Opcode range: 0x89                                                    */
+  /* Stack:        Eint8 -->                                               */
+  /*                                                                       */
+  static void
+  Ins_IDEF( INS_ARG )
+  {
+    TT_DefRecord*  def;
+    TT_DefRecord*  limit;
+
+
+    /*  First of all, look for the same function in our table */
+
+    def   = CUR.IDefs;
+    limit = def + CUR.numIDefs;
+
+    for ( ; def < limit; def++ )
+      if ( def->opc == (FT_ULong)args[0] )
+        break;
+
+    if ( def == limit )
+    {
+      /* check that there is enough room for a new instruction */
+      if ( CUR.numIDefs >= CUR.maxIDefs )
+      {
+        CUR.error = TT_Err_Too_Many_Instruction_Defs;
+        return;
+      }
+      CUR.numIDefs++;
+    }
+
+    def->opc    = args[0];
+    def->start  = CUR.IP+1;
+    def->range  = CUR.curRange;
+    def->active = TRUE;
+
+    if ( (FT_ULong)args[0] > CUR.maxIns )
+      CUR.maxIns = args[0];
+
+    /* Now skip the whole function definition. */
+    /* We don't allow nested IDEFs & FDEFs.    */
+
+    while ( SKIP_Code() == SUCCESS )
+    {
+      switch ( CUR.opcode )
+      {
+      case 0x89:   /* IDEF */
+      case 0x2C:   /* FDEF */
+        CUR.error = TT_Err_Nested_DEFS;
+        return;
+      case 0x2D:   /* ENDF */
+        return;
+      }
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* PUSHING DATA ONTO THE INTERPRETER STACK                               */
+  /*                                                                       */
+  /*   Instructions appear in the specification's order.                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NPUSHB[]:     PUSH N Bytes                                            */
+  /* Opcode range: 0x40                                                    */
+  /* Stack:        --> uint32...                                           */
+  /*                                                                       */
+  static void
+  Ins_NPUSHB( INS_ARG )
+  {
+    FT_UShort  L, K;
+
+
+    L = (FT_UShort)CUR.code[CUR.IP + 1];
+
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    for ( K = 1; K <= L; K++ )
+      args[K - 1] = CUR.code[CUR.IP + K + 1];
+
+    CUR.new_top += L;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* NPUSHW[]:     PUSH N Words                                            */
+  /* Opcode range: 0x41                                                    */
+  /* Stack:        --> int32...                                            */
+  /*                                                                       */
+  static void
+  Ins_NPUSHW( INS_ARG )
+  {
+    FT_UShort  L, K;
+
+
+    L = (FT_UShort)CUR.code[CUR.IP + 1];
+
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    CUR.IP += 2;
+
+    for ( K = 0; K < L; K++ )
+      args[K] = GET_ShortIns();
+
+    CUR.step_ins = FALSE;
+    CUR.new_top += L;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* PUSHB[abc]:   PUSH Bytes                                              */
+  /* Opcode range: 0xB0-0xB7                                               */
+  /* Stack:        --> uint32...                                           */
+  /*                                                                       */
+  static void
+  Ins_PUSHB( INS_ARG )
+  {
+    FT_UShort  L, K;
+
+
+    L = (FT_UShort)(CUR.opcode - 0xB0 + 1);
+
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    for ( K = 1; K <= L; K++ )
+      args[K - 1] = CUR.code[CUR.IP + K];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* PUSHW[abc]:   PUSH Words                                              */
+  /* Opcode range: 0xB8-0xBF                                               */
+  /* Stack:        --> int32...                                            */
+  /*                                                                       */
+  static void
+  Ins_PUSHW( INS_ARG )
+  {
+    FT_UShort  L, K;
+
+
+    L = (FT_UShort)(CUR.opcode - 0xB8 + 1);
+
+    if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
+    {
+      CUR.error = TT_Err_Stack_Overflow;
+      return;
+    }
+
+    CUR.IP++;
+
+    for ( K = 0; K < L; K++ )
+      args[K] = GET_ShortIns();
+
+    CUR.step_ins = FALSE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MANAGING THE GRAPHICS STATE                                           */
+  /*                                                                       */
+  /*  Instructions appear in the specs' order.                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GC[a]:        Get Coordinate projected onto                           */
+  /* Opcode range: 0x46-0x47                                               */
+  /* Stack:        uint32 --> f26.6                                        */
+  /*                                                                       */
+  /* BULLSHIT: Measures from the original glyph must be taken along the    */
+  /*           dual projection vector!                                     */
+  /*                                                                       */
+  static void
+  Ins_GC( INS_ARG )
+  {
+    FT_ULong    L;
+    FT_F26Dot6  R;
+
+
+    L = (FT_ULong)args[0];
+
+    if ( BOUNDS( L, CUR.zp2.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+      {
+        CUR.error = TT_Err_Invalid_Reference;
+        return;
+      }
+      else
+        R = 0;
+    }
+    else
+    {
+      if ( CUR.opcode & 1 )
+        R = CUR_Func_dualproj( CUR.zp2.org + L, NULL_Vector );
+      else
+        R = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector );
+    }
+
+    args[0] = R;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SCFS[]:       Set Coordinate From Stack                               */
+  /* Opcode range: 0x48                                                    */
+  /* Stack:        f26.6 uint32 -->                                        */
+  /*                                                                       */
+  /* Formula:                                                              */
+  /*                                                                       */
+  /*   OA := OA + ( value - OA.p )/( f.p ) * f                             */
+  /*                                                                       */
+  static void
+  Ins_SCFS( INS_ARG )
+  {
+    FT_Long    K;
+    FT_UShort  L;
+
+
+    L = (FT_UShort)args[0];
+
+    if ( BOUNDS( L, CUR.zp2.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    K = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector );
+
+    CUR_Func_move( &CUR.zp2, L, args[1] - K );
+
+    /* not part of the specs, but here for safety */
+
+    if ( CUR.GS.gep2 == 0 )
+      CUR.zp2.org[L] = CUR.zp2.cur[L];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MD[a]:        Measure Distance                                        */
+  /* Opcode range: 0x49-0x4A                                               */
+  /* Stack:        uint32 uint32 --> f26.6                                 */
+  /*                                                                       */
+  /* BULLSHIT: Measure taken in the original glyph must be along the dual  */
+  /*           projection vector.                                          */
+  /*                                                                       */
+  /* Second BULLSHIT: Flag attributes are inverted!                        */
+  /*                  0 => measure distance in original outline            */
+  /*                  1 => measure distance in grid-fitted outline         */
+  /*                                                                       */
+  /* Third one: `zp0 - zp1', and not `zp2 - zp1!                           */
+  /*                                                                       */
+  static void
+  Ins_MD( INS_ARG )
+  {
+    FT_UShort   K, L;
+    FT_F26Dot6  D;
+
+
+    K = (FT_UShort)args[1];
+    L = (FT_UShort)args[0];
+
+    if( BOUNDS( L, CUR.zp0.n_points ) ||
+        BOUNDS( K, CUR.zp1.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+      {
+        CUR.error = TT_Err_Invalid_Reference;
+        return;
+      }
+      D = 0;
+    }
+    else
+    {
+      if ( CUR.opcode & 1 )
+        D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K );
+      else
+        D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K );
+    }
+
+    args[0] = D;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SDPVTL[a]:    Set Dual PVector to Line                                */
+  /* Opcode range: 0x86-0x87                                               */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_SDPVTL( INS_ARG )
+  {
+    FT_Long    A, B, C;
+    FT_UShort  p1, p2;   /* was FT_Int in pas type ERROR */
+
+
+    p1 = (FT_UShort)args[1];
+    p2 = (FT_UShort)args[0];
+
+    if ( BOUNDS( p2, CUR.zp1.n_points ) ||
+         BOUNDS( p1, CUR.zp2.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    {
+      FT_Vector* v1 = CUR.zp1.org + p2;
+      FT_Vector* v2 = CUR.zp2.org + p1;
+
+
+      A = v1->x - v2->x;
+      B = v1->y - v2->y;
+    }
+
+    if ( ( CUR.opcode & 1 ) != 0 )
+    {
+      C =  B;   /* counter clockwise rotation */
+      B =  A;
+      A = -C;
+    }
+
+    NORMalize( A, B, &CUR.GS.dualVector );
+
+    {
+      FT_Vector*  v1 = CUR.zp1.cur + p2;
+      FT_Vector*  v2 = CUR.zp2.cur + p1;
+
+
+      A = v1->x - v2->x;
+      B = v1->y - v2->y;
+    }
+
+    if ( ( CUR.opcode & 1 ) != 0 )
+    {
+      C =  B;   /* counter clockwise rotation */
+      B =  A;
+      A = -C;
+    }
+
+    NORMalize( A, B, &CUR.GS.projVector );
+
+    COMPUTE_Funcs();
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SZP0[]:       Set Zone Pointer 0                                      */
+  /* Opcode range: 0x13                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SZP0( INS_ARG )
+  {
+    switch ( (FT_Int)args[0] )
+    {
+    case 0:
+      CUR.zp0 = CUR.twilight;
+      break;
+
+    case 1:
+      CUR.zp0 = CUR.pts;
+      break;
+
+    default:
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    CUR.GS.gep0 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SZP1[]:       Set Zone Pointer 1                                      */
+  /* Opcode range: 0x14                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SZP1( INS_ARG )
+  {
+    switch ( (FT_Int)args[0] )
+    {
+    case 0:
+      CUR.zp1 = CUR.twilight;
+      break;
+
+    case 1:
+      CUR.zp1 = CUR.pts;
+      break;
+
+    default:
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    CUR.GS.gep1 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SZP2[]:       Set Zone Pointer 2                                      */
+  /* Opcode range: 0x15                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SZP2( INS_ARG )
+  {
+    switch ( (FT_Int)args[0] )
+    {
+    case 0:
+      CUR.zp2 = CUR.twilight;
+      break;
+
+    case 1:
+      CUR.zp2 = CUR.pts;
+      break;
+
+    default:
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    CUR.GS.gep2 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SZPS[]:       Set Zone PointerS                                       */
+  /* Opcode range: 0x16                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SZPS( INS_ARG )
+  {
+    switch ( (FT_Int)args[0] )
+    {
+    case 0:
+      CUR.zp0 = CUR.twilight;
+      break;
+
+    case 1:
+      CUR.zp0 = CUR.pts;
+      break;
+
+    default:
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    CUR.zp1 = CUR.zp0;
+    CUR.zp2 = CUR.zp0;
+
+    CUR.GS.gep0 = (FT_UShort)args[0];
+    CUR.GS.gep1 = (FT_UShort)args[0];
+    CUR.GS.gep2 = (FT_UShort)args[0];
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* INSTCTRL[]:   INSTruction ConTRoL                                     */
+  /* Opcode range: 0x8e                                                    */
+  /* Stack:        int32 int32 -->                                         */
+  /*                                                                       */
+  static void
+  Ins_INSTCTRL( INS_ARG )
+  {
+    FT_Long  K, L;
+
+
+    K = args[1];
+    L = args[0];
+
+    if ( K < 1 || K > 2 )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    if ( L != 0 )
+        L = K;
+
+    CUR.GS.instruct_control = FT_BOOL(
+      ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SCANCTRL[]:   SCAN ConTRoL                                            */
+  /* Opcode range: 0x85                                                    */
+  /* Stack:        uint32? -->                                             */
+  /*                                                                       */
+  static void
+  Ins_SCANCTRL( INS_ARG )
+  {
+    FT_Int  A;
+
+
+    /* Get Threshold */
+    A = (FT_Int)( args[0] & 0xFF );
+
+    if ( A == 0xFF )
+    {
+      CUR.GS.scan_control = TRUE;
+      return;
+    }
+    else if ( A == 0 )
+    {
+      CUR.GS.scan_control = FALSE;
+      return;
+    }
+
+    A *= 64;
+
+#if 0
+    if ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A )
+      CUR.GS.scan_control = TRUE;
+#endif
+
+    if ( (args[0] & 0x200) != 0 && CUR.tt_metrics.rotated )
+      CUR.GS.scan_control = TRUE;
+
+    if ( (args[0] & 0x400) != 0 && CUR.tt_metrics.stretched )
+      CUR.GS.scan_control = TRUE;
+
+#if 0
+    if ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A )
+      CUR.GS.scan_control = FALSE;
+#endif
+
+    if ( (args[0] & 0x1000) != 0 && CUR.tt_metrics.rotated )
+      CUR.GS.scan_control = FALSE;
+
+    if ( (args[0] & 0x2000) != 0 && CUR.tt_metrics.stretched )
+      CUR.GS.scan_control = FALSE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SCANTYPE[]:   SCAN TYPE                                               */
+  /* Opcode range: 0x8D                                                    */
+  /* Stack:        uint32? -->                                             */
+  /*                                                                       */
+  static void
+  Ins_SCANTYPE( INS_ARG )
+  {
+    /* for compatibility with future enhancements, */
+    /* we must ignore new modes                    */
+
+    if ( args[0] >= 0 && args[0] <= 5 )
+    {
+      if ( args[0] == 3 )
+        args[0] = 2;
+
+      CUR.GS.scan_type = (FT_Int)args[0];
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MANAGING OUTLINES                                                     */
+  /*                                                                       */
+  /*   Instructions appear in the specification's order.                   */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPPT[]:     FLIP PoinT                                              */
+  /* Opcode range: 0x80                                                    */
+  /* Stack:        uint32... -->                                           */
+  /*                                                                       */
+  static void
+  Ins_FLIPPT( INS_ARG )
+  {
+    FT_UShort  point;
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.top < CUR.GS.loop )
+    {
+      CUR.error = TT_Err_Too_Few_Arguments;
+      return;
+    }
+
+    while ( CUR.GS.loop > 0 )
+    {
+      CUR.args--;
+
+      point = (FT_UShort)CUR.stack[CUR.args];
+
+      if ( BOUNDS( point, CUR.pts.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+        CUR.pts.tags[point] ^= FT_Curve_Tag_On;
+
+      CUR.GS.loop--;
+    }
+
+    CUR.GS.loop = 1;
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPRGON[]:   FLIP RanGe ON                                           */
+  /* Opcode range: 0x81                                                    */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_FLIPRGON( INS_ARG )
+  {
+    FT_UShort  I, K, L;
+
+
+    K = (FT_UShort)args[1];
+    L = (FT_UShort)args[0];
+
+    if ( BOUNDS( K, CUR.pts.n_points ) ||
+         BOUNDS( L, CUR.pts.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    for ( I = L; I <= K; I++ )
+      CUR.pts.tags[I] |= FT_Curve_Tag_On;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* FLIPRGOFF:    FLIP RanGe OFF                                          */
+  /* Opcode range: 0x82                                                    */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_FLIPRGOFF( INS_ARG )
+  {
+    FT_UShort  I, K, L;
+
+
+    K = (FT_UShort)args[1];
+    L = (FT_UShort)args[0];
+
+    if ( BOUNDS( K, CUR.pts.n_points ) ||
+         BOUNDS( L, CUR.pts.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    for ( I = L; I <= K; I++ )
+      CUR.pts.tags[I] &= ~FT_Curve_Tag_On;
+  }
+
+
+  static FT_Bool
+  Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6*    x,
+                                       FT_F26Dot6*    y,
+                                       TT_GlyphZone*  zone,
+                                       FT_UShort*     refp )
+  {
+    TT_GlyphZone  zp;
+    FT_UShort     p;
+    FT_F26Dot6    d;
+
+
+    if ( CUR.opcode & 1 )
+    {
+      zp = CUR.zp0;
+      p  = CUR.GS.rp1;
+    }
+    else
+    {
+      zp = CUR.zp1;
+      p  = CUR.GS.rp2;
+    }
+
+    if ( BOUNDS( p, zp.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return FAILURE;
+    }
+
+    *zone = zp;
+    *refp = p;
+
+    d = CUR_Func_project( zp.cur + p, zp.org + p );
+
+#ifdef NO_APPLE_PATENT
+
+    *x = TT_MULDIV( d, CUR.GS.freeVector.x, 0x4000 );
+    *y = TT_MULDIV( d, CUR.GS.freeVector.y, 0x4000 );
+
+#else
+
+    *x = TT_MULDIV( d,
+                    (FT_Long)CUR.GS.freeVector.x * 0x10000L,
+                    CUR.F_dot_P );
+    *y = TT_MULDIV( d,
+                    (FT_Long)CUR.GS.freeVector.y * 0x10000L,
+                    CUR.F_dot_P );
+
+#endif /* NO_APPLE_PATENT */
+
+    return SUCCESS;
+  }
+
+
+  static void
+  Move_Zp2_Point( EXEC_OP_ FT_UShort   point,
+                           FT_F26Dot6  dx,
+                           FT_F26Dot6  dy,
+                           FT_Bool     touch )
+  {
+    if ( CUR.GS.freeVector.x != 0 )
+    {
+      CUR.zp2.cur[point].x += dx;
+      if ( touch )
+        CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_X;
+    }
+
+    if ( CUR.GS.freeVector.y != 0 )
+    {
+      CUR.zp2.cur[point].y += dy;
+      if ( touch )
+        CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_Y;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SHP[a]:       SHift Point by the last point                           */
+  /* Opcode range: 0x32-0x33                                               */
+  /* Stack:        uint32... -->                                           */
+  /*                                                                       */
+  static void
+  Ins_SHP( INS_ARG )
+  {
+    TT_GlyphZone  zp;
+    FT_UShort     refp;
+
+    FT_F26Dot6    dx,
+                  dy;
+    FT_UShort     point;
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.top < CUR.GS.loop )
+    {
+      CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+      return;
+
+    while ( CUR.GS.loop > 0 )
+    {
+      CUR.args--;
+      point = (FT_UShort)CUR.stack[CUR.args];
+
+      if ( BOUNDS( point, CUR.zp2.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+        /* XXX: UNDOCUMENTED! SHP touches the points */
+        MOVE_Zp2_Point( point, dx, dy, TRUE );
+
+      CUR.GS.loop--;
+    }
+
+    CUR.GS.loop = 1;
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SHC[a]:       SHift Contour                                           */
+  /* Opcode range: 0x34-35                                                 */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SHC( INS_ARG )
+  {
+    TT_GlyphZone zp;
+    FT_UShort    refp;
+    FT_F26Dot6   dx,
+                 dy;
+
+    FT_Short     contour;
+    FT_UShort    first_point, last_point, i;
+
+
+    contour = (FT_UShort)args[0];
+
+    if ( BOUNDS( contour, CUR.pts.n_contours ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+      return;
+
+    if ( contour == 0 )
+      first_point = 0;
+    else
+      first_point = (FT_UShort)(CUR.pts.contours[contour - 1] + 1);
+
+    last_point = CUR.pts.contours[contour];
+
+    /* XXX: this is probably wrong... at least it prevents memory */
+    /*      corruption when zp2 is the twilight zone              */
+    if ( last_point > CUR.zp2.n_points )
+    {
+      if ( CUR.zp2.n_points > 0 )
+        last_point = (FT_UShort)(CUR.zp2.n_points - 1);
+      else
+        last_point = 0;
+    }
+
+    /* XXX: UNDOCUMENTED! SHC doesn't touch the points */
+    for ( i = first_point; i <= last_point; i++ )
+    {
+      if ( zp.cur != CUR.zp2.cur || refp != i )
+        MOVE_Zp2_Point( i, dx, dy, FALSE );
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SHZ[a]:       SHift Zone                                              */
+  /* Opcode range: 0x36-37                                                 */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_SHZ( INS_ARG )
+  {
+    TT_GlyphZone zp;
+    FT_UShort    refp;
+    FT_F26Dot6   dx,
+                 dy;
+
+    FT_UShort    last_point, i;
+
+
+    if ( BOUNDS( args[0], 2 ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) )
+      return;
+
+    if ( CUR.zp2.n_points > 0 )
+      last_point = (FT_UShort)(CUR.zp2.n_points - 1);
+    else
+      last_point = 0;
+
+    /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */
+    for ( i = 0; i <= last_point; i++ )
+    {
+      if ( zp.cur != CUR.zp2.cur || refp != i )
+        MOVE_Zp2_Point( i, dx, dy, FALSE );
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* SHPIX[]:      SHift points by a PIXel amount                          */
+  /* Opcode range: 0x38                                                    */
+  /* Stack:        f26.6 uint32... -->                                     */
+  /*                                                                       */
+  static void
+  Ins_SHPIX( INS_ARG )
+  {
+    FT_F26Dot6  dx, dy;
+    FT_UShort   point;
+
+
+    if ( CUR.top < CUR.GS.loop + 1 )
+    {
+      CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    dx = TT_MULDIV( args[0],
+                    (FT_Long)CUR.GS.freeVector.x,
+                    0x4000 );
+    dy = TT_MULDIV( args[0],
+                    (FT_Long)CUR.GS.freeVector.y,
+                    0x4000 );
+
+    while ( CUR.GS.loop > 0 )
+    {
+      CUR.args--;
+
+      point = (FT_UShort)CUR.stack[CUR.args];
+
+      if ( BOUNDS( point, CUR.zp2.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+        MOVE_Zp2_Point( point, dx, dy, TRUE );
+
+      CUR.GS.loop--;
+    }
+
+    CUR.GS.loop = 1;
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MSIRP[a]:     Move Stack Indirect Relative Position                   */
+  /* Opcode range: 0x3A-0x3B                                               */
+  /* Stack:        f26.6 uint32 -->                                        */
+  /*                                                                       */
+  static void
+  Ins_MSIRP( INS_ARG )
+  {
+    FT_UShort   point;
+    FT_F26Dot6  distance;
+
+
+    point = (FT_UShort)args[0];
+
+    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    /* XXX: UNDOCUMENTED! behaviour */
+    if ( CUR.GS.gep0 == 0 )   /* if in twilight zone */
+    {
+      CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0];
+      CUR.zp1.cur[point] = CUR.zp1.org[point];
+    }
+
+    distance = CUR_Func_project( CUR.zp1.cur + point,
+                                 CUR.zp0.cur + CUR.GS.rp0 );
+
+    CUR_Func_move( &CUR.zp1, point, args[1] - distance );
+
+    CUR.GS.rp1 = CUR.GS.rp0;
+    CUR.GS.rp2 = point;
+
+    if ( (CUR.opcode & 1) != 0 )
+      CUR.GS.rp0 = point;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MDAP[a]:      Move Direct Absolute Point                              */
+  /* Opcode range: 0x2E-0x2F                                               */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_MDAP( INS_ARG )
+  {
+    FT_UShort   point;
+    FT_F26Dot6  cur_dist,
+                distance;
+
+
+    point = (FT_UShort)args[0];
+
+    if ( BOUNDS( point, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    /* XXX: Is there some undocumented feature while in the */
+    /*      twilight zone? ?                                */
+    if ( ( CUR.opcode & 1 ) != 0 )
+    {
+      cur_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector );
+      distance = CUR_Func_round( cur_dist,
+                                 CUR.tt_metrics.compensations[0] ) - cur_dist;
+    }
+    else
+      distance = 0;
+
+    CUR_Func_move( &CUR.zp0, point, distance );
+
+    CUR.GS.rp0 = point;
+    CUR.GS.rp1 = point;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MIAP[a]:      Move Indirect Absolute Point                            */
+  /* Opcode range: 0x3E-0x3F                                               */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_MIAP( INS_ARG )
+  {
+    FT_ULong    cvtEntry;
+    FT_UShort   point;
+    FT_F26Dot6  distance,
+                org_dist;
+
+
+    cvtEntry = (FT_ULong)args[1];
+    point    = (FT_UShort)args[0];
+
+    if ( BOUNDS( point,    CUR.zp0.n_points ) ||
+         BOUNDS( cvtEntry, CUR.cvtSize )      )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    /* UNDOCUMENTED!                                     */
+    /*                                                   */
+    /* The behaviour of an MIAP instruction is quite     */
+    /* different when used in the twilight zone.         */
+    /*                                                   */
+    /* First, no control value cutin test is performed   */
+    /* as it would fail anyway.  Second, the original    */
+    /* point, i.e. (org_x,org_y) of zp0.point, is set    */
+    /* to the absolute, unrounded distance found in      */
+    /* the CVT.                                          */
+    /*                                                   */
+    /* This is used in the CVT programs of the Microsoft */
+    /* fonts Arial, Times, etc., in order to re-adjust   */
+    /* some key font heights.  It allows the use of the  */
+    /* IP instruction in the twilight zone, which        */
+    /* otherwise would be `illegal' according to the     */
+    /* specification.                                    */
+    /*                                                   */
+    /* We implement it with a special sequence for the   */
+    /* twilight zone.  This is a bad hack, but it seems  */
+    /* to work.                                          */
+
+    distance = CUR_Func_read_cvt( cvtEntry );
+
+    if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */
+    {
+      CUR.zp0.org[point].x = TT_MULDIV( CUR.GS.freeVector.x,
+                                        distance, 0x4000 );
+      CUR.zp0.org[point].y = TT_MULDIV( CUR.GS.freeVector.y,
+                                        distance, 0x4000 );
+      CUR.zp0.cur[point] = CUR.zp0.org[point];
+    }
+
+    org_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector );
+
+    if ( ( CUR.opcode & 1 ) != 0 )   /* rounding and control cutin flag */
+    {
+      if ( ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
+        distance = org_dist;
+
+      distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
+    }
+
+    CUR_Func_move( &CUR.zp0, point, distance - org_dist );
+
+    CUR.GS.rp0 = point;
+    CUR.GS.rp1 = point;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MDRP[abcde]:  Move Direct Relative Point                              */
+  /* Opcode range: 0xC0-0xDF                                               */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_MDRP( INS_ARG )
+  {
+    FT_UShort   point;
+    FT_F26Dot6  org_dist, distance;
+
+
+    point = (FT_UShort)args[0];
+
+    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    /* XXX: Is there some undocumented feature while in the */
+    /*      twilight zone?                                  */
+
+    org_dist = CUR_Func_dualproj( CUR.zp1.org + point,
+                                  CUR.zp0.org + CUR.GS.rp0 );
+
+    /* single width cutin test */
+
+    if ( ABS( org_dist ) < CUR.GS.single_width_cutin )
+    {
+      if ( org_dist >= 0 )
+        org_dist = CUR.GS.single_width_value;
+      else
+        org_dist = -CUR.GS.single_width_value;
+    }
+
+    /* round flag */
+
+    if ( ( CUR.opcode & 4 ) != 0 )
+      distance = CUR_Func_round(
+                   org_dist,
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+    else
+      distance = ROUND_None(
+                   org_dist,
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+
+    /* minimum distance flag */
+
+    if ( ( CUR.opcode & 8 ) != 0 )
+    {
+      if ( org_dist >= 0 )
+      {
+        if ( distance < CUR.GS.minimum_distance )
+          distance = CUR.GS.minimum_distance;
+      }
+      else
+      {
+        if ( distance > -CUR.GS.minimum_distance )
+          distance = -CUR.GS.minimum_distance;
+      }
+    }
+
+    /* now move the point */
+
+    org_dist = CUR_Func_project( CUR.zp1.cur + point,
+                                 CUR.zp0.cur + CUR.GS.rp0 );
+
+    CUR_Func_move( &CUR.zp1, point, distance - org_dist );
+
+    CUR.GS.rp1 = CUR.GS.rp0;
+    CUR.GS.rp2 = point;
+
+    if ( ( CUR.opcode & 16 ) != 0 )
+      CUR.GS.rp0 = point;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MIRP[abcde]:  Move Indirect Relative Point                            */
+  /* Opcode range: 0xE0-0xFF                                               */
+  /* Stack:        int32? uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_MIRP( INS_ARG )
+  {
+    FT_UShort   point;
+    FT_ULong    cvtEntry;
+
+    FT_F26Dot6  cvt_dist,
+                distance,
+                cur_dist,
+                org_dist;
+
+
+    point    = (FT_UShort)args[0];
+    cvtEntry = (FT_ULong)( args[1] + 1 );
+
+    /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
+
+    if ( BOUNDS( point,      CUR.zp1.n_points ) ||
+         BOUNDS( cvtEntry,   CUR.cvtSize + 1 )  ||
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    if ( !cvtEntry )
+      cvt_dist = 0;
+    else
+      cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 );
+
+    /* single width test */
+
+    if ( ABS( cvt_dist ) < CUR.GS.single_width_cutin )
+    {
+      if ( cvt_dist >= 0 )
+        cvt_dist =  CUR.GS.single_width_value;
+      else
+        cvt_dist = -CUR.GS.single_width_value;
+    }
+
+    /* XXX: UNDOCUMENTED! -- twilight zone */
+
+    if ( CUR.GS.gep1 == 0 )
+    {
+      CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x +
+                             TT_MULDIV( cvt_dist,
+                                        CUR.GS.freeVector.x,
+                                        0x4000 );
+
+      CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y +
+                             TT_MULDIV( cvt_dist,
+                                        CUR.GS.freeVector.y,
+                                        0x4000 );
+
+      CUR.zp1.cur[point] = CUR.zp1.org[point];
+    }
+
+    org_dist = CUR_Func_dualproj( CUR.zp1.org + point,
+                                  CUR.zp0.org + CUR.GS.rp0 );
+
+    cur_dist = CUR_Func_project( CUR.zp1.cur + point,
+                                 CUR.zp0.cur + CUR.GS.rp0 );
+
+    /* auto-flip test */
+
+    if ( CUR.GS.auto_flip )
+    {
+      if ( ( org_dist ^ cvt_dist ) < 0 )
+        cvt_dist = -cvt_dist;
+    }
+
+    /* control value cutin and round */
+
+    if ( ( CUR.opcode & 4 ) != 0 )
+    {
+      /* XXX: UNDOCUMENTED!  Only perform cut-in test when both points */
+      /*      refer to the same zone.                                  */
+
+      if ( CUR.GS.gep0 == CUR.GS.gep1 )
+        if ( ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin )
+          cvt_dist = org_dist;
+
+      distance = CUR_Func_round(
+                   cvt_dist,
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+    }
+    else
+      distance = ROUND_None(
+                   cvt_dist,
+                   CUR.tt_metrics.compensations[CUR.opcode & 3] );
+
+    /* minimum distance test */
+
+    if ( ( CUR.opcode & 8 ) != 0 )
+    {
+      if ( org_dist >= 0 )
+      {
+        if ( distance < CUR.GS.minimum_distance )
+          distance = CUR.GS.minimum_distance;
+      }
+      else
+      {
+        if ( distance > -CUR.GS.minimum_distance )
+          distance = -CUR.GS.minimum_distance;
+      }
+    }
+
+    CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
+
+    CUR.GS.rp1 = CUR.GS.rp0;
+
+    if ( ( CUR.opcode & 16 ) != 0 )
+      CUR.GS.rp0 = point;
+
+    /* XXX: UNDOCUMENTED! */
+
+    CUR.GS.rp2 = point;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ALIGNRP[]:    ALIGN Relative Point                                    */
+  /* Opcode range: 0x3C                                                    */
+  /* Stack:        uint32 uint32... -->                                    */
+  /*                                                                       */
+  static void
+  Ins_ALIGNRP( INS_ARG )
+  {
+    FT_UShort   point;
+    FT_F26Dot6  distance;
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.top < CUR.GS.loop ||
+         BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    while ( CUR.GS.loop > 0 )
+    {
+      CUR.args--;
+
+      point = (FT_UShort)CUR.stack[CUR.args];
+
+      if ( BOUNDS( point, CUR.zp1.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+      {
+        distance = CUR_Func_project( CUR.zp1.cur + point,
+                                     CUR.zp0.cur + CUR.GS.rp0 );
+
+        CUR_Func_move( &CUR.zp1, point, -distance );
+      }
+
+      CUR.GS.loop--;
+    }
+
+    CUR.GS.loop = 1;
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ISECT[]:      moves point to InterSECTion                             */
+  /* Opcode range: 0x0F                                                    */
+  /* Stack:        5 * uint32 -->                                          */
+  /*                                                                       */
+  static void
+  Ins_ISECT( INS_ARG )
+  {
+    FT_UShort   point,
+                a0, a1,
+                b0, b1;
+
+    FT_F26Dot6  discriminant;
+
+    FT_F26Dot6  dx,  dy,
+                dax, day,
+                dbx, dby;
+
+    FT_F26Dot6  val;
+
+    FT_Vector   R;
+
+
+    point = (FT_UShort)args[0];
+
+    a0 = (FT_UShort)args[1];
+    a1 = (FT_UShort)args[2];
+    b0 = (FT_UShort)args[3];
+    b1 = (FT_UShort)args[4];
+
+    if ( BOUNDS( b0, CUR.zp0.n_points )  ||
+         BOUNDS( b1, CUR.zp0.n_points )  ||
+         BOUNDS( a0, CUR.zp1.n_points )  ||
+         BOUNDS( a1, CUR.zp1.n_points )  ||
+         BOUNDS( point, CUR.zp2.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
+    dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
+
+    dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x;
+    day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y;
+
+    dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x;
+    dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y;
+
+    CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_Both;
+
+    discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
+                   TT_MULDIV( day, dbx, 0x40 );
+
+    if ( ABS( discriminant ) >= 0x40 )
+    {
+      val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
+
+      R.x = TT_MULDIV( val, dax, discriminant );
+      R.y = TT_MULDIV( val, day, discriminant );
+
+      CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
+      CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
+    }
+    else
+    {
+      /* else, take the middle of the middles of A and B */
+
+      CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x +
+                               CUR.zp1.cur[a1].x +
+                               CUR.zp0.cur[b0].x +
+                               CUR.zp0.cur[b1].x ) / 4;
+      CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y +
+                               CUR.zp1.cur[a1].y +
+                               CUR.zp0.cur[b0].y +
+                               CUR.zp0.cur[b1].y ) / 4;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ALIGNPTS[]:   ALIGN PoinTS                                            */
+  /* Opcode range: 0x27                                                    */
+  /* Stack:        uint32 uint32 -->                                       */
+  /*                                                                       */
+  static void
+  Ins_ALIGNPTS( INS_ARG )
+  {
+    FT_UShort   p1, p2;
+    FT_F26Dot6  distance;
+
+
+    p1 = (FT_UShort)args[0];
+    p2 = (FT_UShort)args[1];
+
+    if ( BOUNDS( args[0], CUR.zp1.n_points ) ||
+         BOUNDS( args[1], CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    distance = CUR_Func_project( CUR.zp0.cur + p2,
+                                 CUR.zp1.cur + p1 ) / 2;
+
+    CUR_Func_move( &CUR.zp1, p1, distance );
+    CUR_Func_move( &CUR.zp0, p2, -distance );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IP[]:         Interpolate Point                                       */
+  /* Opcode range: 0x39                                                    */
+  /* Stack:        uint32... -->                                           */
+  /*                                                                       */
+  static void
+  Ins_IP( INS_ARG )
+  {
+    FT_F26Dot6  org_a, org_b, org_x,
+                cur_a, cur_b, cur_x,
+                distance;
+    FT_UShort   point;
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.top < CUR.GS.loop )
+    {
+      CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    /* XXX: There are some glyphs in some braindead but popular  */
+    /*      fonts out there (e.g. [aeu]grave in monotype.ttf)    */
+    /*      calling IP[] with bad values of rp[12].              */
+    /*      Do something sane when this odd thing happens.       */
+
+    if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) ||
+         BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) )
+    {
+      org_a = cur_a = 0;
+      org_b = cur_b = 0;
+    }
+    else
+    {
+      org_a = CUR_Func_dualproj( CUR.zp0.org + CUR.GS.rp1, NULL_Vector );
+      org_b = CUR_Func_dualproj( CUR.zp1.org + CUR.GS.rp2, NULL_Vector );
+
+      cur_a = CUR_Func_project( CUR.zp0.cur + CUR.GS.rp1, NULL_Vector );
+      cur_b = CUR_Func_project( CUR.zp1.cur + CUR.GS.rp2, NULL_Vector );
+    }
+
+    while ( CUR.GS.loop > 0 )
+    {
+      CUR.args--;
+
+      point = (FT_UShort)CUR.stack[CUR.args];
+      if ( BOUNDS( point, CUR.zp2.n_points ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+      {
+        org_x = CUR_Func_dualproj( CUR.zp2.org + point, NULL_Vector );
+        cur_x = CUR_Func_project ( CUR.zp2.cur + point, NULL_Vector );
+
+        if ( ( org_a <= org_b && org_x <= org_a ) ||
+             ( org_a >  org_b && org_x >= org_a ) )
+
+          distance = ( cur_a - org_a ) + ( org_x - cur_x );
+
+        else if ( ( org_a <= org_b  &&  org_x >= org_b ) ||
+                  ( org_a >  org_b  &&  org_x <  org_b ) )
+
+          distance = ( cur_b - org_b ) + ( org_x - cur_x );
+
+        else
+           /* note: it seems that rounding this value isn't a good */
+           /*       idea (cf. width of capital `S' in Times)       */
+
+           distance = TT_MULDIV( cur_b - cur_a,
+                                 org_x - org_a,
+                                 org_b - org_a ) + ( cur_a - cur_x );
+
+        CUR_Func_move( &CUR.zp2, point, distance );
+      }
+
+      CUR.GS.loop--;
+    }
+
+    CUR.GS.loop = 1;
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* UTP[a]:       UnTouch Point                                           */
+  /* Opcode range: 0x29                                                    */
+  /* Stack:        uint32 -->                                              */
+  /*                                                                       */
+  static void
+  Ins_UTP( INS_ARG )
+  {
+    FT_UShort  point;
+    FT_Byte    mask;
+
+
+    point = (FT_UShort)args[0];
+
+    if ( BOUNDS( point, CUR.zp0.n_points ) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
+    mask = 0xFF;
+
+    if ( CUR.GS.freeVector.x != 0 )
+      mask &= ~FT_Curve_Tag_Touch_X;
+
+    if ( CUR.GS.freeVector.y != 0 )
+      mask &= ~FT_Curve_Tag_Touch_Y;
+
+    CUR.zp0.tags[point] &= mask;
+  }
+
+
+  /* Local variables for Ins_IUP: */
+  struct  LOC_Ins_IUP
+  {
+    FT_Vector*  orgs;   /* original and current coordinate */
+    FT_Vector*  curs;   /* arrays                          */
+  };
+
+
+  static void
+  Shift( FT_UInt              p1,
+         FT_UInt              p2,
+         FT_UInt              p,
+         struct LOC_Ins_IUP*  LINK )
+  {
+    FT_UInt     i;
+    FT_F26Dot6  x;
+
+
+    x = LINK->curs[p].x - LINK->orgs[p].x;
+
+    for ( i = p1; i < p; i++ )
+      LINK->curs[i].x += x;
+
+    for ( i = p + 1; i <= p2; i++ )
+      LINK->curs[i].x += x;
+  }
+
+
+  static void
+  Interp( FT_UInt              p1,
+          FT_UInt              p2,
+          FT_UInt              ref1,
+          FT_UInt              ref2,
+          struct LOC_Ins_IUP*  LINK )
+  {
+    FT_UInt     i;
+    FT_F26Dot6  x, x1, x2, d1, d2;
+
+
+    if ( p1 > p2 )
+      return;
+
+    x1 = LINK->orgs[ref1].x;
+    d1 = LINK->curs[ref1].x - LINK->orgs[ref1].x;
+    x2 = LINK->orgs[ref2].x;
+    d2 = LINK->curs[ref2].x - LINK->orgs[ref2].x;
+
+    if ( x1 == x2 )
+    {
+      for ( i = p1; i <= p2; i++ )
+      {
+        x = LINK->orgs[i].x;
+
+        if ( x <= x1 )
+          x += d1;
+        else
+          x += d2;
+
+        LINK->curs[i].x = x;
+      }
+      return;
+    }
+
+    if ( x1 < x2 )
+    {
+      for ( i = p1; i <= p2; i++ )
+      {
+        x = LINK->orgs[i].x;
+
+        if ( x <= x1 )
+          x += d1;
+        else
+        {
+          if ( x >= x2 )
+            x += d2;
+          else
+            x = LINK->curs[ref1].x +
+                  TT_MULDIV( x - x1,
+                             LINK->curs[ref2].x - LINK->curs[ref1].x,
+                             x2 - x1 );
+        }
+        LINK->curs[i].x = x;
+      }
+      return;
+    }
+
+    /* x2 < x1 */
+
+    for ( i = p1; i <= p2; i++ )
+    {
+      x = LINK->orgs[i].x;
+      if ( x <= x2 )
+        x += d2;
+      else
+      {
+        if ( x >= x1 )
+          x += d1;
+        else
+          x = LINK->curs[ref1].x +
+              TT_MULDIV( x - x1,
+                         LINK->curs[ref2].x - LINK->curs[ref1].x,
+                         x2 - x1 );
+      }
+      LINK->curs[i].x = x;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* IUP[a]:       Interpolate Untouched Points                            */
+  /* Opcode range: 0x30-0x31                                               */
+  /* Stack:        -->                                                     */
+  /*                                                                       */
+  static void
+  Ins_IUP( INS_ARG )
+  {
+    struct LOC_Ins_IUP  V;
+    FT_Byte             mask;
+
+    FT_UInt   first_point;   /* first point of contour        */
+    FT_UInt   end_point;     /* end point (last+1) of contour */
+
+    FT_UInt   first_touched; /* first touched point in contour   */
+    FT_UInt   cur_touched;   /* current touched point in contour */
+
+    FT_UInt   point;         /* current point   */
+    FT_Short  contour;       /* current contour */
+
+    FT_UNUSED_ARG;
+
+
+    if ( CUR.opcode & 1 )
+    {
+      mask   = FT_Curve_Tag_Touch_X;
+      V.orgs = CUR.pts.org;
+      V.curs = CUR.pts.cur;
+    }
+    else
+    {
+      mask   = FT_Curve_Tag_Touch_Y;
+      V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 );
+      V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 );
+    }
+
+    contour = 0;
+    point   = 0;
+
+    do
+    {
+      end_point   = CUR.pts.contours[contour];
+      first_point = point;
+
+      while ( point <= end_point && (CUR.pts.tags[point] & mask) == 0 )
+        point++;
+
+      if ( point <= end_point )
+      {
+        first_touched = point;
+        cur_touched   = point;
+
+        point++;
+
+        while ( point <= end_point )
+        {
+          if ( ( CUR.pts.tags[point] & mask ) != 0 )
+          {
+            if ( point > 0 )
+              Interp( cur_touched + 1,
+                      point - 1,
+                      cur_touched,
+                      point,
+                      &V );
+            cur_touched = point;
+          }
+
+          point++;
+        }
+
+        if ( cur_touched == first_touched )
+          Shift( first_point, end_point, cur_touched, &V );
+        else
+        {
+          Interp( (FT_UShort)( cur_touched + 1 ),
+                  end_point,
+                  cur_touched,
+                  first_touched,
+                  &V );
+
+          if ( first_touched > 0 )
+            Interp( first_point,
+                    first_touched - 1,
+                    cur_touched,
+                    first_touched,
+                    &V );
+        }
+      }
+      contour++;
+    } while ( contour < CUR.pts.n_contours );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DELTAPn[]:    DELTA exceptions P1, P2, P3                             */
+  /* Opcode range: 0x5D,0x71,0x72                                          */
+  /* Stack:        uint32 (2 * uint32)... -->                              */
+  /*                                                                       */
+  static void
+  Ins_DELTAP( INS_ARG )
+  {
+    FT_ULong   k, nump;
+    FT_UShort  A;
+    FT_ULong   C;
+    FT_Long    B;
+
+
+    nump = (FT_ULong)args[0];   /* some points theoretically may occur more
+                                   than once, thus UShort isn't enough */
+
+    for ( k = 1; k <= nump; k++ )
+    {
+      if ( CUR.args < 2 )
+      {
+        CUR.error = TT_Err_Too_Few_Arguments;
+        return;
+      }
+
+      CUR.args -= 2;
+
+      A = (FT_UShort)CUR.stack[CUR.args + 1];
+      B = CUR.stack[CUR.args];
+
+      /* XXX: Because some popular fonts contain some invalid DeltaP */
+      /*      instructions, we simply ignore them when the stacked   */
+      /*      point reference is off limit, rather than returning an */
+      /*      error.  As a delta instruction doesn't change a glyph  */
+      /*      in great ways, this shouldn't be a problem.            */
+
+      if ( !BOUNDS( A, CUR.zp0.n_points ) )
+      {
+        C = ( (FT_ULong)B & 0xF0 ) >> 4;
+
+        switch ( CUR.opcode )
+        {
+        case 0x5D:
+          break;
+
+        case 0x71:
+          C += 16;
+          break;
+
+        case 0x72:
+          C += 32;
+          break;
+        }
+
+        C += CUR.GS.delta_base;
+
+        if ( CURRENT_Ppem() == (FT_Long)C )
+        {
+          B = ( (FT_ULong)B & 0xF ) - 8;
+          if ( B >= 0 )
+            B++;
+          B = B * 64 / ( 1L << CUR.GS.delta_shift );
+
+          CUR_Func_move( &CUR.zp0, A, B );
+        }
+      }
+      else
+        if ( CUR.pedantic_hinting )
+          CUR.error = TT_Err_Invalid_Reference;
+    }
+
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* DELTACn[]:    DELTA exceptions C1, C2, C3                             */
+  /* Opcode range: 0x73,0x74,0x75                                          */
+  /* Stack:        uint32 (2 * uint32)... -->                              */
+  /*                                                                       */
+  static void
+  Ins_DELTAC( INS_ARG )
+  {
+    FT_ULong  nump, k;
+    FT_ULong  A, C;
+    FT_Long   B;
+
+
+    nump = (FT_ULong)args[0];
+
+    for ( k = 1; k <= nump; k++ )
+    {
+      if ( CUR.args < 2 )
+      {
+        CUR.error = TT_Err_Too_Few_Arguments;
+        return;
+      }
+
+      CUR.args -= 2;
+
+      A = (FT_ULong)CUR.stack[CUR.args + 1];
+      B = CUR.stack[CUR.args];
+
+      if ( BOUNDS( A, CUR.cvtSize ) )
+      {
+        if ( CUR.pedantic_hinting )
+        {
+          CUR.error = TT_Err_Invalid_Reference;
+          return;
+        }
+      }
+      else
+      {
+        C = ( (FT_ULong)B & 0xF0 ) >> 4;
+
+        switch ( CUR.opcode )
+        {
+        case 0x73:
+          break;
+
+        case 0x74:
+          C += 16;
+          break;
+
+        case 0x75:
+          C += 32;
+          break;
+        }
+
+        C += CUR.GS.delta_base;
+
+        if ( CURRENT_Ppem() == (FT_Long)C )
+        {
+          B = ( (FT_ULong)B & 0xF ) - 8;
+          if ( B >= 0 )
+            B++;
+          B = B * 64 / ( 1L << CUR.GS.delta_shift );
+
+          CUR_Func_move_cvt( A, B );
+        }
+      }
+    }
+
+    CUR.new_top = CUR.args;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* MISC. INSTRUCTIONS                                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* GETINFO[]:    GET INFOrmation                                         */
+  /* Opcode range: 0x88                                                    */
+  /* Stack:        uint32 --> uint32                                       */
+  /*                                                                       */
+  /* XXX: According to Apple specs, bits 1 & 2 of the argument ought to be */
+  /*      consulted before rotated/stretched info is returned.             */
+  static void
+  Ins_GETINFO( INS_ARG )
+  {
+    FT_Long  K;
+
+
+    K = 0;
+
+    /* We return then Windows 3.1 version number */
+    /* for the font scaler                       */
+    if ( ( args[0] & 1 ) != 0 )
+      K = 3;
+
+    /* Has the glyph been rotated ? */
+    if ( CUR.tt_metrics.rotated )
+      K |= 0x80;
+
+    /* Has the glyph been stretched ? */
+    if ( CUR.tt_metrics.stretched )
+      K |= 0x100;
+
+    args[0] = K;
+  }
+
+
+  static void
+  Ins_UNKNOWN( INS_ARG )
+  {
+    TT_DefRecord*  def   = CUR.IDefs;
+    TT_DefRecord*  limit = def + CUR.numIDefs;
+
+    FT_UNUSED_ARG;
+
+
+    for ( ; def < limit; def++ )
+    {
+      if ( (FT_Byte)def->opc == CUR.opcode && def->active )
+      {
+        TT_CallRec*  call;
+
+
+        if ( CUR.callTop >= CUR.callSize )
+        {
+          CUR.error = TT_Err_Stack_Overflow;
+          return;
+        }
+
+        call = CUR.callStack + CUR.callTop++;
+
+        call->Caller_Range = CUR.curRange;
+        call->Caller_IP    = CUR.IP+1;
+        call->Cur_Count    = 1;
+        call->Cur_Restart  = def->start;
+
+        INS_Goto_CodeRange( def->range, def->start );
+
+        CUR.step_ins = FALSE;
+        return;
+      }
+    }
+
+    CUR.error = TT_Err_Invalid_Opcode;
+  }
+
+
+#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+
+  static
+  TInstruction_Function  Instruct_Dispatch[256] =
+  {
+    /* Opcodes are gathered in groups of 16. */
+    /* Please keep the spaces as they are.   */
+
+    /*  SVTCA  y  */  Ins_SVTCA,
+    /*  SVTCA  x  */  Ins_SVTCA,
+    /*  SPvTCA y  */  Ins_SPVTCA,
+    /*  SPvTCA x  */  Ins_SPVTCA,
+    /*  SFvTCA y  */  Ins_SFVTCA,
+    /*  SFvTCA x  */  Ins_SFVTCA,
+    /*  SPvTL //  */  Ins_SPVTL,
+    /*  SPvTL +   */  Ins_SPVTL,
+    /*  SFvTL //  */  Ins_SFVTL,
+    /*  SFvTL +   */  Ins_SFVTL,
+    /*  SPvFS     */  Ins_SPVFS,
+    /*  SFvFS     */  Ins_SFVFS,
+    /*  GPV       */  Ins_GPV,
+    /*  GFV       */  Ins_GFV,
+    /*  SFvTPv    */  Ins_SFVTPV,
+    /*  ISECT     */  Ins_ISECT,
+
+    /*  SRP0      */  Ins_SRP0,
+    /*  SRP1      */  Ins_SRP1,
+    /*  SRP2      */  Ins_SRP2,
+    /*  SZP0      */  Ins_SZP0,
+    /*  SZP1      */  Ins_SZP1,
+    /*  SZP2      */  Ins_SZP2,
+    /*  SZPS      */  Ins_SZPS,
+    /*  SLOOP     */  Ins_SLOOP,
+    /*  RTG       */  Ins_RTG,
+    /*  RTHG      */  Ins_RTHG,
+    /*  SMD       */  Ins_SMD,
+    /*  ELSE      */  Ins_ELSE,
+    /*  JMPR      */  Ins_JMPR,
+    /*  SCvTCi    */  Ins_SCVTCI,
+    /*  SSwCi     */  Ins_SSWCI,
+    /*  SSW       */  Ins_SSW,
+
+    /*  DUP       */  Ins_DUP,
+    /*  POP       */  Ins_POP,
+    /*  CLEAR     */  Ins_CLEAR,
+    /*  SWAP      */  Ins_SWAP,
+    /*  DEPTH     */  Ins_DEPTH,
+    /*  CINDEX    */  Ins_CINDEX,
+    /*  MINDEX    */  Ins_MINDEX,
+    /*  AlignPTS  */  Ins_ALIGNPTS,
+    /*  INS_0x28  */  Ins_UNKNOWN,
+    /*  UTP       */  Ins_UTP,
+    /*  LOOPCALL  */  Ins_LOOPCALL,
+    /*  CALL      */  Ins_CALL,
+    /*  FDEF      */  Ins_FDEF,
+    /*  ENDF      */  Ins_ENDF,
+    /*  MDAP[0]   */  Ins_MDAP,
+    /*  MDAP[1]   */  Ins_MDAP,
+
+    /*  IUP[0]    */  Ins_IUP,
+    /*  IUP[1]    */  Ins_IUP,
+    /*  SHP[0]    */  Ins_SHP,
+    /*  SHP[1]    */  Ins_SHP,
+    /*  SHC[0]    */  Ins_SHC,
+    /*  SHC[1]    */  Ins_SHC,
+    /*  SHZ[0]    */  Ins_SHZ,
+    /*  SHZ[1]    */  Ins_SHZ,
+    /*  SHPIX     */  Ins_SHPIX,
+    /*  IP        */  Ins_IP,
+    /*  MSIRP[0]  */  Ins_MSIRP,
+    /*  MSIRP[1]  */  Ins_MSIRP,
+    /*  AlignRP   */  Ins_ALIGNRP,
+    /*  RTDG      */  Ins_RTDG,
+    /*  MIAP[0]   */  Ins_MIAP,
+    /*  MIAP[1]   */  Ins_MIAP,
+
+    /*  NPushB    */  Ins_NPUSHB,
+    /*  NPushW    */  Ins_NPUSHW,
+    /*  WS        */  Ins_WS,
+    /*  RS        */  Ins_RS,
+    /*  WCvtP     */  Ins_WCVTP,
+    /*  RCvt      */  Ins_RCVT,
+    /*  GC[0]     */  Ins_GC,
+    /*  GC[1]     */  Ins_GC,
+    /*  SCFS      */  Ins_SCFS,
+    /*  MD[0]     */  Ins_MD,
+    /*  MD[1]     */  Ins_MD,
+    /*  MPPEM     */  Ins_MPPEM,
+    /*  MPS       */  Ins_MPS,
+    /*  FlipON    */  Ins_FLIPON,
+    /*  FlipOFF   */  Ins_FLIPOFF,
+    /*  DEBUG     */  Ins_DEBUG,
+
+    /*  LT        */  Ins_LT,
+    /*  LTEQ      */  Ins_LTEQ,
+    /*  GT        */  Ins_GT,
+    /*  GTEQ      */  Ins_GTEQ,
+    /*  EQ        */  Ins_EQ,
+    /*  NEQ       */  Ins_NEQ,
+    /*  ODD       */  Ins_ODD,
+    /*  EVEN      */  Ins_EVEN,
+    /*  IF        */  Ins_IF,
+    /*  EIF       */  Ins_EIF,
+    /*  AND       */  Ins_AND,
+    /*  OR        */  Ins_OR,
+    /*  NOT       */  Ins_NOT,
+    /*  DeltaP1   */  Ins_DELTAP,
+    /*  SDB       */  Ins_SDB,
+    /*  SDS       */  Ins_SDS,
+
+    /*  ADD       */  Ins_ADD,
+    /*  SUB       */  Ins_SUB,
+    /*  DIV       */  Ins_DIV,
+    /*  MUL       */  Ins_MUL,
+    /*  ABS       */  Ins_ABS,
+    /*  NEG       */  Ins_NEG,
+    /*  FLOOR     */  Ins_FLOOR,
+    /*  CEILING   */  Ins_CEILING,
+    /*  ROUND[0]  */  Ins_ROUND,
+    /*  ROUND[1]  */  Ins_ROUND,
+    /*  ROUND[2]  */  Ins_ROUND,
+    /*  ROUND[3]  */  Ins_ROUND,
+    /*  NROUND[0] */  Ins_NROUND,
+    /*  NROUND[1] */  Ins_NROUND,
+    /*  NROUND[2] */  Ins_NROUND,
+    /*  NROUND[3] */  Ins_NROUND,
+
+    /*  WCvtF     */  Ins_WCVTF,
+    /*  DeltaP2   */  Ins_DELTAP,
+    /*  DeltaP3   */  Ins_DELTAP,
+    /*  DeltaCn[0] */ Ins_DELTAC,
+    /*  DeltaCn[1] */ Ins_DELTAC,
+    /*  DeltaCn[2] */ Ins_DELTAC,
+    /*  SROUND    */  Ins_SROUND,
+    /*  S45Round  */  Ins_S45ROUND,
+    /*  JROT      */  Ins_JROT,
+    /*  JROF      */  Ins_JROF,
+    /*  ROFF      */  Ins_ROFF,
+    /*  INS_0x7B  */  Ins_UNKNOWN,
+    /*  RUTG      */  Ins_RUTG,
+    /*  RDTG      */  Ins_RDTG,
+    /*  SANGW     */  Ins_SANGW,
+    /*  AA        */  Ins_AA,
+
+    /*  FlipPT    */  Ins_FLIPPT,
+    /*  FlipRgON  */  Ins_FLIPRGON,
+    /*  FlipRgOFF */  Ins_FLIPRGOFF,
+    /*  INS_0x83  */  Ins_UNKNOWN,
+    /*  INS_0x84  */  Ins_UNKNOWN,
+    /*  ScanCTRL  */  Ins_SCANCTRL,
+    /*  SDPVTL[0] */  Ins_SDPVTL,
+    /*  SDPVTL[1] */  Ins_SDPVTL,
+    /*  GetINFO   */  Ins_GETINFO,
+    /*  IDEF      */  Ins_IDEF,
+    /*  ROLL      */  Ins_ROLL,
+    /*  MAX       */  Ins_MAX,
+    /*  MIN       */  Ins_MIN,
+    /*  ScanTYPE  */  Ins_SCANTYPE,
+    /*  InstCTRL  */  Ins_INSTCTRL,
+    /*  INS_0x8F  */  Ins_UNKNOWN,
+
+    /*  INS_0x90  */   Ins_UNKNOWN,
+    /*  INS_0x91  */   Ins_UNKNOWN,
+    /*  INS_0x92  */   Ins_UNKNOWN,
+    /*  INS_0x93  */   Ins_UNKNOWN,
+    /*  INS_0x94  */   Ins_UNKNOWN,
+    /*  INS_0x95  */   Ins_UNKNOWN,
+    /*  INS_0x96  */   Ins_UNKNOWN,
+    /*  INS_0x97  */   Ins_UNKNOWN,
+    /*  INS_0x98  */   Ins_UNKNOWN,
+    /*  INS_0x99  */   Ins_UNKNOWN,
+    /*  INS_0x9A  */   Ins_UNKNOWN,
+    /*  INS_0x9B  */   Ins_UNKNOWN,
+    /*  INS_0x9C  */   Ins_UNKNOWN,
+    /*  INS_0x9D  */   Ins_UNKNOWN,
+    /*  INS_0x9E  */   Ins_UNKNOWN,
+    /*  INS_0x9F  */   Ins_UNKNOWN,
+
+    /*  INS_0xA0  */   Ins_UNKNOWN,
+    /*  INS_0xA1  */   Ins_UNKNOWN,
+    /*  INS_0xA2  */   Ins_UNKNOWN,
+    /*  INS_0xA3  */   Ins_UNKNOWN,
+    /*  INS_0xA4  */   Ins_UNKNOWN,
+    /*  INS_0xA5  */   Ins_UNKNOWN,
+    /*  INS_0xA6  */   Ins_UNKNOWN,
+    /*  INS_0xA7  */   Ins_UNKNOWN,
+    /*  INS_0xA8  */   Ins_UNKNOWN,
+    /*  INS_0xA9  */   Ins_UNKNOWN,
+    /*  INS_0xAA  */   Ins_UNKNOWN,
+    /*  INS_0xAB  */   Ins_UNKNOWN,
+    /*  INS_0xAC  */   Ins_UNKNOWN,
+    /*  INS_0xAD  */   Ins_UNKNOWN,
+    /*  INS_0xAE  */   Ins_UNKNOWN,
+    /*  INS_0xAF  */   Ins_UNKNOWN,
+
+    /*  PushB[0]  */  Ins_PUSHB,
+    /*  PushB[1]  */  Ins_PUSHB,
+    /*  PushB[2]  */  Ins_PUSHB,
+    /*  PushB[3]  */  Ins_PUSHB,
+    /*  PushB[4]  */  Ins_PUSHB,
+    /*  PushB[5]  */  Ins_PUSHB,
+    /*  PushB[6]  */  Ins_PUSHB,
+    /*  PushB[7]  */  Ins_PUSHB,
+    /*  PushW[0]  */  Ins_PUSHW,
+    /*  PushW[1]  */  Ins_PUSHW,
+    /*  PushW[2]  */  Ins_PUSHW,
+    /*  PushW[3]  */  Ins_PUSHW,
+    /*  PushW[4]  */  Ins_PUSHW,
+    /*  PushW[5]  */  Ins_PUSHW,
+    /*  PushW[6]  */  Ins_PUSHW,
+    /*  PushW[7]  */  Ins_PUSHW,
+
+    /*  MDRP[00]  */  Ins_MDRP,
+    /*  MDRP[01]  */  Ins_MDRP,
+    /*  MDRP[02]  */  Ins_MDRP,
+    /*  MDRP[03]  */  Ins_MDRP,
+    /*  MDRP[04]  */  Ins_MDRP,
+    /*  MDRP[05]  */  Ins_MDRP,
+    /*  MDRP[06]  */  Ins_MDRP,
+    /*  MDRP[07]  */  Ins_MDRP,
+    /*  MDRP[08]  */  Ins_MDRP,
+    /*  MDRP[09]  */  Ins_MDRP,
+    /*  MDRP[10]  */  Ins_MDRP,
+    /*  MDRP[11]  */  Ins_MDRP,
+    /*  MDRP[12]  */  Ins_MDRP,
+    /*  MDRP[13]  */  Ins_MDRP,
+    /*  MDRP[14]  */  Ins_MDRP,
+    /*  MDRP[15]  */  Ins_MDRP,
+
+    /*  MDRP[16]  */  Ins_MDRP,
+    /*  MDRP[17]  */  Ins_MDRP,
+    /*  MDRP[18]  */  Ins_MDRP,
+    /*  MDRP[19]  */  Ins_MDRP,
+    /*  MDRP[20]  */  Ins_MDRP,
+    /*  MDRP[21]  */  Ins_MDRP,
+    /*  MDRP[22]  */  Ins_MDRP,
+    /*  MDRP[23]  */  Ins_MDRP,
+    /*  MDRP[24]  */  Ins_MDRP,
+    /*  MDRP[25]  */  Ins_MDRP,
+    /*  MDRP[26]  */  Ins_MDRP,
+    /*  MDRP[27]  */  Ins_MDRP,
+    /*  MDRP[28]  */  Ins_MDRP,
+    /*  MDRP[29]  */  Ins_MDRP,
+    /*  MDRP[30]  */  Ins_MDRP,
+    /*  MDRP[31]  */  Ins_MDRP,
+
+    /*  MIRP[00]  */  Ins_MIRP,
+    /*  MIRP[01]  */  Ins_MIRP,
+    /*  MIRP[02]  */  Ins_MIRP,
+    /*  MIRP[03]  */  Ins_MIRP,
+    /*  MIRP[04]  */  Ins_MIRP,
+    /*  MIRP[05]  */  Ins_MIRP,
+    /*  MIRP[06]  */  Ins_MIRP,
+    /*  MIRP[07]  */  Ins_MIRP,
+    /*  MIRP[08]  */  Ins_MIRP,
+    /*  MIRP[09]  */  Ins_MIRP,
+    /*  MIRP[10]  */  Ins_MIRP,
+    /*  MIRP[11]  */  Ins_MIRP,
+    /*  MIRP[12]  */  Ins_MIRP,
+    /*  MIRP[13]  */  Ins_MIRP,
+    /*  MIRP[14]  */  Ins_MIRP,
+    /*  MIRP[15]  */  Ins_MIRP,
+
+    /*  MIRP[16]  */  Ins_MIRP,
+    /*  MIRP[17]  */  Ins_MIRP,
+    /*  MIRP[18]  */  Ins_MIRP,
+    /*  MIRP[19]  */  Ins_MIRP,
+    /*  MIRP[20]  */  Ins_MIRP,
+    /*  MIRP[21]  */  Ins_MIRP,
+    /*  MIRP[22]  */  Ins_MIRP,
+    /*  MIRP[23]  */  Ins_MIRP,
+    /*  MIRP[24]  */  Ins_MIRP,
+    /*  MIRP[25]  */  Ins_MIRP,
+    /*  MIRP[26]  */  Ins_MIRP,
+    /*  MIRP[27]  */  Ins_MIRP,
+    /*  MIRP[28]  */  Ins_MIRP,
+    /*  MIRP[29]  */  Ins_MIRP,
+    /*  MIRP[30]  */  Ins_MIRP,
+    /*  MIRP[31]  */  Ins_MIRP
+  };
+
+
+#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* RUN                                                                   */
+  /*                                                                       */
+  /*  This function executes a run of opcodes.  It will exit in the        */
+  /*  following cases:                                                     */
+  /*                                                                       */
+  /*  - Errors (in which case it returns FALSE).                           */
+  /*                                                                       */
+  /*  - Reaching the end of the main code range (returns TRUE).            */
+  /*    Reaching the end of a code range within a function call is an      */
+  /*    error.                                                             */
+  /*                                                                       */
+  /*  - After executing one single opcode, if the flag `Instruction_Trap'  */
+  /*    is set to TRUE (returns TRUE).                                     */
+  /*                                                                       */
+  /*  On exit whith TRUE, test IP < CodeSize to know wether it comes from  */
+  /*  an instruction trap or a normal termination.                         */
+  /*                                                                       */
+  /*                                                                       */
+  /*  Note: The documented DEBUG opcode pops a value from the stack.  This */
+  /*        behaviour is unsupported; here a DEBUG opcode is always an     */
+  /*        error.                                                         */
+  /*                                                                       */
+  /*                                                                       */
+  /* THIS IS THE INTERPRETER'S MAIN LOOP.                                  */
+  /*                                                                       */
+  /*  Instructions appear in the specification's order.                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* documentation is in ttinterp.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  TT_RunIns( TT_ExecContext  exc )
+  {
+    FT_Long  ins_counter = 0;  /* executed instructions counter */
+
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+    cur = *exc;
+#endif
+
+    /* set CVT functions */
+    CUR.tt_metrics.ratio = 0;
+    if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
+    {
+      /* non-square pixels, use the stretched routines */
+      CUR.func_read_cvt  = Read_CVT_Stretched;
+      CUR.func_write_cvt = Write_CVT_Stretched;
+      CUR.func_move_cvt  = Move_CVT_Stretched;
+    }
+    else
+    {
+      /* square pixels, use normal routines */
+      CUR.func_read_cvt  = Read_CVT;
+      CUR.func_write_cvt = Write_CVT;
+      CUR.func_move_cvt  = Move_CVT;
+    }
+
+    COMPUTE_Funcs();
+    COMPUTE_Round( (FT_Byte)exc->GS.round_state );
+
+    do
+    {
+      CUR.opcode = CUR.code[CUR.IP];
+
+      if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 )
+      {
+        if ( CUR.IP + 1 > CUR.codeSize )
+          goto LErrorCodeOverflow_;
+
+        CUR.length = CUR.code[CUR.IP + 1] + 2;
+      }
+
+      if ( CUR.IP + CUR.length > CUR.codeSize )
+        goto LErrorCodeOverflow_;
+
+      /* First, let's check for empty stack and overflow */
+      CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 );
+
+      /* `args' is the top of the stack once arguments have been popped. */
+      /* One can also interpret it as the index of the last argument.    */
+      if ( CUR.args < 0 )
+      {
+        CUR.error = TT_Err_Too_Few_Arguments;
+        goto LErrorLabel_;
+      }
+
+      CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 );
+
+      /* `new_top' is the new top of the stack, after the instruction's */
+      /* execution.  `top' will be set to `new_top' after the `switch'  */
+      /* statement.                                                     */
+      if ( CUR.new_top > CUR.stackSize )
+      {
+        CUR.error = TT_Err_Stack_Overflow;
+        goto LErrorLabel_;
+      }
+
+      CUR.step_ins = TRUE;
+      CUR.error    = TT_Err_Ok;
+
+#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
+
+      {
+        FT_Long*  args   = CUR.stack + CUR.args;
+        FT_Byte   opcode = CUR.opcode;
+
+
+#undef  ARRAY_BOUND_ERROR
+#define ARRAY_BOUND_ERROR  goto Set_Invalid_Ref
+
+
+        switch ( opcode )
+        {
+        case 0x00:  /* SVTCA y  */
+        case 0x01:  /* SVTCA x  */
+        case 0x02:  /* SPvTCA y */
+        case 0x03:  /* SPvTCA x */
+        case 0x04:  /* SFvTCA y */
+        case 0x05:  /* SFvTCA x */
+          {
+            FT_Short AA, BB;
+
+
+            AA = (FT_Short)( ( opcode & 1 ) << 14 );
+            BB = (FT_Short)( AA ^ 0x4000 );
+
+            if ( opcode < 4 )
+            {
+              CUR.GS.projVector.x = AA;
+              CUR.GS.projVector.y = BB;
+
+              CUR.GS.dualVector.x = AA;
+              CUR.GS.dualVector.y = BB;
+            }
+
+            if ( ( opcode & 2 ) == 0 )
+            {
+              CUR.GS.freeVector.x = AA;
+              CUR.GS.freeVector.y = BB;
+            }
+
+            COMPUTE_Funcs();
+          }
+          break;
+
+        case 0x06:  /* SPvTL // */
+        case 0x07:  /* SPvTL +  */
+          DO_SPVTL
+          break;
+
+        case 0x08:  /* SFvTL // */
+        case 0x09:  /* SFvTL +  */
+          DO_SFVTL
+          break;
+
+        case 0x0A:  /* SPvFS */
+          DO_SPVFS
+          break;
+
+        case 0x0B:  /* SFvFS */
+          DO_SFVFS
+          break;
+
+        case 0x0C:  /* GPV */
+          DO_GPV
+          break;
+
+        case 0x0D:  /* GFV */
+          DO_GFV
+          break;
+
+        case 0x0E:  /* SFvTPv */
+          DO_SFVTPV
+          break;
+
+        case 0x0F:  /* ISECT  */
+          Ins_ISECT( EXEC_ARG_ args );
+          break;
+
+        case 0x10:  /* SRP0 */
+          DO_SRP0
+          break;
+
+        case 0x11:  /* SRP1 */
+          DO_SRP1
+          break;
+
+        case 0x12:  /* SRP2 */
+          DO_SRP2
+          break;
+
+        case 0x13:  /* SZP0 */
+          Ins_SZP0( EXEC_ARG_ args );
+          break;
+
+        case 0x14:  /* SZP1 */
+          Ins_SZP1( EXEC_ARG_ args );
+          break;
+
+        case 0x15:  /* SZP2 */
+          Ins_SZP2( EXEC_ARG_ args );
+          break;
+
+        case 0x16:  /* SZPS */
+          Ins_SZPS( EXEC_ARG_ args );
+          break;
+
+        case 0x17:  /* SLOOP */
+          DO_SLOOP
+          break;
+
+        case 0x18:  /* RTG */
+          DO_RTG
+          break;
+
+        case 0x19:  /* RTHG */
+          DO_RTHG
+          break;
+
+        case 0x1A:  /* SMD */
+          DO_SMD
+          break;
+
+        case 0x1B:  /* ELSE */
+          Ins_ELSE( EXEC_ARG_ args );
+          break;
+
+        case 0x1C:  /* JMPR */
+          DO_JMPR
+          break;
+
+        case 0x1D:  /* SCVTCI */
+          DO_SCVTCI
+          break;
+
+        case 0x1E:  /* SSWCI */
+          DO_SSWCI
+          break;
+
+        case 0x1F:  /* SSW */
+          DO_SSW
+          break;
+
+        case 0x20:  /* DUP */
+          DO_DUP
+          break;
+
+        case 0x21:  /* POP */
+          /* nothing :-) */
+          break;
+
+        case 0x22:  /* CLEAR */
+          DO_CLEAR
+          break;
+
+        case 0x23:  /* SWAP */
+          DO_SWAP
+          break;
+
+        case 0x24:  /* DEPTH */
+          DO_DEPTH
+          break;
+
+        case 0x25:  /* CINDEX */
+          DO_CINDEX
+          break;
+
+        case 0x26:  /* MINDEX */
+          Ins_MINDEX( EXEC_ARG_ args );
+          break;
+
+        case 0x27:  /* ALIGNPTS */
+          Ins_ALIGNPTS( EXEC_ARG_ args );
+          break;
+
+        case 0x28:  /* ???? */
+          Ins_UNKNOWN( EXEC_ARG_ args );
+          break;
+
+        case 0x29:  /* UTP */
+          Ins_UTP( EXEC_ARG_ args );
+          break;
+
+        case 0x2A:  /* LOOPCALL */
+          Ins_LOOPCALL( EXEC_ARG_ args );
+          break;
+
+        case 0x2B:  /* CALL */
+          Ins_CALL( EXEC_ARG_ args );
+          break;
+
+        case 0x2C:  /* FDEF */
+          Ins_FDEF( EXEC_ARG_ args );
+          break;
+
+        case 0x2D:  /* ENDF */
+          Ins_ENDF( EXEC_ARG_ args );
+          break;
+
+        case 0x2E:  /* MDAP */
+        case 0x2F:  /* MDAP */
+          Ins_MDAP( EXEC_ARG_ args );
+          break;
+
+
+        case 0x30:  /* IUP */
+        case 0x31:  /* IUP */
+          Ins_IUP( EXEC_ARG_ args );
+          break;
+
+        case 0x32:  /* SHP */
+        case 0x33:  /* SHP */
+          Ins_SHP( EXEC_ARG_ args );
+          break;
+
+        case 0x34:  /* SHC */
+        case 0x35:  /* SHC */
+          Ins_SHC( EXEC_ARG_ args );
+          break;
+
+        case 0x36:  /* SHZ */
+        case 0x37:  /* SHZ */
+          Ins_SHZ( EXEC_ARG_ args );
+          break;
+
+        case 0x38:  /* SHPIX */
+          Ins_SHPIX( EXEC_ARG_ args );
+          break;
+
+        case 0x39:  /* IP    */
+          Ins_IP( EXEC_ARG_ args );
+          break;
+
+        case 0x3A:  /* MSIRP */
+        case 0x3B:  /* MSIRP */
+          Ins_MSIRP( EXEC_ARG_ args );
+          break;
+
+        case 0x3C:  /* AlignRP */
+          Ins_ALIGNRP( EXEC_ARG_ args );
+          break;
+
+        case 0x3D:  /* RTDG */
+          DO_RTDG
+          break;
+
+        case 0x3E:  /* MIAP */
+        case 0x3F:  /* MIAP */
+          Ins_MIAP( EXEC_ARG_ args );
+          break;
+
+        case 0x40:  /* NPUSHB */
+          Ins_NPUSHB( EXEC_ARG_ args );
+          break;
+
+        case 0x41:  /* NPUSHW */
+          Ins_NPUSHW( EXEC_ARG_ args );
+          break;
+
+        case 0x42:  /* WS */
+          DO_WS
+          break;
+
+      Set_Invalid_Ref:
+            CUR.error = TT_Err_Invalid_Reference;
+          break;
+
+        case 0x43:  /* RS */
+          DO_RS
+          break;
+
+        case 0x44:  /* WCVTP */
+          DO_WCVTP
+          break;
+
+        case 0x45:  /* RCVT */
+          DO_RCVT
+          break;
+
+        case 0x46:  /* GC */
+        case 0x47:  /* GC */
+          Ins_GC( EXEC_ARG_ args );
+          break;
+
+        case 0x48:  /* SCFS */
+          Ins_SCFS( EXEC_ARG_ args );
+          break;
+
+        case 0x49:  /* MD */
+        case 0x4A:  /* MD */
+          Ins_MD( EXEC_ARG_ args );
+          break;
+
+        case 0x4B:  /* MPPEM */
+          DO_MPPEM
+          break;
+
+        case 0x4C:  /* MPS */
+          DO_MPS
+          break;
+
+        case 0x4D:  /* FLIPON */
+          DO_FLIPON
+          break;
+
+        case 0x4E:  /* FLIPOFF */
+          DO_FLIPOFF
+          break;
+
+        case 0x4F:  /* DEBUG */
+          DO_DEBUG
+          break;
+
+        case 0x50:  /* LT */
+          DO_LT
+          break;
+
+        case 0x51:  /* LTEQ */
+          DO_LTEQ
+          break;
+
+        case 0x52:  /* GT */
+          DO_GT
+          break;
+
+        case 0x53:  /* GTEQ */
+          DO_GTEQ
+          break;
+
+        case 0x54:  /* EQ */
+          DO_EQ
+          break;
+
+        case 0x55:  /* NEQ */
+          DO_NEQ
+          break;
+
+        case 0x56:  /* ODD */
+          DO_ODD
+          break;
+
+        case 0x57:  /* EVEN */
+          DO_EVEN
+          break;
+
+        case 0x58:  /* IF */
+          Ins_IF( EXEC_ARG_ args );
+          break;
+
+        case 0x59:  /* EIF */
+          /* do nothing */
+          break;
+
+        case 0x5A:  /* AND */
+          DO_AND
+          break;
+
+        case 0x5B:  /* OR */
+          DO_OR
+          break;
+
+        case 0x5C:  /* NOT */
+          DO_NOT
+          break;
+
+        case 0x5D:  /* DELTAP1 */
+          Ins_DELTAP( EXEC_ARG_ args );
+          break;
+
+        case 0x5E:  /* SDB */
+          DO_SDB
+          break;
+
+        case 0x5F:  /* SDS */
+          DO_SDS
+          break;
+
+        case 0x60:  /* ADD */
+          DO_ADD
+          break;
+
+        case 0x61:  /* SUB */
+          DO_SUB
+          break;
+
+        case 0x62:  /* DIV */
+          DO_DIV
+          break;
+
+        case 0x63:  /* MUL */
+          DO_MUL
+          break;
+
+        case 0x64:  /* ABS */
+          DO_ABS
+          break;
+
+        case 0x65:  /* NEG */
+          DO_NEG
+          break;
+
+        case 0x66:  /* FLOOR */
+          DO_FLOOR
+          break;
+
+        case 0x67:  /* CEILING */
+          DO_CEILING
+          break;
+
+        case 0x68:  /* ROUND */
+        case 0x69:  /* ROUND */
+        case 0x6A:  /* ROUND */
+        case 0x6B:  /* ROUND */
+          DO_ROUND
+          break;
+
+        case 0x6C:  /* NROUND */
+        case 0x6D:  /* NROUND */
+        case 0x6E:  /* NRRUND */
+        case 0x6F:  /* NROUND */
+          DO_NROUND
+          break;
+
+        case 0x70:  /* WCVTF */
+          DO_WCVTF
+          break;
+
+        case 0x71:  /* DELTAP2 */
+        case 0x72:  /* DELTAP3 */
+          Ins_DELTAP( EXEC_ARG_ args );
+          break;
+
+        case 0x73:  /* DELTAC0 */
+        case 0x74:  /* DELTAC1 */
+        case 0x75:  /* DELTAC2 */
+          Ins_DELTAC( EXEC_ARG_ args );
+          break;
+
+        case 0x76:  /* SROUND */
+          DO_SROUND
+          break;
+
+        case 0x77:  /* S45Round */
+          DO_S45ROUND
+          break;
+
+        case 0x78:  /* JROT */
+          DO_JROT
+          break;
+
+        case 0x79:  /* JROF */
+          DO_JROF
+          break;
+
+        case 0x7A:  /* ROFF */
+          DO_ROFF
+          break;
+
+        case 0x7B:  /* ???? */
+          Ins_UNKNOWN( EXEC_ARG_ args );
+          break;
+
+        case 0x7C:  /* RUTG */
+          DO_RUTG
+          break;
+
+        case 0x7D:  /* RDTG */
+          DO_RDTG
+          break;
+
+        case 0x7E:  /* SANGW */
+        case 0x7F:  /* AA    */
+          /* nothing - obsolete */
+          break;
+
+        case 0x80:  /* FLIPPT */
+          Ins_FLIPPT( EXEC_ARG_ args );
+          break;
+
+        case 0x81:  /* FLIPRGON */
+          Ins_FLIPRGON( EXEC_ARG_ args );
+          break;
+
+        case 0x82:  /* FLIPRGOFF */
+          Ins_FLIPRGOFF( EXEC_ARG_ args );
+          break;
+
+        case 0x83:  /* UNKNOWN */
+        case 0x84:  /* UNKNOWN */
+          Ins_UNKNOWN( EXEC_ARG_ args );
+          break;
+
+        case 0x85:  /* SCANCTRL */
+          Ins_SCANCTRL( EXEC_ARG_ args );
+          break;
+
+        case 0x86:  /* SDPVTL */
+        case 0x87:  /* SDPVTL */
+          Ins_SDPVTL( EXEC_ARG_ args );
+          break;
+
+        case 0x88:  /* GETINFO */
+          Ins_GETINFO( EXEC_ARG_ args );
+          break;
+
+        case 0x89:  /* IDEF */
+          Ins_IDEF( EXEC_ARG_ args );
+          break;
+
+        case 0x8A:  /* ROLL */
+          Ins_ROLL( EXEC_ARG_ args );
+          break;
+
+        case 0x8B:  /* MAX */
+          DO_MAX
+          break;
+
+        case 0x8C:  /* MIN */
+          DO_MIN
+          break;
+
+        case 0x8D:  /* SCANTYPE */
+          Ins_SCANTYPE( EXEC_ARG_ args );
+          break;
+
+        case 0x8E:  /* INSTCTRL */
+          Ins_INSTCTRL( EXEC_ARG_ args );
+          break;
+
+        case 0x8F:
+          Ins_UNKNOWN( EXEC_ARG_ args );
+          break;
+
+        default:
+          if ( opcode >= 0xE0 )
+            Ins_MIRP( EXEC_ARG_ args );
+          else if ( opcode >= 0xC0 )
+            Ins_MDRP( EXEC_ARG_ args );
+          else if ( opcode >= 0xB8 )
+            Ins_PUSHW( EXEC_ARG_ args );
+          else if ( opcode >= 0xB0 )
+            Ins_PUSHB( EXEC_ARG_ args );
+          else
+            Ins_UNKNOWN( EXEC_ARG_ args );
+        }
+
+      }
+
+#else
+
+      Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] );
+
+#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
+
+      if ( CUR.error != TT_Err_Ok )
+      {
+        switch ( CUR.error )
+        {
+        case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
+          {
+            TT_DefRecord*  def   = CUR.IDefs;
+            TT_DefRecord*  limit = def + CUR.numIDefs;
+
+
+            for ( ; def < limit; def++ )
+            {
+              if ( def->active && CUR.opcode == (FT_Byte)def->opc )
+              {
+                TT_CallRec*  callrec;
+
+
+                if ( CUR.callTop >= CUR.callSize )
+                {
+                  CUR.error = TT_Err_Invalid_Reference;
+                  goto LErrorLabel_;
+                }
+
+                callrec = &CUR.callStack[CUR.callTop];
+
+                callrec->Caller_Range = CUR.curRange;
+                callrec->Caller_IP    = CUR.IP + 1;
+                callrec->Cur_Count    = 1;
+                callrec->Cur_Restart  = def->start;
+
+                if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
+                  goto LErrorLabel_;
+
+                goto LSuiteLabel_;
+              }
+            }
+          }
+
+          CUR.error = TT_Err_Invalid_Opcode;
+          goto LErrorLabel_;
+
+#if 0
+          break;   /* Unreachable code warning suppression.             */
+                   /* Leave to remind in case a later change the editor */
+                   /* to consider break;                                */
+#endif
+
+        default:
+          goto LErrorLabel_;
+
+#if 0
+        break;
+#endif
+        }
+      }
+
+      CUR.top = CUR.new_top;
+
+      if ( CUR.step_ins )
+        CUR.IP += CUR.length;
+
+      /* increment instruction counter and check if we didn't */
+      /* run this program for too long (e.g. infinite loops). */
+      if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
+        return TT_Err_Execution_Too_Long;
+
+    LSuiteLabel_:
+      if ( CUR.IP >= CUR.codeSize )
+      {
+        if ( CUR.callTop > 0 )
+        {
+          CUR.error = TT_Err_Code_Overflow;
+          goto LErrorLabel_;
+        }
+        else
+          goto LNo_Error_;
+      }
+    } while ( !CUR.instruction_trap );
+
+  LNo_Error_:
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+    *exc = cur;
+#endif
+
+    return TT_Err_Ok;
+
+  LErrorCodeOverflow_:
+    CUR.error = TT_Err_Code_Overflow;
+
+  LErrorLabel_:
+
+#ifdef TT_CONFIG_OPTION_STATIC_RASTER
+    *exc = cur;
+#endif
+
+    return CUR.error;
+  }
+
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ttload.c b/libraries/freetype-2.0.5/ttload.c
new file mode 100644 (file)
index 0000000..0c9a178
--- /dev/null
@@ -0,0 +1,1820 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttload.c                                                               */
+/*                                                                         */
+/*    Load the basic TrueType tables, i.e., tables that can be either in   */
+/*    TTF or OTF fonts (body).                                             */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include "ttload.h"
+#include "ttcmap.h"
+
+#include "sferrors.h"
+
+#include <stdlib.h>  /* for qsort */
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttload
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_LookUp_Table                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Looks for a TrueType table by name.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A face object handle.                                      */
+  /*    tag  :: The searched tag.                                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    A pointer to the table directory entry.  0 if not found.           */
+  /*                                                                       */
+  FT_LOCAL_DEF TT_Table*
+  TT_LookUp_Table( TT_Face   face,
+                   FT_ULong  tag  )
+  {
+    TT_Table*  entry;
+    TT_Table*  limit;
+
+
+    FT_TRACE3(( "TT_LookUp_Table: %08p, `%c%c%c%c' -- ",
+                face,
+                (FT_Char)( tag >> 24 ),
+                (FT_Char)( tag >> 16 ),
+                (FT_Char)( tag >> 8  ),
+                (FT_Char)( tag       ) ));
+
+    entry = face->dir_tables;
+    limit = entry + face->num_tables;
+
+    for ( ; entry < limit; entry++ )
+    {
+      if ( entry->Tag == tag )
+      {
+        FT_TRACE3(( "found table.\n" ));
+        return entry;
+      }
+    }
+
+    FT_TRACE3(( "could not find table!\n" ));
+    return 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Goto_Table                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Looks for a TrueType table by name, then seek a stream to it.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A face object handle.                                    */
+  /*    tag    :: The searched tag.                                        */
+  /*    stream :: The stream to seek when the table is found.              */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    length :: The length of the table if found, undefined otherwise.   */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Goto_Table( TT_Face    face,
+                 FT_ULong   tag,
+                 FT_Stream  stream,
+                 FT_ULong*  length )
+  {
+    TT_Table*  table;
+    FT_Error   error;
+
+
+    table = TT_LookUp_Table( face, tag );
+    if ( table )
+    {
+      if ( length )
+        *length = table->Length;
+
+      if ( FILE_Seek( table->Offset ) )
+       goto Exit;
+    }
+    else
+      error = SFNT_Err_Table_Missing;
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SFNT_Header                                                */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the header of a SFNT font file.  Supports collections.       */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face       :: A handle to the target face object.                  */
+  /*    stream     :: The input stream.                                    */
+  /*    face_index :: If the font is a collection, the number of the font  */
+  /*                  in the collection, ignored otherwise.                */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    sfnt       :: The SFNT header.                                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be at the font file's origin.               */
+  /*                                                                       */
+  /*    This function recognizes fonts embedded in a `TrueType collection' */
+  /*                                                                       */
+  /*    The header will be checked whether it is valid by looking at the   */
+  /*    values of `search_range', `entry_selector', and `range_shift'.     */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_SFNT_Header( TT_Face       face,
+                       FT_Stream     stream,
+                       FT_Long       face_index,
+                       SFNT_Header*  sfnt )
+  {
+    FT_Error   error;
+    FT_ULong   format_tag;
+    FT_Memory  memory = stream->memory;
+
+    const FT_Frame_Field  sfnt_header_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  SFNT_Header
+
+      FT_FRAME_START( 8 ),
+        FT_FRAME_USHORT( num_tables ),
+        FT_FRAME_USHORT( search_range ),
+        FT_FRAME_USHORT( entry_selector ),
+        FT_FRAME_USHORT( range_shift ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  ttc_header_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TTC_Header
+
+      FT_FRAME_START( 8 ),
+        FT_FRAME_LONG( version ),
+        FT_FRAME_LONG( count   ),
+      FT_FRAME_END };
+
+
+    FT_TRACE2(( "TT_Load_SFNT_Header: %08p, %ld\n",
+                face, face_index ));
+
+    face->ttc_header.tag      = 0;
+    face->ttc_header.version  = 0;
+    face->ttc_header.count    = 0;
+
+    face->num_tables = 0;
+
+    /* first of all, read the first 4 bytes.  If it is `ttcf', then the */
+    /* file is a TrueType collection, otherwise it can be any other     */
+    /* kind of font.                                                    */
+    if ( READ_ULong( format_tag ) )
+      goto Exit;
+
+    if ( format_tag == TTAG_ttcf )
+    {
+      FT_Int  n;
+
+
+      FT_TRACE3(( "TT_Load_SFNT_Header: file is a collection\n" ));
+
+      /* it's a TrueType collection, i.e. a file containing several */
+      /* font files.  Read the font directory now                   */
+      if ( READ_Fields( ttc_header_fields, &face->ttc_header ) )
+        goto Exit;
+
+      /* now read the offsets of each font in the file */
+      if ( ALLOC_ARRAY( face->ttc_header.offsets,
+                        face->ttc_header.count,
+                        FT_ULong )                     ||
+           ACCESS_Frame( face->ttc_header.count * 4L ) )
+        goto Exit;
+
+      for ( n = 0; n < face->ttc_header.count; n++ )
+        face->ttc_header.offsets[n] = GET_ULong();
+
+      FORGET_Frame();
+
+      /* check face index */
+      if ( face_index >= face->ttc_header.count )
+      {
+        error = SFNT_Err_Bad_Argument;
+        goto Exit;
+      }
+
+      /* seek to the appropriate TrueType file, then read tag */
+      if ( FILE_Seek( face->ttc_header.offsets[face_index] ) ||
+           READ_Long( format_tag )                           )
+        goto Exit;
+    }
+
+    /* the format tag was read, now check the rest of the header */
+    sfnt->format_tag = format_tag;
+    if ( READ_Fields( sfnt_header_fields, sfnt ) )
+      goto Exit;
+
+    /* now, check the values of `num_tables', `seach_range', etc. */
+    {
+      FT_UInt   num_tables     = sfnt->num_tables;
+      FT_ULong  entry_selector = 1L << sfnt->entry_selector;
+
+
+      /* IMPORTANT: Many fonts have an incorrect `search_range' value, so */
+      /*            we only check the `entry_selector' correctness here.  */
+      /*                                                                  */
+      if ( num_tables == 0                  ||
+           entry_selector > num_tables      ||
+           entry_selector * 2 <= num_tables )
+      {
+        FT_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" ));
+        error = SFNT_Err_Unknown_File_Format;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Directory                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the table directory into a face object.                      */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: The input stream.                                        */
+  /*    sfnt   :: The SFNT directory header.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be at the font file's origin.               */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Directory( TT_Face       face,
+                     FT_Stream     stream,
+                     SFNT_Header*  sfnt )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+    TT_Table *entry, *limit;
+
+
+    FT_TRACE2(( "TT_Load_Directory: %08p\n", face ));
+
+    FT_TRACE2(( "-- Tables count:   %12u\n",  sfnt->num_tables ));
+    FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag ));
+
+    face->num_tables = sfnt->num_tables;
+
+    if ( ALLOC_ARRAY( face->dir_tables,
+                      face->num_tables,
+                      TT_Table ) )
+      goto Exit;
+
+    if ( ACCESS_Frame( face->num_tables * 16L ) )
+      goto Exit;
+
+    entry = face->dir_tables;
+    limit = entry + face->num_tables;
+
+    for ( ; entry < limit; entry++ )
+    {                    /* loop through the tables and get all entries */
+      entry->Tag      = GET_Tag4();
+      entry->CheckSum = GET_ULong();
+      entry->Offset   = GET_Long();
+      entry->Length   = GET_Long();
+
+      FT_TRACE2(( "  %c%c%c%c  -  %08lx  -  %08lx\n",
+                  (FT_Char)( entry->Tag >> 24 ),
+                  (FT_Char)( entry->Tag >> 16 ),
+                  (FT_Char)( entry->Tag >> 8  ),
+                  (FT_Char)( entry->Tag       ),
+                  entry->Offset,
+                  entry->Length ));
+    }
+
+    FORGET_Frame();
+
+    FT_TRACE2(( "Directory loaded\n\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Any                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads any font table into client memory.                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: The face object to look for.                             */
+  /*                                                                       */
+  /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
+  /*              to access the whole font file, else set this parameter   */
+  /*              to a valid TrueType table tag that you can forge with    */
+  /*              the MAKE_TT_TAG macro.                                   */
+  /*                                                                       */
+  /*    offset :: The starting offset in the table (or the file if         */
+  /*              tag == 0).                                               */
+  /*                                                                       */
+  /*    length :: The address of the decision variable:                    */
+  /*                                                                       */
+  /*                If length == NULL:                                     */
+  /*                  Loads the whole table.  Returns an error if          */
+  /*                  `offset' == 0!                                       */
+  /*                                                                       */
+  /*                If *length == 0:                                       */
+  /*                  Exits immediately; returning the length of the given */
+  /*                  table or of the font file, depending on the value of */
+  /*                  `tag'.                                               */
+  /*                                                                       */
+  /*                If *length != 0:                                       */
+  /*                  Loads the next `length' bytes of table or font,      */
+  /*                  starting at offset `offset' (in table or font too).  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    buffer :: The address of target buffer.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Any( TT_Face    face,
+               FT_ULong   tag,
+               FT_Long    offset,
+               FT_Byte*   buffer,
+               FT_ULong*  length )
+  {
+    FT_Error   error;
+    FT_Stream  stream;
+    TT_Table*  table;
+    FT_ULong   size;
+
+
+    if ( tag != 0 )
+    {
+      /* look for tag in font directory */
+      table = TT_LookUp_Table( face, tag );
+      if ( !table )
+      {
+        error = SFNT_Err_Table_Missing;
+        goto Exit;
+      }
+
+      offset += table->Offset;
+      size    = table->Length;
+    }
+    else
+      /* tag == 0 -- the user wants to access the font file directly */
+      size = face->root.stream->size;
+
+    if ( length && *length == 0 )
+    {
+      *length = size;
+
+      return SFNT_Err_Ok;
+    }
+
+    if ( length )
+      size = *length;
+
+    stream = face->root.stream;
+    /* the `if' is syntactic sugar for picky compilers */
+    if ( FILE_Read_At( offset, buffer, size ) )
+      goto Exit;
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Generic_Header                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the TrueType table `head' or `bhed'.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  TT_Load_Generic_Header( TT_Face    face,
+                          FT_Stream  stream,
+                          FT_ULong   tag )
+  {
+    FT_Error    error;
+    TT_Header*  header;
+
+    static const FT_Frame_Field  header_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_Header
+
+      FT_FRAME_START( 54 ),
+        FT_FRAME_ULONG ( Table_Version ),
+        FT_FRAME_ULONG ( Font_Revision ),
+        FT_FRAME_LONG  ( CheckSum_Adjust ),
+        FT_FRAME_LONG  ( Magic_Number ),
+        FT_FRAME_USHORT( Flags ),
+        FT_FRAME_USHORT( Units_Per_EM ),
+        FT_FRAME_LONG  ( Created[0] ),
+        FT_FRAME_LONG  ( Created[1] ),
+        FT_FRAME_LONG  ( Modified[0] ),
+        FT_FRAME_LONG  ( Modified[1] ),
+        FT_FRAME_SHORT ( xMin ),
+        FT_FRAME_SHORT ( yMin ),
+        FT_FRAME_SHORT ( xMax ),
+        FT_FRAME_SHORT ( yMax ),
+        FT_FRAME_USHORT( Mac_Style ),
+        FT_FRAME_USHORT( Lowest_Rec_PPEM ),
+        FT_FRAME_SHORT ( Font_Direction ),
+        FT_FRAME_SHORT ( Index_To_Loc_Format ),
+        FT_FRAME_SHORT ( Glyph_Data_Format ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "TT_Load_Generic_Header: "
+                "%08p, looking up font table `%c%c%c%c'.\n",
+                face,
+                (FT_Char)( tag >> 24 ),
+                (FT_Char)( tag >> 16 ),
+                (FT_Char)( tag >> 8  ),
+                (FT_Char)( tag       ) ));
+
+    error = face->goto_table( face, tag, stream, 0 );
+    if ( error )
+    {
+      FT_TRACE2(( "TT_Load_Generic_Table: Font table is missing!\n" ));
+      goto Exit;
+    }
+
+    header = &face->header;
+
+    if ( READ_Fields( header_fields, header ) )
+      goto Exit;
+
+    FT_TRACE2(( "    Units per EM: %8u\n", header->Units_Per_EM ));
+    FT_TRACE2(( "    IndexToLoc:   %8d\n", header->Index_To_Loc_Format ));
+    FT_TRACE2(( "TT_Load_Generic_Table: Font table loaded.\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Header( TT_Face    face,
+                  FT_Stream  stream )
+  {
+    return TT_Load_Generic_Header( face, stream, TTAG_head );
+  }
+
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Bitmap_Header( TT_Face    face,
+                         FT_Stream  stream )
+  {
+    return TT_Load_Generic_Header( face, stream, TTAG_bhed );
+  }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_MaxProfile                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the maximum profile into a face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_MaxProfile( TT_Face    face,
+                      FT_Stream  stream )
+  {
+    FT_Error        error;
+    TT_MaxProfile*  maxProfile = &face->max_profile;
+
+    const FT_Frame_Field  maxp_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_MaxProfile
+
+      FT_FRAME_START( 6 ),
+        FT_FRAME_LONG  ( version ),
+        FT_FRAME_USHORT( numGlyphs ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  maxp_fields_extra[] =
+    {
+      FT_FRAME_START( 26 ),
+        FT_FRAME_USHORT( maxPoints ),
+        FT_FRAME_USHORT( maxContours ),
+        FT_FRAME_USHORT( maxCompositePoints ),
+        FT_FRAME_USHORT( maxCompositeContours ),
+        FT_FRAME_USHORT( maxZones ),
+        FT_FRAME_USHORT( maxTwilightPoints ),
+        FT_FRAME_USHORT( maxStorage ),
+        FT_FRAME_USHORT( maxFunctionDefs ),
+        FT_FRAME_USHORT( maxInstructionDefs ),
+        FT_FRAME_USHORT( maxStackElements ),
+        FT_FRAME_USHORT( maxSizeOfInstructions ),
+        FT_FRAME_USHORT( maxComponentElements ),
+        FT_FRAME_USHORT( maxComponentDepth ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face ));
+
+    error = face->goto_table( face, TTAG_maxp, stream, 0 );
+    if ( error )
+      goto Exit;
+
+    if ( READ_Fields( maxp_fields, maxProfile ) )
+      goto Exit;
+
+    maxProfile->maxPoints             = 0;
+    maxProfile->maxContours           = 0;
+    maxProfile->maxCompositePoints    = 0;
+    maxProfile->maxCompositeContours  = 0;
+    maxProfile->maxZones              = 0;
+    maxProfile->maxTwilightPoints     = 0;
+    maxProfile->maxStorage            = 0;
+    maxProfile->maxFunctionDefs       = 0;
+    maxProfile->maxInstructionDefs    = 0;
+    maxProfile->maxStackElements      = 0;
+    maxProfile->maxSizeOfInstructions = 0;
+    maxProfile->maxComponentElements  = 0;
+    maxProfile->maxComponentDepth     = 0;
+
+    if ( maxProfile->version >= 0x10000L )
+    {
+      if ( READ_Fields( maxp_fields_extra, maxProfile ) )
+        goto Exit;
+
+      /* XXX: an adjustment that is necessary to load certain */
+      /*      broken fonts like `Keystrokes MT' :-(           */
+      /*                                                      */
+      /*   We allocate 64 function entries by default when    */
+      /*   the maxFunctionDefs field is null.                 */
+
+      if ( maxProfile->maxFunctionDefs == 0 )
+        maxProfile->maxFunctionDefs = 64;
+
+      face->root.num_glyphs = maxProfile->numGlyphs;
+
+      face->root.internal->max_points =
+        (FT_UShort)MAX( maxProfile->maxCompositePoints,
+                        maxProfile->maxPoints );
+
+      face->root.internal->max_contours =
+        (FT_Short)MAX( maxProfile->maxCompositeContours,
+                       maxProfile->maxContours );
+
+      face->max_components = (FT_ULong)maxProfile->maxComponentElements +
+                             maxProfile->maxComponentDepth;
+
+      /* XXX: some fonts have maxComponents set to 0; we will */
+      /*      then use 16 of them by default.                 */
+      if ( face->max_components == 0 )
+        face->max_components = 16;
+
+      /* We also increase maxPoints and maxContours in order to support */
+      /* some broken fonts.                                             */
+      face->root.internal->max_points   += 8;
+      face->root.internal->max_contours += 4;
+    }
+
+    FT_TRACE2(( "MAXP loaded.\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Metrics                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the horizontal or vertical metrics table into a face object. */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the target face object.                    */
+  /*    stream   :: The input stream.                                      */
+  /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  TT_Load_Metrics( TT_Face    face,
+                   FT_Stream  stream,
+                   FT_Bool    vertical )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+    FT_ULong   table_len;
+    FT_Long    num_shorts, num_longs, num_shorts_checked;
+
+    TT_LongMetrics**   longs;
+    TT_ShortMetrics**  shorts;
+
+
+    FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
+                                                       : "Horizontal",
+                                              face ));
+
+    if ( vertical )
+    {
+      /* The table is optional, quit silently if it wasn't found       */
+      /* XXX: Some fonts have a valid vertical header with a non-null  */
+      /*      `number_of_VMetrics' fields, but no corresponding `vmtx' */
+      /*      table to get the metrics from (e.g. mingliu).            */
+      /*                                                               */
+      /*      For safety, we set the field to 0!                       */
+      /*                                                               */
+      error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
+      if ( error )
+      {
+        /* Set number_Of_VMetrics to 0! */
+        FT_TRACE2(( "  no vertical header in file.\n" ));
+        face->vertical.number_Of_VMetrics = 0;
+        error = SFNT_Err_Ok;
+        goto Exit;
+      }
+
+      num_longs = face->vertical.number_Of_VMetrics;
+      longs     = (TT_LongMetrics**)&face->vertical.long_metrics;
+      shorts    = (TT_ShortMetrics**)&face->vertical.short_metrics;
+    }
+    else
+    {
+      error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
+      if ( error )
+      {
+        FT_ERROR(( " no horizontal metrics in file!\n" ));
+        error = SFNT_Err_Hmtx_Table_Missing;
+        goto Exit;
+      }
+
+      num_longs = face->horizontal.number_Of_HMetrics;
+      longs     = (TT_LongMetrics**)&face->horizontal.long_metrics;
+      shorts    = (TT_ShortMetrics**)&face->horizontal.short_metrics;
+    }
+
+    /* never trust derived values */
+
+    num_shorts         = face->max_profile.numGlyphs - num_longs;
+    num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
+
+    if ( num_shorts < 0 )
+    {
+      FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
+                 vertical ? "Vertical"
+                          : "Horizontal" ));
+
+      error = vertical ? SFNT_Err_Invalid_Vert_Metrics
+                       : SFNT_Err_Invalid_Horiz_Metrics;
+      goto Exit;
+    }
+
+    if ( ALLOC_ARRAY( *longs,  num_longs,  TT_LongMetrics )  ||
+         ALLOC_ARRAY( *shorts, num_shorts, TT_ShortMetrics ) )
+      goto Exit;
+
+    if ( ACCESS_Frame( table_len ) )
+      goto Exit;
+
+    {
+      TT_LongMetrics*  cur   = *longs;
+      TT_LongMetrics*  limit = cur + num_longs;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        cur->advance = GET_UShort();
+        cur->bearing = GET_Short();
+      }
+    }
+
+    /* do we have an inconsistent number of metric values? */
+    {
+      TT_ShortMetrics*  cur   = *shorts;
+      TT_ShortMetrics*  limit = cur + MIN( num_shorts, num_shorts_checked );
+
+
+      for ( ; cur < limit; cur++ )
+        *cur = GET_Short();
+
+      /* we fill up the missing left side bearings with the     */
+      /* last valid value.  Since this will occur for buggy CJK */
+      /* fonts usually only, nothing serious will happen        */
+      if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
+      {
+        FT_Short  val = (*shorts)[num_shorts_checked - 1];
+
+
+        limit = *shorts + num_shorts;
+        for ( ; cur < limit; cur++ )
+          *cur = val;
+      }
+    }
+
+    FORGET_Frame();
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Metrics_Header                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the horizontal or vertical header in a face object.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face     :: A handle to the target face object.                    */
+  /*    stream   :: The input stream.                                      */
+  /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Metrics_Header( TT_Face    face,
+                          FT_Stream  stream,
+                          FT_Bool    vertical )
+  {
+    FT_Error        error;
+    TT_HoriHeader*  header;
+
+    const FT_Frame_Field  metrics_header_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_HoriHeader
+
+      FT_FRAME_START( 36 ),
+        FT_FRAME_ULONG ( Version ),
+        FT_FRAME_SHORT ( Ascender ),
+        FT_FRAME_SHORT ( Descender ),
+        FT_FRAME_SHORT ( Line_Gap ),
+        FT_FRAME_USHORT( advance_Width_Max ),
+        FT_FRAME_SHORT ( min_Left_Side_Bearing ),
+        FT_FRAME_SHORT ( min_Right_Side_Bearing ),
+        FT_FRAME_SHORT ( xMax_Extent ),
+        FT_FRAME_SHORT ( caret_Slope_Rise ),
+        FT_FRAME_SHORT ( caret_Slope_Run ),
+        FT_FRAME_SHORT ( caret_Offset ),
+        FT_FRAME_SHORT ( Reserved[0] ),
+        FT_FRAME_SHORT ( Reserved[1] ),
+        FT_FRAME_SHORT ( Reserved[2] ),
+        FT_FRAME_SHORT ( Reserved[3] ),
+        FT_FRAME_SHORT ( metric_Data_Format ),
+        FT_FRAME_USHORT( number_Of_HMetrics ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
+
+    if ( vertical )
+    {
+      face->vertical_info = 0;
+
+      /* The vertical header table is optional, so return quietly if */
+      /* we don't find it.                                           */
+      error = face->goto_table( face, TTAG_vhea, stream, 0 );
+      if ( error )
+      {
+        error = SFNT_Err_Ok;
+        goto Exit;
+      }
+
+      face->vertical_info = 1;
+      header = (TT_HoriHeader*)&face->vertical;
+    }
+    else
+    {
+      /* The horizontal header is mandatory; return an error if we */
+      /* don't find it.                                            */
+      error = face->goto_table( face, TTAG_hhea, stream, 0 );
+      if ( error )
+      {
+        error = SFNT_Err_Horiz_Header_Missing;
+        goto Exit;
+      }
+
+      header = &face->horizontal;
+    }
+
+    if ( READ_Fields( metrics_header_fields, header ) )
+      goto Exit;
+
+    header->long_metrics  = NULL;
+    header->short_metrics = NULL;
+
+    FT_TRACE2(( "loaded\n" ));
+
+    /* Now try to load the corresponding metrics */
+
+    error = TT_Load_Metrics( face, stream, vertical );
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Names                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the name records.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Names( TT_Face    face,
+                 FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+    FT_ULong   table_pos, table_len;
+    FT_ULong   storageSize;
+
+    TT_NameTable*  names;
+
+    const FT_Frame_Field  name_table_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_NameTable
+
+      FT_FRAME_START( 6 ),
+        FT_FRAME_USHORT( format ),
+        FT_FRAME_USHORT( numNameRecords ),
+        FT_FRAME_USHORT( storageOffset ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  name_record_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_NameRec
+
+      /* no FT_FRAME_START */
+        FT_FRAME_USHORT( platformID ),
+        FT_FRAME_USHORT( encodingID ),
+        FT_FRAME_USHORT( languageID ),
+        FT_FRAME_USHORT( nameID ),
+        FT_FRAME_USHORT( stringLength ),
+        FT_FRAME_USHORT( stringOffset ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "Names " ));
+
+    error = face->goto_table( face, TTAG_name, stream, &table_len );
+    if ( error )
+    {
+      /* The name table is required so indicate failure. */
+      FT_TRACE2(( "is missing!\n" ));
+      error = SFNT_Err_Name_Table_Missing;
+      goto Exit;
+    }
+
+    table_pos = FILE_Pos();
+
+    names = &face->name_table;
+
+    if ( READ_Fields( name_table_fields, names ) )
+      goto Exit;
+
+    /* Allocate the array of name records. */
+    if ( ALLOC_ARRAY( names->names,
+                      names->numNameRecords,
+                      TT_NameRec )                   ||
+         ACCESS_Frame( names->numNameRecords * 12L ) )
+      goto Exit;
+
+    /* Load the name records and determine how much storage is needed */
+    /* to hold the strings themselves.                                */
+    {
+      TT_NameRec*  cur   = names->names;
+      TT_NameRec*  limit = cur + names->numNameRecords;
+
+
+      storageSize = 0;
+
+      for ( ; cur < limit; cur ++ )
+      {
+        FT_ULong  upper;
+
+
+        if ( READ_Fields( name_record_fields, cur ) )
+          break;
+
+        upper = (FT_ULong)( cur->stringOffset + cur->stringLength );
+        if ( upper > storageSize )
+          storageSize = upper;
+      }
+    }
+
+    FORGET_Frame();
+
+    if ( storageSize > 0 )
+    {
+      /* allocate the name storage area in memory, then read it */
+      if ( ALLOC( names->storage, storageSize )               ||
+           FILE_Read_At( table_pos + names->storageOffset,
+                         names->storage, storageSize ) )
+        goto Exit;
+
+      /* Go through and assign the string pointers to the name records. */
+      {
+        TT_NameRec*  cur   = names->names;
+        TT_NameRec*  limit = cur + names->numNameRecords;
+
+
+        for ( ; cur < limit; cur++ )
+          cur->string = names->storage + cur->stringOffset;
+      }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+      /* Print Name Record Table in case of debugging */
+      {
+        TT_NameRec*  cur   = names->names;
+        TT_NameRec*  limit = cur + names->numNameRecords;
+
+
+        for ( ; cur < limit; cur++ )
+        {
+          FT_UInt  j;
+
+
+          FT_TRACE3(( "%d %d %x %d\n  ",
+                       cur->platformID,
+                       cur->encodingID,
+                       cur->languageID,
+                       cur->nameID ));
+
+          /* I know that M$ encoded strings are Unicode,            */
+          /* but this works reasonable well for debugging purposes. */
+          if ( cur->string )
+            for ( j = 0; j < (FT_UInt)cur->stringLength; j++ )
+            {
+              FT_Char  c = *( cur->string + j );
+
+
+              if ( (FT_Byte)c < 128 )
+                FT_TRACE3(( "%c", c ));
+            }
+        }
+      }
+      FT_TRACE3(( "\n" ));
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+    }
+    FT_TRACE2(( "loaded\n" ));
+
+    /* everything went well, update face->num_names */
+    face->num_names = names->numNameRecords;
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Free_Names                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Frees the name records.                                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the target face object.                        */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  TT_Free_Names( TT_Face  face )
+  {
+    FT_Memory      memory = face->root.driver->root.memory;
+    TT_NameTable*  names  = &face->name_table;
+
+
+    /* free strings table */
+    FREE( names->names );
+
+    /* free strings storage */
+    FREE( names->storage );
+
+    names->numNameRecords = 0;
+    names->format         = 0;
+    names->storageOffset  = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_CMap                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the cmap directory in a face object.  The cmaps itselves are */
+  /*    loaded on demand in the `ttcmap.c' module.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_CMap( TT_Face    face,
+                FT_Stream  stream )
+  {
+    FT_Error    error;
+    FT_Memory   memory = stream->memory;
+    FT_Long     table_start;
+    TT_CMapDir  cmap_dir;
+
+    const FT_Frame_Field  cmap_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_CMapDir
+
+      FT_FRAME_START( 4 ),
+        FT_FRAME_USHORT( tableVersionNumber ),
+        FT_FRAME_USHORT( numCMaps ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  cmap_rec_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_CMapTable
+
+      FT_FRAME_START( 4 ),
+        FT_FRAME_USHORT( format ),
+        FT_FRAME_USHORT( length ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "CMaps " ));
+
+    error = face->goto_table( face, TTAG_cmap, stream, 0 );
+    if ( error )
+    {
+      error = SFNT_Err_CMap_Table_Missing;
+      goto Exit;
+    }
+
+    table_start = FILE_Pos();
+
+    if ( READ_Fields( cmap_fields, &cmap_dir ) )
+      goto Exit;
+
+    /* reserve space in face table for cmap tables */
+    if ( ALLOC_ARRAY( face->charmaps,
+                      cmap_dir.numCMaps,
+                      TT_CharMapRec ) )
+      goto Exit;
+
+    face->num_charmaps = cmap_dir.numCMaps;
+    {
+      TT_CharMap  charmap = face->charmaps;
+      TT_CharMap  limit   = charmap + face->num_charmaps;
+
+
+      /* read the header of each charmap first */
+      if ( ACCESS_Frame( face->num_charmaps * 8L ) )
+        goto Exit;
+
+      for ( ; charmap < limit; charmap++ )
+      {
+        TT_CMapTable*  cmap;
+
+
+        charmap->root.face = (FT_Face)face;
+        cmap               = &charmap->cmap;
+
+        cmap->loaded             = FALSE;
+        cmap->platformID         = GET_UShort();
+        cmap->platformEncodingID = GET_UShort();
+        cmap->offset             = (FT_ULong)GET_Long();
+      }
+
+      FORGET_Frame();
+
+      /* now read the rest of each table */
+      for ( charmap = face->charmaps; charmap < limit; charmap++ )
+      {
+        TT_CMapTable* cmap = &charmap->cmap;
+
+
+        if ( FILE_Seek( table_start + (FT_Long)cmap->offset ) ||
+             READ_Fields( cmap_rec_fields, cmap )             )
+          goto Exit;
+
+        cmap->offset = FILE_Pos();
+      }
+    }
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_OS2                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the OS2 table.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_OS2( TT_Face    face,
+               FT_Stream  stream )
+  {
+    FT_Error  error;
+    TT_OS2*   os2;
+
+    const FT_Frame_Field  os2_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_OS2
+
+      FT_FRAME_START( 78 ),
+        FT_FRAME_USHORT( version ),
+        FT_FRAME_SHORT ( xAvgCharWidth ),
+        FT_FRAME_USHORT( usWeightClass ),
+        FT_FRAME_USHORT( usWidthClass ),
+        FT_FRAME_SHORT ( fsType ),
+        FT_FRAME_SHORT ( ySubscriptXSize ),
+        FT_FRAME_SHORT ( ySubscriptYSize ),
+        FT_FRAME_SHORT ( ySubscriptXOffset ),
+        FT_FRAME_SHORT ( ySubscriptYOffset ),
+        FT_FRAME_SHORT ( ySuperscriptXSize ),
+        FT_FRAME_SHORT ( ySuperscriptYSize ),
+        FT_FRAME_SHORT ( ySuperscriptXOffset ),
+        FT_FRAME_SHORT ( ySuperscriptYOffset ),
+        FT_FRAME_SHORT ( yStrikeoutSize ),
+        FT_FRAME_SHORT ( yStrikeoutPosition ),
+        FT_FRAME_SHORT ( sFamilyClass ),
+        FT_FRAME_BYTE  ( panose[0] ),
+        FT_FRAME_BYTE  ( panose[1] ),
+        FT_FRAME_BYTE  ( panose[2] ),
+        FT_FRAME_BYTE  ( panose[3] ),
+        FT_FRAME_BYTE  ( panose[4] ),
+        FT_FRAME_BYTE  ( panose[5] ),
+        FT_FRAME_BYTE  ( panose[6] ),
+        FT_FRAME_BYTE  ( panose[7] ),
+        FT_FRAME_BYTE  ( panose[8] ),
+        FT_FRAME_BYTE  ( panose[9] ),
+        FT_FRAME_ULONG ( ulUnicodeRange1 ),
+        FT_FRAME_ULONG ( ulUnicodeRange2 ),
+        FT_FRAME_ULONG ( ulUnicodeRange3 ),
+        FT_FRAME_ULONG ( ulUnicodeRange4 ),
+        FT_FRAME_BYTE  ( achVendID[0] ),
+        FT_FRAME_BYTE  ( achVendID[1] ),
+        FT_FRAME_BYTE  ( achVendID[2] ),
+        FT_FRAME_BYTE  ( achVendID[3] ),
+
+        FT_FRAME_USHORT( fsSelection ),
+        FT_FRAME_USHORT( usFirstCharIndex ),
+        FT_FRAME_USHORT( usLastCharIndex ),
+        FT_FRAME_SHORT ( sTypoAscender ),
+        FT_FRAME_SHORT ( sTypoDescender ),
+        FT_FRAME_SHORT ( sTypoLineGap ),
+        FT_FRAME_USHORT( usWinAscent ),
+        FT_FRAME_USHORT( usWinDescent ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  os2_fields_extra[] =
+    {
+      FT_FRAME_START( 8 ),
+        FT_FRAME_ULONG( ulCodePageRange1 ),
+        FT_FRAME_ULONG( ulCodePageRange2 ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  os2_fields_extra2[] =
+    {
+      FT_FRAME_START( 10 ),
+        FT_FRAME_SHORT ( sxHeight ),
+        FT_FRAME_SHORT ( sCapHeight ),
+        FT_FRAME_USHORT( usDefaultChar ),
+        FT_FRAME_USHORT( usBreakChar ),
+        FT_FRAME_USHORT( usMaxContext ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "OS/2 Table " ));
+
+    /* We now support old Mac fonts where the OS/2 table doesn't  */
+    /* exist.  Simply put, we set the `version' field to 0xFFFF   */
+    /* and test this value each time we need to access the table. */
+    error = face->goto_table( face, TTAG_OS2, stream, 0 );
+    if ( error )
+    {
+      FT_TRACE2(( "is missing!\n" ));
+      face->os2.version = 0xFFFF;
+      error = SFNT_Err_Ok;
+      goto Exit;
+    }
+
+    os2 = &face->os2;
+
+    if ( READ_Fields( os2_fields, os2 ) )
+      goto Exit;
+
+    os2->ulCodePageRange1 = 0;
+    os2->ulCodePageRange2 = 0;
+    os2->sxHeight         = 0;
+    os2->sCapHeight       = 0;
+    os2->usDefaultChar    = 0;
+    os2->usBreakChar      = 0;
+    os2->usMaxContext     = 0;
+
+    if ( os2->version >= 0x0001 )
+    {
+      /* only version 1 tables */
+      if ( READ_Fields( os2_fields_extra, os2 ) )
+        goto Exit;
+
+      if ( os2->version >= 0x0002 )
+      {
+        /* only version 2 tables */
+        if ( READ_Fields( os2_fields_extra2, os2 ) )
+          goto Exit;
+      }
+    }
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Postscript                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the Postscript table.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_PostScript( TT_Face    face,
+                      FT_Stream  stream )
+  {
+    FT_Error        error;
+    TT_Postscript*  post = &face->postscript;
+
+    static const FT_Frame_Field  post_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_Postscript
+
+      FT_FRAME_START( 32 ),
+        FT_FRAME_ULONG( FormatType ),
+        FT_FRAME_ULONG( italicAngle ),
+        FT_FRAME_SHORT( underlinePosition ),
+        FT_FRAME_SHORT( underlineThickness ),
+        FT_FRAME_ULONG( isFixedPitch ),
+        FT_FRAME_ULONG( minMemType42 ),
+        FT_FRAME_ULONG( maxMemType42 ),
+        FT_FRAME_ULONG( minMemType1 ),
+        FT_FRAME_ULONG( maxMemType1 ),
+      FT_FRAME_END
+    };
+
+
+    FT_TRACE2(( "PostScript " ));
+
+    error = face->goto_table( face, TTAG_post, stream, 0 );
+    if ( error )
+      return SFNT_Err_Post_Table_Missing;
+
+    if ( READ_Fields( post_fields, post ) )
+      return error;
+
+    /* we don't load the glyph names, we do that in another */
+    /* module (ttpost).                                     */
+    FT_TRACE2(( "loaded\n" ));
+
+    return SFNT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_PCLT                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the PCL 5 Table.                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_PCLT( TT_Face    face,
+                FT_Stream  stream )
+  {
+    static const FT_Frame_Field  pclt_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_PCLT
+
+      FT_FRAME_START( 54 ),
+        FT_FRAME_ULONG ( Version ),
+        FT_FRAME_ULONG ( FontNumber ),
+        FT_FRAME_USHORT( Pitch ),
+        FT_FRAME_USHORT( xHeight ),
+        FT_FRAME_USHORT( Style ),
+        FT_FRAME_USHORT( TypeFamily ),
+        FT_FRAME_USHORT( CapHeight ),
+        FT_FRAME_BYTES ( TypeFace, 16 ),
+        FT_FRAME_BYTES ( CharacterComplement, 8 ),
+        FT_FRAME_BYTES ( FileName, 6 ),
+        FT_FRAME_CHAR  ( StrokeWeight ),
+        FT_FRAME_CHAR  ( WidthType ),
+        FT_FRAME_BYTE  ( SerifStyle ),
+        FT_FRAME_BYTE  ( Reserved ),
+      FT_FRAME_END
+    };
+
+    FT_Error  error;
+    TT_PCLT*  pclt = &face->pclt;
+
+
+    FT_TRACE2(( "PCLT " ));
+
+    /* optional table */
+    error = face->goto_table( face, TTAG_PCLT, stream, 0 );
+    if ( error )
+    {
+      FT_TRACE2(( "missing (optional)\n" ));
+      pclt->Version = 0;
+      return SFNT_Err_Ok;
+    }
+
+    if ( READ_Fields( pclt_fields, pclt ) )
+      goto Exit;
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Gasp                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the `gasp' table into a face object.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Gasp( TT_Face    face,
+                FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+    FT_UInt        j,num_ranges;
+    TT_GaspRange*  gaspranges;
+
+
+    FT_TRACE2(( "TT_Load_Gasp: %08p\n", face ));
+
+    /* the gasp table is optional */
+    error = face->goto_table( face, TTAG_gasp, stream, 0 );
+    if ( error )
+      return SFNT_Err_Ok;
+
+    if ( ACCESS_Frame( 4L ) )
+      goto Exit;
+
+    face->gasp.version   = GET_UShort();
+    face->gasp.numRanges = GET_UShort();
+
+    FORGET_Frame();
+
+    num_ranges = face->gasp.numRanges;
+    FT_TRACE3(( "number of ranges = %d\n", num_ranges ));
+
+    if ( ALLOC_ARRAY( gaspranges, num_ranges, TT_GaspRange ) ||
+         ACCESS_Frame( num_ranges * 4L )                     )
+      goto Exit;
+
+    face->gasp.gaspRanges = gaspranges;
+
+    for ( j = 0; j < num_ranges; j++ )
+    {
+      gaspranges[j].maxPPEM  = GET_UShort();
+      gaspranges[j].gaspFlag = GET_UShort();
+
+      FT_TRACE3(( " [max:%d flag:%d]",
+                    gaspranges[j].maxPPEM,
+                    gaspranges[j].gaspFlag ));
+    }
+    FT_TRACE3(( "\n" ));
+
+    FORGET_Frame();
+    FT_TRACE2(( "GASP loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( int )
+  tt_kern_pair_compare( const void*  a,
+                        const void*  b );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Kern                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the first kerning table with format 0 in the font.  Only     */
+  /*    accepts the first horizontal kerning table.  Developers should use */
+  /*    the `ftxkern' extension to access other kerning tables in the font */
+  /*    file, if they really want to.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Kern( TT_Face    face,
+                FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+    FT_UInt    n, num_tables;
+
+
+    /* the kern table is optional; exit silently if it is missing */
+    error = face->goto_table( face, TTAG_kern, stream, 0 );
+    if ( error )
+      return SFNT_Err_Ok;
+
+    if ( ACCESS_Frame( 4L ) )
+      goto Exit;
+
+    (void)GET_UShort();         /* version */
+    num_tables = GET_UShort();
+
+    FORGET_Frame();
+
+    for ( n = 0; n < num_tables; n++ )
+    {
+      FT_UInt  coverage;
+      FT_UInt  length;
+
+
+      if ( ACCESS_Frame( 6L ) )
+        goto Exit;
+
+      (void)GET_UShort();           /* version                 */
+      length   = GET_UShort() - 6;  /* substract header length */
+      coverage = GET_UShort();
+
+      FORGET_Frame();
+
+      if ( coverage == 0x0001 )
+      {
+        FT_UInt          num_pairs;
+        TT_Kern_0_Pair*  pair;
+        TT_Kern_0_Pair*  limit;
+
+
+        /* found a horizontal format 0 kerning table! */
+        if ( ACCESS_Frame( 8L ) )
+          goto Exit;
+
+        num_pairs = GET_UShort();
+
+        /* skip the rest */
+
+        FORGET_Frame();
+
+        /* allocate array of kerning pairs */
+        if ( ALLOC_ARRAY( face->kern_pairs, num_pairs, TT_Kern_0_Pair ) ||
+             ACCESS_Frame( 6L * num_pairs )                             )
+          goto Exit;
+
+        pair  = face->kern_pairs;
+        limit = pair + num_pairs;
+        for ( ; pair < limit; pair++ )
+        {
+          pair->left  = GET_UShort();
+          pair->right = GET_UShort();
+          pair->value = GET_UShort();
+        }
+
+        FORGET_Frame();
+
+        face->num_kern_pairs   = num_pairs;
+        face->kern_table_index = n;
+
+        /* ensure that the kerning pair table is sorted (yes, some */
+        /* fonts have unsorted tables!)                            */
+        {
+          FT_UInt          i;
+          TT_Kern_0_Pair*  pair0;
+
+
+          pair0 = face->kern_pairs;
+
+          for ( i = 1; i < num_pairs; i++, pair0++ )
+          {
+            if ( tt_kern_pair_compare( pair0, pair0 + 1 ) != -1 )
+            {
+              qsort( (void*)face->kern_pairs, (int)num_pairs,
+                     sizeof ( TT_Kern_0_Pair ), tt_kern_pair_compare );
+              break;
+            }
+          }
+        }
+
+        goto Exit;
+      }
+
+      if ( FILE_Skip( length ) )
+        goto Exit;
+    }
+
+    /* no kern table found -- doesn't matter */
+    face->kern_table_index = -1;
+    face->num_kern_pairs   = 0;
+    face->kern_pairs       = NULL;
+
+  Exit:
+    return error;
+  }
+
+
+#undef  TT_KERN_INDEX
+#define TT_KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
+
+  FT_CALLBACK_DEF( int )
+  tt_kern_pair_compare( const void*  a,
+                        const void*  b )
+  {
+    TT_Kern_0_Pair*  pair1 = (TT_Kern_0_Pair*)a;
+    TT_Kern_0_Pair*  pair2 = (TT_Kern_0_Pair*)b;
+
+    FT_ULong  index1 = TT_KERN_INDEX( pair1->left, pair1->right );
+    FT_ULong  index2 = TT_KERN_INDEX( pair2->left, pair2->right );
+
+
+    return ( index1 < index2 ? -1 :
+           ( index1 > index2 ?  1 : 0 ));
+  }
+
+#undef TT_KERN_INDEX
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Hdmx                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the horizontal device metrics table.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Hdmx( TT_Face    face,
+                FT_Stream  stream )
+  {
+    FT_Error  error;
+    FT_Memory memory = stream->memory;
+
+    TT_Hdmx*  hdmx = &face->hdmx;
+    FT_Long   num_glyphs;
+    FT_Long   record_size;
+
+
+    hdmx->version     = 0;
+    hdmx->num_records = 0;
+    hdmx->records     = 0;
+
+    /* this table is optional */
+    error = face->goto_table( face, TTAG_hdmx, stream, 0 );
+    if ( error )
+      return SFNT_Err_Ok;
+
+    if ( ACCESS_Frame( 8L ) )
+      goto Exit;
+
+    hdmx->version     = GET_UShort();
+    hdmx->num_records = GET_Short();
+    record_size       = GET_Long();
+
+    FORGET_Frame();
+
+    /* Only recognize format 0 */
+    if ( hdmx->version != 0 )
+      goto Exit;
+
+    if ( ALLOC_ARRAY( hdmx->records, hdmx->num_records, TT_HdmxRec ) )
+      goto Exit;
+
+    num_glyphs   = face->root.num_glyphs;
+    record_size -= num_glyphs + 2;
+
+    {
+      TT_HdmxRec*  cur   = hdmx->records;
+      TT_HdmxRec*  limit = cur + hdmx->num_records;
+
+
+      for ( ; cur < limit; cur++ )
+      {
+        /* read record */
+        if ( READ_Byte( cur->ppem      ) ||
+             READ_Byte( cur->max_width ) )
+          goto Exit;
+
+        if ( ALLOC( cur->widths, num_glyphs )     ||
+             FILE_Read( cur->widths, num_glyphs ) )
+          goto Exit;
+
+        /* skip padding bytes */
+        if ( record_size > 0 && FILE_Skip( record_size ) )
+            goto Exit;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Free_Hdmx                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Frees the horizontal device metrics table.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A handle to the target face object.                        */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  TT_Free_Hdmx( TT_Face  face )
+  {
+    if ( face )
+    {
+      FT_Int     n;
+      FT_Memory  memory = face->root.driver->root.memory;
+
+
+      for ( n = 0; n < face->hdmx.num_records; n++ )
+        FREE( face->hdmx.records[n].widths );
+
+      FREE( face->hdmx.records );
+      face->hdmx.num_records = 0;
+    }
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ttobjs.c b/libraries/freetype-2.0.5/ttobjs.c
new file mode 100644 (file)
index 0000000..7fee693
--- /dev/null
@@ -0,0 +1,868 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttobjs.c                                                               */
+/*                                                                         */
+/*    Objects manager (body).                                              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_POSTSCRIPT_NAMES_H
+
+#include "ttgload.h"
+#include "ttpload.h"
+
+#include "tterrors.h"
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#include "ttinterp.h"
+#endif
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttobjs
+
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                       GLYPH ZONE FUNCTIONS                            */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_GlyphZone                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Deallocates a glyph zone.                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    zone :: A pointer to the target glyph zone.                        */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  TT_Done_GlyphZone( TT_GlyphZone*  zone )
+  {
+    FT_Memory  memory = zone->memory;
+
+
+    FREE( zone->contours );
+    FREE( zone->tags );
+    FREE( zone->cur );
+    FREE( zone->org );
+
+    zone->max_points   = zone->n_points   = 0;
+    zone->max_contours = zone->n_contours = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_New_GlyphZone                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Allocates a new glyph zone.                                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    memory      :: A handle to the current memory object.              */
+  /*                                                                       */
+  /*    maxPoints   :: The capacity of glyph zone in points.               */
+  /*                                                                       */
+  /*    maxContours :: The capacity of glyph zone in contours.             */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    zone        :: A pointer to the target glyph zone record.          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_New_GlyphZone( FT_Memory      memory,
+                    FT_UShort      maxPoints,
+                    FT_Short       maxContours,
+                    TT_GlyphZone*  zone )
+  {
+    FT_Error  error;
+
+
+    if ( maxPoints > 0 )
+      maxPoints += 2;
+
+    MEM_Set( zone, 0, sizeof ( *zone ) );
+    zone->memory = memory;
+
+    if ( ALLOC_ARRAY( zone->org,      maxPoints * 2, FT_F26Dot6 ) ||
+         ALLOC_ARRAY( zone->cur,      maxPoints * 2, FT_F26Dot6 ) ||
+         ALLOC_ARRAY( zone->tags,     maxPoints,     FT_Byte    ) ||
+         ALLOC_ARRAY( zone->contours, maxContours,   FT_UShort  ) )
+    {
+      TT_Done_GlyphZone( zone );
+    }
+
+    return error;
+  }
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Init_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given TrueType face object.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream     :: The source font stream.                              */
+  /*                                                                       */
+  /*    face_index :: The index of the font face in the resource.          */
+  /*                                                                       */
+  /*    num_params :: Number of additional generic parameters.  Ignored.   */
+  /*                                                                       */
+  /*    params     :: Additional generic parameters.  Ignored.             */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face       :: The newly built face object.                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Init_Face( FT_Stream      stream,
+                TT_Face        face,
+                FT_Int         face_index,
+                FT_Int         num_params,
+                FT_Parameter*  params )
+  {
+    FT_Error         error;
+    FT_Library       library;
+    SFNT_Interface*  sfnt;
+
+
+    library = face->root.driver->root.library;
+    sfnt    = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" );
+    if ( !sfnt )
+      goto Bad_Format;
+
+    /* create input stream from resource */
+    if ( FILE_Seek( 0 ) )
+      goto Exit;
+
+    /* check that we have a valid TrueType file */
+    error = sfnt->init_face( stream, face, face_index, num_params, params );
+    if ( error )
+      goto Exit;
+
+    /* We must also be able to accept Mac/GX fonts, as well as OT ones */
+    if ( face->format_tag != 0x00010000L &&    /* MS fonts  */
+         face->format_tag != TTAG_true   )     /* Mac fonts */
+    {
+      FT_TRACE2(( "[not a valid TTF font]\n" ));
+      goto Bad_Format;
+    }
+
+    /* If we are performing a simple font format check, exit immediately */
+    if ( face_index < 0 )
+      return TT_Err_Ok;
+
+    /* Load font directory */
+    error = sfnt->load_face( stream, face, face_index, num_params, params );
+    if ( error )
+      goto Exit;
+
+    if ( face->root.face_flags & FT_FACE_FLAG_SCALABLE )
+      error = TT_Load_Locations( face, stream ) ||
+              TT_Load_CVT      ( face, stream ) ||
+              TT_Load_Programs ( face, stream );
+
+    /* initialize standard glyph loading routines */
+    TT_Init_Glyph_Loading( face );
+
+  Exit:
+    return error;
+
+  Bad_Format:
+    error = TT_Err_Unknown_File_Format;
+    goto Exit;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_Face                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given face object.                                     */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: A pointer to the face object to destroy.                   */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  TT_Done_Face( TT_Face  face )
+  {
+    FT_Memory  memory = face->root.memory;
+    FT_Stream  stream = face->root.stream;
+
+    SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
+
+
+    /* for `extended TrueType formats' (i.e. compressed versions) */
+    if ( face->extra.finalizer )
+      face->extra.finalizer( face->extra.data );
+
+    if ( sfnt )
+      sfnt->done_face( face );
+
+    /* freeing the locations table */
+    FREE( face->glyph_locations );
+    face->num_locations = 0;
+
+    /* freeing the CVT */
+    FREE( face->cvt );
+    face->cvt_size = 0;
+
+    /* freeing the programs */
+    RELEASE_Frame( face->font_program );
+    RELEASE_Frame( face->cvt_program );
+    face->font_program_size = 0;
+    face->cvt_program_size  = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*                           SIZE  FUNCTIONS                             */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Init_Size                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a new TrueType size object.                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    size :: A handle to the size object.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Init_Size( TT_Size  size )
+  {
+    FT_Error  error = TT_Err_Ok;
+
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    TT_Face    face   = (TT_Face)size->root.face;
+    FT_Memory  memory = face->root.memory;
+    FT_Int     i;
+
+    TT_ExecContext  exec;
+    FT_UShort       n_twilight;
+    TT_MaxProfile*  maxp = &face->max_profile;
+
+
+    size->ttmetrics.valid = FALSE;
+
+    size->max_function_defs    = maxp->maxFunctionDefs;
+    size->max_instruction_defs = maxp->maxInstructionDefs;
+
+    size->num_function_defs    = 0;
+    size->num_instruction_defs = 0;
+
+    size->max_func = 0;
+    size->max_ins  = 0;
+
+    size->cvt_size     = face->cvt_size;
+    size->storage_size = maxp->maxStorage;
+
+    /* Set default metrics */
+    {
+      FT_Size_Metrics*  metrics  = &size->root.metrics;
+      TT_Size_Metrics*  metrics2 = &size->ttmetrics;
+
+
+      metrics->x_ppem = 0;
+      metrics->y_ppem = 0;
+
+      metrics2->rotated   = FALSE;
+      metrics2->stretched = FALSE;
+
+      /* set default compensation (all 0) */
+      for ( i = 0; i < 4; i++ )
+        metrics2->compensations[i] = 0;
+    }
+
+    /* allocate function defs, instruction defs, cvt, and storage area */
+    if ( ALLOC_ARRAY( size->function_defs,
+                      size->max_function_defs,
+                      TT_DefRecord )                ||
+
+         ALLOC_ARRAY( size->instruction_defs,
+                      size->max_instruction_defs,
+                      TT_DefRecord )                ||
+
+         ALLOC_ARRAY( size->cvt,
+                      size->cvt_size, FT_Long )     ||
+
+         ALLOC_ARRAY( size->storage,
+                      size->storage_size, FT_Long ) )
+
+      goto Fail_Memory;
+
+    /* reserve twilight zone */
+    n_twilight = maxp->maxTwilightPoints;
+    error = TT_New_GlyphZone( memory, n_twilight, 0, &size->twilight );
+    if ( error )
+      goto Fail_Memory;
+
+    size->twilight.n_points = n_twilight;
+
+    /* set `face->interpreter' according to the debug hook present */
+    {
+      FT_Library  library = face->root.driver->root.library;
+
+
+      face->interpreter = (TT_Interpreter)
+                            library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
+      if ( !face->interpreter )
+        face->interpreter = (TT_Interpreter)TT_RunIns;
+    }
+
+    /* Fine, now execute the font program! */
+    exec = size->context;
+    /* size objects used during debugging have their own context */
+    if ( !size->debug )
+      exec = TT_New_Context( face );
+
+    if ( !exec )
+    {
+      error = TT_Err_Could_Not_Find_Context;
+      goto Fail_Memory;
+    }
+
+    size->GS = tt_default_graphics_state;
+    TT_Load_Context( exec, face, size );
+
+    exec->callTop   = 0;
+    exec->top       = 0;
+
+    exec->period    = 64;
+    exec->phase     = 0;
+    exec->threshold = 0;
+
+    {
+      FT_Size_Metrics*  metrics    = &exec->metrics;
+      TT_Size_Metrics*  tt_metrics = &exec->tt_metrics;
+
+
+      metrics->x_ppem   = 0;
+      metrics->y_ppem   = 0;
+      metrics->x_scale  = 0;
+      metrics->y_scale  = 0;
+
+      tt_metrics->ppem  = 0;
+      tt_metrics->scale = 0;
+      tt_metrics->ratio = 0x10000L;
+    }
+
+    exec->instruction_trap = FALSE;
+
+    exec->cvtSize = size->cvt_size;
+    exec->cvt     = size->cvt;
+
+    exec->F_dot_P = 0x10000L;
+
+    /* allow font program execution */
+    TT_Set_CodeRange( exec,
+                      tt_coderange_font,
+                      face->font_program,
+                      face->font_program_size );
+
+    /* disable CVT and glyph programs coderange */
+    TT_Clear_CodeRange( exec, tt_coderange_cvt );
+    TT_Clear_CodeRange( exec, tt_coderange_glyph );
+
+    if ( face->font_program_size > 0 )
+    {
+      error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
+      if ( !error )
+        error = face->interpreter( exec );
+
+      if ( error )
+        goto Fail_Exec;
+    }
+    else
+      error = TT_Err_Ok;
+
+    TT_Save_Context( exec, size );
+
+    if ( !size->debug )
+      TT_Done_Context( exec );
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    size->ttmetrics.valid = FALSE;
+    return error;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+  Fail_Exec:
+    if ( !size->debug )
+      TT_Done_Context( exec );
+
+  Fail_Memory:
+
+    TT_Done_Size( size );
+    return error;
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_Size                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    The TrueType size object finalizer.                                */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  TT_Done_Size( TT_Size  size )
+  {
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    FT_Memory  memory = size->root.face->memory;
+
+
+    if ( size->debug )
+    {
+      /* the debug context must be deleted by the debugger itself */
+      size->context = NULL;
+      size->debug   = FALSE;
+    }
+
+    FREE( size->cvt );
+    size->cvt_size = 0;
+
+    /* free storage area */
+    FREE( size->storage );
+    size->storage_size = 0;
+
+    /* twilight zone */
+    TT_Done_GlyphZone( &size->twilight );
+
+    FREE( size->function_defs );
+    FREE( size->instruction_defs );
+
+    size->num_function_defs    = 0;
+    size->max_function_defs    = 0;
+    size->num_instruction_defs = 0;
+    size->max_instruction_defs = 0;
+
+    size->max_func = 0;
+    size->max_ins  = 0;
+
+#endif
+
+    size->ttmetrics.valid = FALSE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Reset_Outline_Size                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Resets a TrueType outline size when resolutions and character      */
+  /*    dimensions have been changed.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  static FT_Error
+  Reset_Outline_Size( TT_Size  size )
+  {
+    TT_Face   face;
+    FT_Error  error = TT_Err_Ok;
+
+    FT_Size_Metrics*  metrics;
+
+
+    if ( size->ttmetrics.valid )
+      return TT_Err_Ok;
+
+    face = (TT_Face)size->root.face;
+
+    metrics = &size->root.metrics;
+
+    if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
+      return TT_Err_Invalid_PPem;
+
+    /* compute new transformation */
+    if ( metrics->x_ppem >= metrics->y_ppem )
+    {
+      size->ttmetrics.scale   = metrics->x_scale;
+      size->ttmetrics.ppem    = metrics->x_ppem;
+      size->ttmetrics.x_ratio = 0x10000L;
+      size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem,
+                                           0x10000L,
+                                           metrics->x_ppem );
+    }
+    else
+    {
+      size->ttmetrics.scale   = metrics->y_scale;
+      size->ttmetrics.ppem    = metrics->y_ppem;
+      size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem,
+                                           0x10000L,
+                                           metrics->y_ppem );
+      size->ttmetrics.y_ratio = 0x10000L;
+    }
+
+    /* Compute root ascender, descender, test height, and max_advance */
+    metrics->ascender    = ( FT_MulFix( face->root.ascender,
+                                        metrics->y_scale ) + 32 ) & -64;
+    metrics->descender   = ( FT_MulFix( face->root.descender,
+                                        metrics->y_scale ) + 32 ) & -64;
+    metrics->height      = ( FT_MulFix( face->root.height,
+                                        metrics->y_scale ) + 32 ) & -64;
+    metrics->max_advance = ( FT_MulFix( face->root.max_advance_width,
+                                        metrics->x_scale ) + 32 ) & -64;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+    /* set to `invalid' by default */
+    size->strike_index = 0xFFFF;
+#endif
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    {
+      TT_ExecContext  exec;
+      FT_UInt         i, j;
+
+
+      /* Scale the cvt values to the new ppem.          */
+      /* We use by default the y ppem to scale the CVT. */
+      for ( i = 0; i < size->cvt_size; i++ )
+        size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
+
+      /* All twilight points are originally zero */
+      for ( j = 0; j < (FT_UInt)size->twilight.n_points; j++ )
+      {
+        size->twilight.org[j].x = 0;
+        size->twilight.org[j].y = 0;
+        size->twilight.cur[j].x = 0;
+        size->twilight.cur[j].y = 0;
+      }
+
+      /* clear storage area */
+      for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
+        size->storage[i] = 0;
+
+      size->GS = tt_default_graphics_state;
+
+      /* get execution context and run prep program */
+      if ( size->debug )
+        exec = size->context;
+      else
+        exec = TT_New_Context( face );
+      /* debugging instances have their own context */
+
+      if ( !exec )
+        return TT_Err_Could_Not_Find_Context;
+
+      TT_Load_Context( exec, face, size );
+
+      TT_Set_CodeRange( exec,
+                        tt_coderange_cvt,
+                        face->cvt_program,
+                        face->cvt_program_size );
+
+      TT_Clear_CodeRange( exec, tt_coderange_glyph );
+
+      exec->instruction_trap = FALSE;
+
+      exec->top     = 0;
+      exec->callTop = 0;
+
+      if ( face->cvt_program_size > 0 )
+      {
+        error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
+        if ( error )
+          goto End;
+
+        if ( !size->debug )
+          error = face->interpreter( exec );
+      }
+      else
+        error = TT_Err_Ok;
+
+      size->GS = exec->GS;
+      /* save default graphics state */
+
+    End:
+      TT_Save_Context( exec, size );
+
+      if ( !size->debug )
+        TT_Done_Context( exec );
+      /* debugging instances keep their context */
+    }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    if ( !error )
+      size->ttmetrics.valid = TRUE;
+
+    return error;
+  }
+
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Reset_SBit_Size                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Resets a TrueType sbit size when resolutions and character         */
+  /*    dimensions have been changed.                                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  static FT_Error
+  Reset_SBit_Size( TT_Size  size )
+  {
+    TT_Face           face;
+    FT_Error          error = TT_Err_Ok;
+
+    FT_ULong          strike_index;
+    FT_Size_Metrics*  metrics;
+    FT_Size_Metrics*  sbit_metrics;
+    SFNT_Interface*   sfnt;
+
+
+    metrics = &size->root.metrics;
+
+    if ( size->strike_index != 0xFFFF )
+      return TT_Err_Ok;
+
+    face = (TT_Face)size->root.face;
+    sfnt = (SFNT_Interface*)face->sfnt;
+
+    sbit_metrics = &size->strike_metrics;
+
+    error = sfnt->set_sbit_strike(face,
+                                  metrics->x_ppem, metrics->y_ppem,
+                                  &strike_index);
+
+    if ( !error )
+    {
+      TT_SBit_Strike*  strike = face->sbit_strikes + strike_index;
+
+
+      sbit_metrics->x_ppem      = metrics->x_ppem;
+      sbit_metrics->y_ppem      = metrics->y_ppem;
+#if 0
+      /*
+       * sbit_metrics->?_scale
+       * are not used now.
+       */
+      sbit_metrics->x_scale     = 1 << 16;
+      sbit_metrics->y_scale     = 1 << 16;
+#endif
+
+      sbit_metrics->ascender    = strike->hori.ascender << 6;
+      sbit_metrics->descender   = strike->hori.descender << 6;
+
+      /* XXX: Is this correct? */
+      sbit_metrics->height      = sbit_metrics->ascender -
+                                  sbit_metrics->descender;
+
+      /* XXX: Is this correct? */
+      sbit_metrics->max_advance = ( strike->hori.min_origin_SB +
+                                    strike->hori.max_width     +
+                                    strike->hori.min_advance_SB ) << 6;
+
+      size->strike_index = strike_index;
+    }
+    else
+    {
+      size->strike_index = 0xFFFF;
+
+      sbit_metrics->x_ppem      = 0;
+      sbit_metrics->y_ppem      = 0;
+      sbit_metrics->ascender    = 0;
+      sbit_metrics->descender   = 0;
+      sbit_metrics->height      = 0;
+      sbit_metrics->max_advance = 0;
+    }
+
+    return error;
+  }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Reset_Size                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Resets a TrueType size when resolutions and character dimensions   */
+  /*    have been changed.                                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    size :: A handle to the target size object.                        */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Reset_Size( TT_Size  size )
+  {
+    FT_Face   face;
+    FT_Error  error = TT_Err_Ok;
+
+
+    face = size->root.face;
+
+    if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+    {
+      if ( !size->ttmetrics.valid )
+        error = Reset_Outline_Size( size );
+
+      if ( error )
+        return error;
+    }
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    if ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
+    {
+      if ( size->strike_index == 0xFFFF )
+        error = Reset_SBit_Size( size );
+
+      if ( !error && !( face->face_flags & FT_FACE_FLAG_SCALABLE ) )
+        size->root.metrics = size->strike_metrics;
+    }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+      return TT_Err_Ok;
+    else
+      return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Init_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a given TrueType driver object.                        */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target driver object.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Init_Driver( TT_Driver  driver )
+  {
+    FT_Error  error;
+
+
+    /* set `extra' in glyph loader */
+    error = FT_GlyphLoader_Create_Extra( FT_DRIVER( driver )->glyph_loader );
+
+    /* init extension registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+    if ( !error )
+      return TT_Init_Extensions( driver );
+#endif
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Done_Driver                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes a given TrueType driver.                                 */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    driver :: A handle to the target TrueType driver.                  */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  TT_Done_Driver( TT_Driver  driver )
+  {
+    /* destroy extensions registry if needed */
+
+#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
+
+    TT_Done_Extensions( driver );
+
+#endif
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    /* destroy the execution context */
+    if ( driver->context )
+    {
+      TT_Destroy_Context( driver->context, driver->root.root.memory );
+      driver->context = NULL;
+    }
+#else
+    FT_UNUSED( driver );
+#endif
+
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ttpload.c b/libraries/freetype-2.0.5/ttpload.c
new file mode 100644 (file)
index 0000000..478c67b
--- /dev/null
@@ -0,0 +1,270 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttpload.c                                                              */
+/*                                                                         */
+/*    TrueType glyph data/program tables loader (body).                    */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+
+#include "ttpload.h"
+
+#include "tterrors.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttpload
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Locations                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the locations table.                                         */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Locations( TT_Face    face,
+                     FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+    FT_Short   LongOffsets;
+    FT_ULong   table_len;
+
+
+    FT_TRACE2(( "Locations " ));
+    LongOffsets = face->header.Index_To_Loc_Format;
+
+    error = face->goto_table( face, TTAG_loca, stream, &table_len );
+    if ( error )
+    {
+      error = TT_Err_Locations_Missing;
+      goto Exit;
+    }
+
+    if ( LongOffsets != 0 )
+    {
+      face->num_locations = (FT_UShort)( table_len >> 2 );
+
+      FT_TRACE2(( "(32bit offsets): %12d ", face->num_locations ));
+
+      if ( ALLOC_ARRAY( face->glyph_locations,
+                        face->num_locations,
+                        FT_Long ) )
+        goto Exit;
+
+      if ( ACCESS_Frame( face->num_locations * 4L ) )
+        goto Exit;
+
+      {
+        FT_Long*  loc   = face->glyph_locations;
+        FT_Long*  limit = loc + face->num_locations;
+
+
+        for ( ; loc < limit; loc++ )
+          *loc = GET_Long();
+      }
+
+      FORGET_Frame();
+    }
+    else
+    {
+      face->num_locations = (FT_UShort)( table_len >> 1 );
+
+      FT_TRACE2(( "(16bit offsets): %12d ", face->num_locations ));
+
+      if ( ALLOC_ARRAY( face->glyph_locations,
+                        face->num_locations,
+                        FT_Long ) )
+        goto Exit;
+
+      if ( ACCESS_Frame( face->num_locations * 2L ) )
+        goto Exit;
+      {
+        FT_Long*  loc   = face->glyph_locations;
+        FT_Long*  limit = loc + face->num_locations;
+
+
+        for ( ; loc < limit; loc++ )
+          *loc = (FT_Long)( (FT_ULong)GET_UShort() * 2 );
+      }
+      FORGET_Frame();
+    }
+
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_CVT                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the control value table into a face object.                  */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_CVT( TT_Face    face,
+               FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+    FT_ULong   table_len;
+
+
+    FT_TRACE2(( "CVT " ));
+
+    error = face->goto_table( face, TTAG_cvt, stream, &table_len );
+    if ( error )
+    {
+      FT_TRACE2(( "is missing!\n" ));
+
+      face->cvt_size = 0;
+      face->cvt      = NULL;
+      error          = TT_Err_Ok;
+
+      goto Exit;
+    }
+
+    face->cvt_size = table_len / 2;
+
+    if ( ALLOC_ARRAY( face->cvt,
+                      face->cvt_size,
+                      FT_Short ) )
+      goto Exit;
+
+    if ( ACCESS_Frame( face->cvt_size * 2L ) )
+      goto Exit;
+
+    {
+      FT_Short*  cur   = face->cvt;
+      FT_Short*  limit = cur + face->cvt_size;
+
+
+      for ( ; cur <  limit; cur++ )
+        *cur = GET_Short();
+    }
+
+    FORGET_Frame();
+    FT_TRACE2(( "loaded\n" ));
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_Progams                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the font program and the cvt program.                        */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face   :: A handle to the target face object.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream :: A handle to the input stream.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_Programs( TT_Face    face,
+                    FT_Stream  stream )
+  {
+    FT_Error   error;
+    FT_ULong   table_len;
+
+
+    FT_TRACE2(( "Font program " ));
+
+    /* The font program is optional */
+    error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
+    if ( error )
+    {
+      face->font_program      = NULL;
+      face->font_program_size = 0;
+
+      FT_TRACE2(( "is missing!\n" ));
+    }
+    else
+    {
+      face->font_program_size = table_len;
+      if ( EXTRACT_Frame( table_len, face->font_program ) )
+        goto Exit;
+
+      FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
+    }
+
+    FT_TRACE2(( "Prep program " ));
+
+    error = face->goto_table( face, TTAG_prep, stream, &table_len );
+    if ( error )
+    {
+      face->cvt_program      = NULL;
+      face->cvt_program_size = 0;
+      error                  = TT_Err_Ok;
+
+      FT_TRACE2(( "is missing!\n" ));
+    }
+    else
+    {
+      face->cvt_program_size = table_len;
+      if ( EXTRACT_Frame( table_len, face->cvt_program ) )
+        goto Exit;
+
+      FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
+    }
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ttpost.c b/libraries/freetype-2.0.5/ttpost.c
new file mode 100644 (file)
index 0000000..c228706
--- /dev/null
@@ -0,0 +1,534 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttpost.c                                                               */
+/*                                                                         */
+/*    Postcript name table processing for TrueType and OpenType fonts      */
+/*    (body).                                                              */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The post table is not completely loaded by the core engine.  This     */
+  /* file loads the missing PS glyph names and implements an API to access */
+  /* them.                                                                 */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include "ttpost.h"
+#include "ttload.h"
+
+#include "sferrors.h"
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttpost
+
+
+  /* If this configuration macro is defined, we rely on the `PSNames' */
+  /* module to grab the glyph names.                                  */
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+#include <freetype/internal/psnames.h>
+
+#define MAC_NAME( x )  ( (FT_String*)psnames->macintosh_name( x ) )
+
+
+#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+   /* Otherwise, we ignore the `PSNames' module, and provide our own  */
+   /* table of Mac names.  Thus, it is possible to build a version of */
+   /* FreeType without the Type 1 driver & PSNames module.            */
+
+#define MAC_NAME( x )  TT_Post_Default_Names[x]
+
+  /* the 258 default Mac PS glyph names */
+
+  FT_String*  TT_Post_Default_Names[258] =
+  {
+    /*   0 */
+    ".notdef", ".null", "CR", "space", "exclam",
+    "quotedbl", "numbersign", "dollar", "percent", "ampersand",
+    /*  10 */
+    "quotesingle", "parenleft", "parenright", "asterisk", "plus",
+    "comma", "hyphen", "period", "slash", "zero",
+    /*  20 */
+    "one", "two", "three", "four", "five",
+    "six", "seven", "eight", "nine", "colon",
+    /*  30 */
+    "semicolon", "less", "equal", "greater", "question",
+    "at", "A", "B", "C", "D",
+    /*  40 */
+    "E", "F", "G", "H", "I",
+    "J", "K", "L", "M", "N",
+    /*  50 */
+    "O", "P", "Q", "R", "S",
+    "T", "U", "V", "W", "X",
+    /*  60 */
+    "Y", "Z", "bracketleft", "backslash", "bracketright",
+    "asciicircum", "underscore", "grave", "a", "b",
+    /*  70 */
+    "c", "d", "e", "f", "g",
+    "h", "i", "j", "k", "l",
+    /*  80 */
+    "m", "n", "o", "p", "q",
+    "r", "s", "t", "u", "v",
+    /*  90 */
+    "w", "x", "y", "z", "braceleft",
+    "bar", "braceright", "asciitilde", "Adieresis", "Aring",
+    /* 100 */
+    "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
+    "aacute", "agrave", "acircumflex", "adieresis", "atilde",
+    /* 110 */
+    "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
+    "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
+    /* 120 */
+    "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
+    "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
+    /* 130 */
+    "dagger", "degree", "cent", "sterling", "section",
+    "bullet", "paragraph", "germandbls", "registered", "copyright",
+    /* 140 */
+    "trademark", "acute", "dieresis", "notequal", "AE",
+    "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
+    /* 150 */
+    "yen", "mu", "partialdiff", "summation", "product",
+    "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
+    /* 160 */
+    "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
+    "radical", "florin", "approxequal", "Delta", "guillemotleft",
+    /* 170 */
+    "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
+    "Otilde", "OE", "oe", "endash", "emdash",
+    /* 180 */
+    "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
+    "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
+    /* 190 */
+    "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
+    "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
+    /* 200 */
+    "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
+    "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
+    /* 210 */
+    "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
+    "dotlessi", "circumflex", "tilde", "macron", "breve",
+    /* 220 */
+    "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
+    "caron", "Lslash", "lslash", "Scaron", "scaron",
+    /* 230 */
+    "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
+    "Yacute", "yacute", "Thorn", "thorn", "minus",
+    /* 240 */
+    "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
+    "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
+    /* 250 */
+    "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
+    "Ccaron", "ccaron", "dmacron",
+  };
+
+
+#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+  static FT_Error
+  Load_Format_20( TT_Face    face,
+                  FT_Stream  stream )
+  {
+    FT_Memory  memory = stream->memory;
+    FT_Error   error;
+
+    FT_Int     num_glyphs;
+    FT_UShort  num_names;
+
+    FT_UShort* glyph_indices = 0;
+    FT_Char**  name_strings  = 0;
+
+
+    if ( READ_UShort( num_glyphs ) )
+      goto Exit;
+
+    /* UNDOCUMENTED!  The number of glyphs in this table can be smaller */
+    /* than the value in the maxp table (cf. cyberbit.ttf).             */
+
+    /* There already exist fonts which have more than 32768 glyph names */
+    /* in this table, so the test for this threshold has been dropped.  */
+
+    if ( num_glyphs > face->root.num_glyphs )
+    {
+      error = SFNT_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    /* load the indices */
+    {
+      FT_Int  n;
+
+
+      if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, FT_UShort ) ||
+           ACCESS_Frame( num_glyphs * 2L )                      )
+        goto Fail;
+
+      for ( n = 0; n < num_glyphs; n++ )
+        glyph_indices[n] = GET_UShort();
+
+      FORGET_Frame();
+    }
+
+    /* compute number of names stored in table */
+    {
+      FT_Int  n;
+
+
+      num_names = 0;
+
+      for ( n = 0; n < num_glyphs; n++ )
+      {
+        FT_Int  index;
+
+
+        index = glyph_indices[n];
+        if ( index >= 258 )
+        {
+          index -= 257;
+          if ( index > num_names )
+            num_names = (FT_UShort)index;
+        }
+      }
+    }
+
+    /* now load the name strings */
+    {
+      FT_UShort  n;
+
+
+      if ( ALLOC_ARRAY( name_strings, num_names, FT_Char* ) )
+        goto Fail;
+
+      for ( n = 0; n < num_names; n++ )
+      {
+        FT_UInt  len;
+
+
+        if ( READ_Byte  ( len )                               ||
+             ALLOC_ARRAY( name_strings[n], len + 1, FT_Char ) ||
+             FILE_Read  ( name_strings[n], len )              )
+          goto Fail1;
+
+        name_strings[n][len] = '\0';
+      }
+    }
+
+    /* all right, set table fields and exit successfuly */
+    {
+      TT_Post_20*  table = &face->postscript_names.names.format_20;
+
+
+      table->num_glyphs    = (FT_UShort)num_glyphs;
+      table->num_names     = (FT_UShort)num_names;
+      table->glyph_indices = glyph_indices;
+      table->glyph_names   = name_strings;
+    }
+    return SFNT_Err_Ok;
+
+
+  Fail1:
+    {
+      FT_UShort  n;
+
+
+      for ( n = 0; n < num_names; n++ )
+        FREE( name_strings[n] );
+    }
+
+  Fail:
+    FREE( name_strings );
+    FREE( glyph_indices );
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_Error
+  Load_Format_25( TT_Face    face,
+                  FT_Stream  stream )
+  {
+    FT_Memory  memory = stream->memory;
+    FT_Error   error;
+
+    FT_Int     num_glyphs;
+    FT_Char*   offset_table = 0;
+
+
+    /* UNDOCUMENTED!  This value appears only in the Apple TT specs. */
+    if ( READ_UShort( num_glyphs ) )
+      goto Exit;
+
+    /* check the number of glyphs */
+    if ( num_glyphs > face->root.num_glyphs || num_glyphs > 258 )
+    {
+      error = SFNT_Err_Invalid_File_Format;
+      goto Exit;
+    }
+
+    if ( ALLOC    ( offset_table, num_glyphs ) ||
+         FILE_Read( offset_table, num_glyphs ) )
+      goto Fail;
+
+    /* now check the offset table */
+    {
+      FT_Int  n;
+
+
+      for ( n = 0; n < num_glyphs; n++ )
+      {
+        FT_Long  index = (FT_Long)n + offset_table[n];
+
+
+        if ( index < 0 || index > num_glyphs )
+        {
+          error = SFNT_Err_Invalid_File_Format;
+          goto Fail;
+        }
+      }
+    }
+
+    /* OK, set table fields and exit successfuly */
+    {
+      TT_Post_25*  table = &face->postscript_names.names.format_25;
+
+
+      table->num_glyphs = (FT_UShort)num_glyphs;
+      table->offsets    = offset_table;
+    }
+
+    return SFNT_Err_Ok;
+
+  Fail:
+    FREE( offset_table );
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_Error
+  Load_Post_Names( TT_Face  face )
+  {
+    FT_Stream  stream;
+    FT_Error   error;
+    FT_Fixed   format;
+
+
+    /* get a stream for the face's resource */
+    stream = face->root.stream;
+
+    /* seek to the beginning of the PS names table */
+    error = face->goto_table( face, TTAG_post, stream, 0 );
+    if ( error )
+      goto Exit;
+
+    format = face->postscript.FormatType;
+
+    /* go to beginning of subtable */
+    if ( FILE_Skip( 32 ) )
+      goto Exit;
+
+    /* now read postscript table */
+    switch ( format )
+    {
+    case 0x00020000L:
+      error = Load_Format_20( face, stream );
+      break;
+
+    case 0x00028000L:
+      error = Load_Format_25( face, stream );
+      break;
+
+    default:
+      error = SFNT_Err_Invalid_File_Format;
+    }
+
+    face->postscript_names.loaded = 1;
+
+  Exit:
+    return error;
+  }
+
+
+  FT_LOCAL_DEF void
+  TT_Free_Post_Names( TT_Face  face )
+  {
+    FT_Memory       memory = face->root.memory;
+    TT_Post_Names*  names  = &face->postscript_names;
+
+
+    if ( names->loaded )
+    {
+      switch ( face->postscript.FormatType )
+      {
+      case 0x00020000L:
+        {
+          TT_Post_20*  table = &names->names.format_20;
+          FT_UShort    n;
+
+
+          FREE( table->glyph_indices );
+          table->num_glyphs = 0;
+
+          for ( n = 0; n < table->num_names; n++ )
+            FREE( table->glyph_names[n] );
+
+          FREE( table->glyph_names );
+          table->num_names = 0;
+        }
+        break;
+
+      case 0x00028000L:
+        {
+          TT_Post_25*  table = &names->names.format_25;
+
+
+          FREE( table->offsets );
+          table->num_glyphs = 0;
+        }
+        break;
+      }
+    }
+    names->loaded = 0;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Get_PS_Name                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Gets the PostScript glyph name of a glyph.                         */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: A handle to the parent face.                             */
+  /*                                                                       */
+  /*    index  :: The glyph index.                                         */
+  /*                                                                       */
+  /*    PSname :: The address of a string pointer.  Will be NULL in case   */
+  /*              of error, otherwise it is a pointer to the glyph name.   */
+  /*                                                                       */
+  /*              You must not modify the returned string!                 */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Get_PS_Name( TT_Face      face,
+                  FT_UInt      index,
+                  FT_String**  PSname )
+  {
+    FT_Error            error;
+    TT_Post_Names*      names;
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+    PSNames_Interface*  psnames;
+#endif
+
+
+    if ( !face )
+      return SFNT_Err_Invalid_Face_Handle;
+
+    if ( index >= (FT_UInt)face->root.num_glyphs )
+      return SFNT_Err_Invalid_Glyph_Index;
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+    psnames = (PSNames_Interface*)face->psnames;
+    if ( !psnames )
+      return SFNT_Err_Unimplemented_Feature;
+#endif
+
+    names = &face->postscript_names;
+
+    /* `.notdef' by default */
+    *PSname = MAC_NAME( 0 );
+
+    switch ( face->postscript.FormatType )
+    {
+    case 0x00010000L:
+      if ( index < 258 )                    /* paranoid checking */
+        *PSname = MAC_NAME( index );
+      break;
+
+    case 0x00020000L:
+      {
+        TT_Post_20*  table = &names->names.format_20;
+
+
+        if ( !names->loaded )
+        {
+          error = Load_Post_Names( face );
+          if ( error )
+            break;
+        }
+
+        if ( index < (FT_UInt)table->num_glyphs )
+        {
+          FT_UShort  name_index = table->glyph_indices[index];
+
+
+          if ( name_index < 258 )
+            *PSname = MAC_NAME( name_index );
+          else
+            *PSname = (FT_String*)table->glyph_names[name_index - 258];
+        }
+      }
+      break;
+
+    case 0x00028000L:
+      {
+        TT_Post_25*  table = &names->names.format_25;
+
+
+        if ( !names->loaded )
+        {
+          error = Load_Post_Names( face );
+          if ( error )
+            break;
+        }
+
+        if ( index < (FT_UInt)table->num_glyphs )    /* paranoid checking */
+        {
+          index  += table->offsets[index];
+          *PSname = MAC_NAME( index );
+        }
+      }
+      break;
+
+    case 0x00030000L:
+      break;                                /* nothing to do */
+    }
+
+    return SFNT_Err_Ok;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/ttsbit.c b/libraries/freetype-2.0.5/ttsbit.c
new file mode 100644 (file)
index 0000000..cb007a1
--- /dev/null
@@ -0,0 +1,1470 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttsbit.c                                                               */
+/*                                                                         */
+/*    TrueType and OpenType embedded bitmap support (body).                */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include "ttsbit.h"
+
+#include "sferrors.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_ttsbit
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    blit_sbit                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Blits a bitmap from an input stream into a given target.  Supports */
+  /*    x and y offsets as well as byte padded lines.                      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    target      :: The target bitmap/pixmap.                           */
+  /*                                                                       */
+  /*    source      :: The input packed bitmap data.                       */
+  /*                                                                       */
+  /*    line_bits   :: The number of bits per line.                        */
+  /*                                                                       */
+  /*    byte_padded :: A flag which is true if lines are byte-padded.      */
+  /*                                                                       */
+  /*    x_offset    :: The horizontal offset.                              */
+  /*                                                                       */
+  /*    y_offset    :: The vertical offset.                                */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    IMPORTANT: The x and y offsets are relative to the top corner of   */
+  /*               the target bitmap (unlike the normal TrueType           */
+  /*               convention).  A positive y offset indicates a downwards */
+  /*               direction!                                              */
+  /*                                                                       */
+  static void
+  blit_sbit( FT_Bitmap*  target,
+             FT_Byte*    source,
+             FT_Int      line_bits,
+             FT_Bool     byte_padded,
+             FT_Int      x_offset,
+             FT_Int      y_offset )
+  {
+    FT_Byte*   line_buff;
+    FT_Int     line_incr;
+    FT_Int     height;
+
+    FT_UShort  acc;
+    FT_UInt    loaded;
+
+
+    /* first of all, compute starting write position */
+    line_incr = target->pitch;
+    line_buff = target->buffer;
+
+    if ( line_incr < 0 )
+      line_buff -= line_incr * ( target->rows - 1 );
+
+    line_buff += ( x_offset >> 3 ) + y_offset * line_incr;
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* We use the extra-classic `accumulator' trick to extract the bits    */
+    /* from the source byte stream.                                        */
+    /*                                                                     */
+    /* Namely, the variable `acc' is a 16-bit accumulator containing the   */
+    /* last `loaded' bits from the input stream.  The bits are shifted to  */
+    /* the upmost position in `acc'.                                       */
+    /*                                                                     */
+    /***********************************************************************/
+
+    acc    = 0;  /* clear accumulator   */
+    loaded = 0;  /* no bits were loaded */
+
+    for ( height = target->rows; height > 0; height-- )
+    {
+      FT_Byte*  cur   = line_buff;        /* current write cursor          */
+      FT_Int    count = line_bits;        /* # of bits to extract per line */
+      FT_Byte   shift = (FT_Byte)( x_offset & 7 ); /* current write shift  */
+      FT_Byte   space = (FT_Byte)( 8 - shift );
+
+
+      /* first of all, read individual source bytes */
+      if ( count >= 8 )
+      {
+        count -= 8;
+        {
+          do
+          {
+            FT_Byte  val;
+
+
+            /* ensure that there are at least 8 bits in the accumulator */
+            if ( loaded < 8 )
+            {
+              acc    |= (FT_UShort)*source++ << ( 8 - loaded );
+              loaded += 8;
+            }
+
+            /* now write one byte */
+            val = (FT_Byte)( acc >> 8 );
+            if ( shift )
+            {
+              cur[0] |= val >> shift;
+              cur[1] |= val << space;
+            }
+            else
+              cur[0] |= val;
+
+            cur++;
+            acc   <<= 8;  /* remove bits from accumulator */
+            loaded -= 8;
+            count  -= 8;
+
+          } while ( count >= 0 );
+        }
+
+        /* restore `count' to correct value */
+        count += 8;
+      }
+
+      /* now write remaining bits (count < 8) */
+      if ( count > 0 )
+      {
+        FT_Byte  val;
+
+
+        /* ensure that there are at least `count' bits in the accumulator */
+        if ( (FT_Int)loaded < count )
+        {
+          acc    |= (FT_UShort)*source++ << ( 8 - loaded );
+          loaded += 8;
+        }
+
+        /* now write remaining bits */
+        val     = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) );
+        cur[0] |= val >> shift;
+
+        if ( count > space )
+          cur[1] |= val << space;
+
+        acc   <<= count;
+        loaded -= count;
+      }
+
+      /* now, skip to next line */
+      if ( byte_padded )
+      {
+        acc    = 0;
+        loaded = 0;   /* clear accumulator on byte-padded lines */
+      }
+
+      line_buff += line_incr;
+    }
+  }
+
+
+  const FT_Frame_Field  sbit_metrics_fields[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_SBit_Metrics
+
+    FT_FRAME_START( 8 ),
+      FT_FRAME_BYTE( height ),
+      FT_FRAME_BYTE( width ),
+
+      FT_FRAME_CHAR( horiBearingX ),
+      FT_FRAME_CHAR( horiBearingY ),
+      FT_FRAME_BYTE( horiAdvance ),
+
+      FT_FRAME_CHAR( vertBearingX ),
+      FT_FRAME_CHAR( vertBearingY ),
+      FT_FRAME_BYTE( vertAdvance ),
+    FT_FRAME_END
+  };
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SBit_Const_Metrics                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the metrics for `EBLC' index tables format 2 and 5.          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range  :: The target range.                                        */
+  /*                                                                       */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  Load_SBit_Const_Metrics( TT_SBit_Range*  range,
+                           FT_Stream       stream )
+  {
+    FT_Error  error;
+
+
+    if ( READ_ULong( range->image_size ) )
+      return error;
+
+    return READ_Fields( sbit_metrics_fields, &range->metrics );
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SBit_Range_Codes                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the range codes for `EBLC' index tables format 4 and 5.      */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range        :: The target range.                                  */
+  /*                                                                       */
+  /*    stream       :: The input stream.                                  */
+  /*                                                                       */
+  /*    load_offsets :: A flag whether to load the glyph offset table.     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  Load_SBit_Range_Codes( TT_SBit_Range*  range,
+                         FT_Stream       stream,
+                         FT_Bool         load_offsets )
+  {
+    FT_Error   error;
+    FT_ULong   count, n, size;
+    FT_Memory  memory = stream->memory;
+
+
+    if ( READ_ULong( count ) )
+      goto Exit;
+
+    range->num_glyphs = count;
+
+    /* Allocate glyph offsets table if needed */
+    if ( load_offsets )
+    {
+      if ( ALLOC_ARRAY( range->glyph_offsets, count, FT_ULong ) )
+        goto Exit;
+
+      size = count * 4L;
+    }
+    else
+      size = count * 2L;
+
+    /* Allocate glyph codes table and access frame */
+    if ( ALLOC_ARRAY ( range->glyph_codes, count, FT_UShort ) ||
+         ACCESS_Frame( size )                                 )
+      goto Exit;
+
+    for ( n = 0; n < count; n++ )
+    {
+      range->glyph_codes[n] = GET_UShort();
+
+      if ( load_offsets )
+        range->glyph_offsets[n] = (FT_ULong)range->image_offset +
+                                  GET_UShort();
+    }
+
+    FORGET_Frame();
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SBit_Range                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given `EBLC' index/range table.                            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    range  :: The target range.                                        */
+  /*                                                                       */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  static FT_Error
+  Load_SBit_Range( TT_SBit_Range*  range,
+                   FT_Stream       stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+
+    switch( range->index_format )
+    {
+    case 1:   /* variable metrics with 4-byte offsets */
+    case 3:   /* variable metrics with 2-byte offsets */
+      {
+        FT_ULong  num_glyphs, n;
+        FT_Int    size_elem;
+        FT_Bool   large = FT_BOOL( range->index_format == 1 );
+
+
+        num_glyphs        = range->last_glyph - range->first_glyph + 1L;
+        range->num_glyphs = num_glyphs;
+        num_glyphs++;                       /* XXX: BEWARE - see spec */
+
+        size_elem = large ? 4 : 2;
+
+        if ( ALLOC_ARRAY( range->glyph_offsets,
+                          num_glyphs, FT_ULong )    ||
+             ACCESS_Frame( num_glyphs * size_elem ) )
+          goto Exit;
+
+        for ( n = 0; n < num_glyphs; n++ )
+          range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
+                                                  ( large ? GET_ULong()
+                                                          : GET_UShort() ) );
+        FORGET_Frame();
+      }
+      break;
+
+    case 2:   /* all glyphs have identical metrics */
+      error = Load_SBit_Const_Metrics( range, stream );
+      break;
+
+    case 4:
+      error = Load_SBit_Range_Codes( range, stream, 1 );
+      break;
+
+    case 5:
+      error = Load_SBit_Const_Metrics( range, stream ) ||
+              Load_SBit_Range_Codes( range, stream, 0  );
+      break;
+
+    default:
+      error = SFNT_Err_Invalid_File_Format;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SBit_Strikes                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads the table of embedded bitmap sizes for this face.            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face   :: The target face object.                                  */
+  /*                                                                       */
+  /*    stream :: The input stream.                                        */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_SBit_Strikes( TT_Face    face,
+                        FT_Stream  stream )
+  {
+    FT_Error   error  = 0;
+    FT_Memory  memory = stream->memory;
+    FT_Fixed   version;
+    FT_ULong   num_strikes;
+    FT_ULong   table_base;
+
+    const FT_Frame_Field  sbit_line_metrics_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_SBit_Line_Metrics
+
+      /* no FT_FRAME_START */
+        FT_FRAME_CHAR( ascender ),
+        FT_FRAME_CHAR( descender ),
+        FT_FRAME_BYTE( max_width ),
+
+        FT_FRAME_CHAR( caret_slope_numerator ),
+        FT_FRAME_CHAR( caret_slope_denominator ),
+        FT_FRAME_CHAR( caret_offset ),
+
+        FT_FRAME_CHAR( min_origin_SB ),
+        FT_FRAME_CHAR( min_advance_SB ),
+        FT_FRAME_CHAR( max_before_BL ),
+        FT_FRAME_CHAR( min_after_BL ),
+        FT_FRAME_CHAR( pads[0] ),
+        FT_FRAME_CHAR( pads[1] ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  strike_start_fields[] =
+    {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_SBit_Strike
+
+      /* no FT_FRAME_START */
+        FT_FRAME_ULONG( ranges_offset ),
+        FT_FRAME_SKIP_LONG,
+        FT_FRAME_ULONG( num_ranges ),
+        FT_FRAME_ULONG( color_ref ),
+      FT_FRAME_END
+    };
+
+    const FT_Frame_Field  strike_end_fields[] =
+    {
+      /* no FT_FRAME_START */
+        FT_FRAME_USHORT( start_glyph ),
+        FT_FRAME_USHORT( end_glyph ),
+        FT_FRAME_BYTE  ( x_ppem ),
+        FT_FRAME_BYTE  ( y_ppem ),
+        FT_FRAME_BYTE  ( bit_depth ),
+        FT_FRAME_CHAR  ( flags ),
+      FT_FRAME_END
+    };
+
+
+    face->num_sbit_strikes = 0;
+
+    /* this table is optional */
+    error = face->goto_table( face, TTAG_EBLC, stream, 0 );
+    if ( error )
+      error = face->goto_table( face, TTAG_bloc, stream, 0 );
+    if ( error )
+      goto Exit;
+
+    table_base = FILE_Pos();
+    if ( ACCESS_Frame( 8L ) )
+      goto Exit;
+
+    version     = GET_Long();
+    num_strikes = GET_ULong();
+
+    FORGET_Frame();
+
+    /* check version number and strike count */
+    if ( version     != 0x00020000L ||
+         num_strikes >= 0x10000L    )
+    {
+      FT_ERROR(( "TT_Load_SBit_Strikes: invalid table version!\n" ));
+      error = SFNT_Err_Invalid_File_Format;
+
+      goto Exit;
+    }
+
+    /* allocate the strikes table */
+    if ( ALLOC_ARRAY( face->sbit_strikes, num_strikes, TT_SBit_Strike ) )
+      goto Exit;
+
+    face->num_sbit_strikes = num_strikes;
+
+    /* now read each strike table separately */
+    {
+      TT_SBit_Strike*  strike = face->sbit_strikes;
+      FT_ULong         count  = num_strikes;
+
+
+      if ( ACCESS_Frame( 48L * num_strikes ) )
+        goto Exit;
+
+      while ( count > 0 )
+      {
+        if ( READ_Fields( strike_start_fields, strike )             ||
+             READ_Fields( sbit_line_metrics_fields, &strike->hori ) ||
+             READ_Fields( sbit_line_metrics_fields, &strike->vert ) ||
+             READ_Fields( strike_end_fields, strike )               )
+          break;
+
+        count--;
+        strike++;
+      }
+
+      FORGET_Frame();
+    }
+
+    /* allocate the index ranges for each strike table */
+    {
+      TT_SBit_Strike*  strike = face->sbit_strikes;
+      FT_ULong         count  = num_strikes;
+
+
+      while ( count > 0 )
+      {
+        TT_SBit_Range*  range;
+        FT_ULong        count2 = strike->num_ranges;
+
+
+        if ( ALLOC_ARRAY( strike->sbit_ranges,
+                          strike->num_ranges,
+                          TT_SBit_Range ) )
+          goto Exit;
+
+        /* read each range */
+        if ( FILE_Seek( table_base + strike->ranges_offset ) ||
+             ACCESS_Frame( strike->num_ranges * 8L )         )
+          goto Exit;
+
+        range = strike->sbit_ranges;
+        while ( count2 > 0 )
+        {
+          range->first_glyph  = GET_UShort();
+          range->last_glyph   = GET_UShort();
+          range->table_offset = table_base + strike->ranges_offset
+                                 + GET_ULong();
+          count2--;
+          range++;
+        }
+
+        FORGET_Frame();
+
+        /* Now, read each index table */
+        count2 = strike->num_ranges;
+        range  = strike->sbit_ranges;
+        while ( count2 > 0 )
+        {
+          /* Read the header */
+          if ( FILE_Seek( range->table_offset ) ||
+               ACCESS_Frame( 8L )               )
+            goto Exit;
+
+          range->index_format = GET_UShort();
+          range->image_format = GET_UShort();
+          range->image_offset = GET_ULong();
+
+          FORGET_Frame();
+
+          error = Load_SBit_Range( range, stream );
+          if ( error )
+            goto Exit;
+
+          count2--;
+          range++;
+        }
+
+        count--;
+        strike++;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Free_SBit_Strikes                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Releases the embedded bitmap tables.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face :: The target face object.                                    */
+  /*                                                                       */
+  FT_LOCAL_DEF void
+  TT_Free_SBit_Strikes( TT_Face  face )
+  {
+    FT_Memory        memory       = face->root.memory;
+    TT_SBit_Strike*  strike       = face->sbit_strikes;
+    TT_SBit_Strike*  strike_limit = strike + face->num_sbit_strikes;
+
+
+    if ( strike )
+    {
+      for ( ; strike < strike_limit; strike++ )
+      {
+        TT_SBit_Range*  range       = strike->sbit_ranges;
+        TT_SBit_Range*  range_limit = range + strike->num_ranges;
+
+
+        if ( range )
+        {
+          for ( ; range < range_limit; range++ )
+          {
+            /* release the glyph offsets and codes tables */
+            /* where appropriate                          */
+            FREE( range->glyph_offsets );
+            FREE( range->glyph_codes );
+          }
+        }
+        FREE( strike->sbit_ranges );
+        strike->num_ranges = 0;
+      }
+      FREE( face->sbit_strikes );
+    }
+    face->num_sbit_strikes = 0;
+  }
+
+
+  FT_LOCAL_DEF FT_Error
+  TT_Set_SBit_Strike( TT_Face    face,
+                      FT_Int     x_ppem,
+                      FT_Int     y_ppem,
+                      FT_ULong  *astrike_index )
+  {
+    FT_Int  i;
+
+
+    if ( x_ppem < 0 || x_ppem > 255 ||
+         y_ppem < 1 || y_ppem > 255 )
+      return SFNT_Err_Invalid_PPem;
+
+    for ( i = 0; i < face->num_sbit_strikes; i++ )
+    {
+      if ( ( face->sbit_strikes[i].y_ppem  == y_ppem )  &&
+           ( ( x_ppem == 0 ) ||
+             ( face->sbit_strikes[i].x_ppem == x_ppem ) ) )
+      {
+        *astrike_index = i;
+        return SFNT_Err_Ok;
+      }
+    }
+
+    return SFNT_Err_Invalid_PPem;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Find_SBit_Range                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Scans a given strike's ranges and return, for a given glyph        */
+  /*    index, the corresponding sbit range, and `EBDT' offset.            */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    glyph_index   :: The glyph index.                                  */
+  /*                                                                       */
+  /*    strike        :: The source/current sbit strike.                   */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    arange        :: The sbit range containing the glyph index.        */
+  /*                                                                       */
+  /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means the glyph index was found.           */
+  /*                                                                       */
+  static FT_Error
+  Find_SBit_Range( FT_UInt          glyph_index,
+                   TT_SBit_Strike*  strike,
+                   TT_SBit_Range**  arange,
+                   FT_ULong*        aglyph_offset )
+  {
+    TT_SBit_Range  *range, *range_limit;
+
+
+    /* check whether the glyph index is within this strike's */
+    /* glyph range                                           */
+    if ( glyph_index < (FT_UInt)strike->start_glyph ||
+         glyph_index > (FT_UInt)strike->end_glyph   )
+      goto Fail;
+
+    /* scan all ranges in strike */
+    range       = strike->sbit_ranges;
+    range_limit = range + strike->num_ranges;
+    if ( !range )
+      goto Fail;
+
+    for ( ; range < range_limit; range++ )
+    {
+      if ( glyph_index >= (FT_UInt)range->first_glyph &&
+           glyph_index <= (FT_UInt)range->last_glyph  )
+      {
+        FT_UShort  delta = (FT_UShort)( glyph_index - range->first_glyph );
+
+
+        switch ( range->index_format )
+        {
+        case 1:
+        case 3:
+          *aglyph_offset = range->glyph_offsets[delta];
+          break;
+
+        case 2:
+          *aglyph_offset = range->image_offset +
+                           range->image_size * delta;
+          break;
+
+        case 4:
+        case 5:
+          {
+            FT_ULong  n;
+
+
+            for ( n = 0; n < range->num_glyphs; n++ )
+            {
+              if ( (FT_UInt)range->glyph_codes[n] == glyph_index )
+              {
+                if ( range->index_format == 4 )
+                  *aglyph_offset = range->glyph_offsets[n];
+                else
+                  *aglyph_offset = range->image_offset +
+                                   n * range->image_size;
+                goto Found;
+              }
+            }
+          }
+
+          /* fall-through */
+          default:
+            goto Fail;
+        }
+
+    Found:
+        /* return successfully! */
+        *arange  = range;
+        return 0;
+      }
+    }
+
+  Fail:
+    *arange        = 0;
+    *aglyph_offset = 0;
+
+    return SFNT_Err_Invalid_Argument;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Find_SBit_Image                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Checks whether an embedded bitmap (an `sbit') exists for a given   */
+  /*    glyph, at a given strike.                                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face          :: The target face object.                           */
+  /*                                                                       */
+  /*    glyph_index   :: The glyph index.                                  */
+  /*                                                                       */
+  /*    strike_index  :: The current strike index.                         */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    arange        :: The SBit range containing the glyph index.        */
+  /*                                                                       */
+  /*    astrike       :: The SBit strike containing the glyph index.       */
+  /*                                                                       */
+  /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  Returns                    */
+  /*    SFNT_Err_Invalid_Argument if no sbit exists for the requested      */
+  /*    glyph.                                                             */
+  /*                                                                       */
+  static FT_Error
+  Find_SBit_Image( TT_Face           face,
+                   FT_UInt           glyph_index,
+                   FT_ULong          strike_index,
+                   TT_SBit_Range*   *arange,
+                   TT_SBit_Strike*  *astrike,
+                   FT_ULong         *aglyph_offset )
+  {
+    FT_Error         error;
+    TT_SBit_Strike*  strike;
+
+
+    if ( !face->sbit_strikes                              ||
+         ( face->num_sbit_strikes <= (FT_Int)strike_index ) )
+      goto Fail;
+
+    strike = &face->sbit_strikes[strike_index];
+
+    error = Find_SBit_Range( glyph_index, strike,
+                             arange, aglyph_offset );
+    if ( error )
+      goto Fail;
+
+    *astrike = strike;
+
+    return SFNT_Err_Ok;
+
+  Fail:
+    /* no embedded bitmap for this glyph in face */
+    *arange        = 0;
+    *astrike       = 0;
+    *aglyph_offset = 0;
+
+    return SFNT_Err_Invalid_Argument;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Load_SBit_Metrics                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Gets the big metrics for a given SBit.                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    stream      :: The input stream.                                   */
+  /*                                                                       */
+  /*    range       :: The SBit range containing the glyph.                */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    big_metrics :: A big SBit metrics structure for the glyph.         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    The stream cursor must be positioned at the glyph's offset within  */
+  /*    the `EBDT' table before the call.                                  */
+  /*                                                                       */
+  /*    If the image format uses variable metrics, the stream cursor is    */
+  /*    positioned just after the metrics header in the `EBDT' table on    */
+  /*    function exit.                                                     */
+  /*                                                                       */
+  static FT_Error
+  Load_SBit_Metrics( FT_Stream         stream,
+                     TT_SBit_Range*    range,
+                     TT_SBit_Metrics*  metrics )
+  {
+    FT_Error  error = SFNT_Err_Ok;
+
+
+    switch ( range->image_format )
+    {
+    case 1:
+    case 2:
+    case 8:
+      /* variable small metrics */
+      {
+        TT_SBit_Small_Metrics  smetrics;
+
+        const FT_Frame_Field  sbit_small_metrics_fields[] =
+        {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  TT_SBit_Small_Metrics
+
+          FT_FRAME_START( 5 ),
+            FT_FRAME_BYTE( height ),
+            FT_FRAME_BYTE( width ),
+            FT_FRAME_CHAR( bearingX ),
+            FT_FRAME_CHAR( bearingY ),
+            FT_FRAME_BYTE( advance ),
+          FT_FRAME_END
+        };
+
+
+        /* read small metrics */
+        if ( READ_Fields( sbit_small_metrics_fields, &smetrics ) )
+          goto Exit;
+
+        /* convert it to a big metrics */
+        metrics->height       = smetrics.height;
+        metrics->width        = smetrics.width;
+        metrics->horiBearingX = smetrics.bearingX;
+        metrics->horiBearingY = smetrics.bearingY;
+        metrics->horiAdvance  = smetrics.advance;
+
+        /* these metrics are made up at a higher level when */
+        /* needed.                                          */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+      }
+      break;
+
+    case 6:
+    case 7:
+    case 9:
+      /* variable big metrics */
+      if ( READ_Fields( sbit_metrics_fields, metrics ) )
+        goto Exit;
+      break;
+
+    case 5:
+    default:  /* constant metrics */
+      if ( range->index_format == 2 || range->index_format == 5 )
+        *metrics = range->metrics;
+      else
+        return SFNT_Err_Invalid_File_Format;
+   }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Crop_Bitmap                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Crops a bitmap to its tightest bounding box, and adjusts its       */
+  /*    metrics.                                                           */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    map     :: The bitmap.                                             */
+  /*                                                                       */
+  /*    metrics :: The corresponding metrics structure.                    */
+  /*                                                                       */
+  static void
+  Crop_Bitmap( FT_Bitmap*        map,
+               TT_SBit_Metrics*  metrics )
+  {
+    /***********************************************************************/
+    /*                                                                     */
+    /* In this situation, some bounding boxes of embedded bitmaps are too  */
+    /* large.  We need to crop it to a reasonable size.                    */
+    /*                                                                     */
+    /*      ---------                                                      */
+    /*      |       |                -----                                 */
+    /*      |  ***  |                |***|                                 */
+    /*      |   *   |                | * |                                 */
+    /*      |   *   |    ------>     | * |                                 */
+    /*      |   *   |                | * |                                 */
+    /*      |   *   |                | * |                                 */
+    /*      |  ***  |                |***|                                 */
+    /*      ---------                -----                                 */
+    /*                                                                     */
+    /***********************************************************************/
+
+    FT_Int    rows, count;
+    FT_Long   line_len;
+    FT_Byte*  line;
+
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* first of all, check the top-most lines of the bitmap, and remove    */
+    /* them if they're empty.                                              */
+    /*                                                                     */
+    {
+      line     = (FT_Byte*)map->buffer;
+      rows     = map->rows;
+      line_len = map->pitch;
+
+
+      for ( count = 0; count < rows; count++ )
+      {
+        FT_Byte*  cur   = line;
+        FT_Byte*  limit = line + line_len;
+
+
+        for ( ; cur < limit; cur++ )
+          if ( cur[0] )
+            goto Found_Top;
+
+        /* the current line was empty - skip to next one */
+        line  = limit;
+      }
+
+    Found_Top:
+      /* check that we have at least one filled line */
+      if ( count >= rows )
+        goto Empty_Bitmap;
+
+      /* now, crop the empty upper lines */
+      if ( count > 0 )
+      {
+        line = (FT_Byte*)map->buffer;
+
+        MEM_Move( line, line + count * line_len,
+                  ( rows - count ) * line_len );
+
+        metrics->height       = (FT_Byte)( metrics->height - count );
+        metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count );
+        metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count );
+
+        map->rows -= count;
+        rows      -= count;
+      }
+    }
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* second, crop the lower lines                                        */
+    /*                                                                     */
+    {
+      line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;
+
+      for ( count = 0; count < rows; count++ )
+      {
+        FT_Byte*  cur   = line;
+        FT_Byte*  limit = line + line_len;
+
+
+        for ( ; cur < limit; cur++ )
+          if ( cur[0] )
+            goto Found_Bottom;
+
+        /* the current line was empty - skip to previous one */
+        line -= line_len;
+      }
+
+    Found_Bottom:
+      if ( count > 0 )
+      {
+        metrics->height  = (FT_Byte)( metrics->height - count );
+        rows            -= count;
+        map->rows       -= count;
+      }
+    }
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* third, get rid of the space on the left side of the glyph           */
+    /*                                                                     */
+    do
+    {
+      FT_Byte*  limit;
+
+
+      line  = (FT_Byte*)map->buffer;
+      limit = line + rows * line_len;
+
+      for ( ; line < limit; line += line_len )
+        if ( line[0] & 0x80 )
+          goto Found_Left;
+
+      /* shift the whole glyph one pixel to the left */
+      line  = (FT_Byte*)map->buffer;
+      limit = line + rows * line_len;
+
+      for ( ; line < limit; line += line_len )
+      {
+        FT_Int    n, width = map->width;
+        FT_Byte   old;
+        FT_Byte*  cur = line;
+
+
+        old = (FT_Byte)(cur[0] << 1);
+        for ( n = 8; n < width; n += 8 )
+        {
+          FT_Byte  val;
+
+
+          val    = cur[1];
+          cur[0] = (FT_Byte)( old | ( val >> 7 ) );
+          old    = (FT_Byte)( val << 1 );
+          cur++;
+        }
+        cur[0] = old;
+      }
+
+      map->width--;
+      metrics->horiBearingX++;
+      metrics->vertBearingX++;
+      metrics->width--;
+
+    } while ( map->width > 0 );
+
+  Found_Left:
+
+    /***********************************************************************/
+    /*                                                                     */
+    /* finally, crop the bitmap width to get rid of the space on the right */
+    /* side of the glyph.                                                  */
+    /*                                                                     */
+    do
+    {
+      FT_Int    right = map->width - 1;
+      FT_Byte*  limit;
+      FT_Byte   mask;
+
+
+      line  = (FT_Byte*)map->buffer + ( right >> 3 );
+      limit = line + rows * line_len;
+      mask  = (FT_Byte)( 0x80 >> ( right & 7 ) );
+
+      for ( ; line < limit; line += line_len )
+        if ( line[0] & mask )
+          goto Found_Right;
+
+      /* crop the whole glyph to the right */
+      map->width--;
+      metrics->width--;
+
+    } while ( map->width > 0 );
+
+  Found_Right:
+    /* all right, the bitmap was cropped */
+    return;
+
+  Empty_Bitmap:
+    map->width      = 0;
+    map->rows       = 0;
+    map->pitch      = 0;
+    map->pixel_mode = ft_pixel_mode_mono;
+  }
+
+
+  static FT_Error
+  Load_SBit_Single( FT_Bitmap*        map,
+                    FT_Int            x_offset,
+                    FT_Int            y_offset,
+                    FT_Int            pix_bits,
+                    FT_UShort         image_format,
+                    TT_SBit_Metrics*  metrics,
+                    FT_Stream         stream )
+  {
+    FT_Error  error;
+
+
+    /* check that the source bitmap fits into the target pixmap */
+    if ( x_offset < 0 || x_offset + metrics->width  > map->width ||
+         y_offset < 0 || y_offset + metrics->height > map->rows  )
+    {
+      error = SFNT_Err_Invalid_Argument;
+
+      goto Exit;
+    }
+
+    {
+      FT_Int  glyph_width  = metrics->width;
+      FT_Int  glyph_height = metrics->height;
+      FT_Int  glyph_size;
+      FT_Int  line_bits    = pix_bits * glyph_width;
+      FT_Bool pad_bytes    = 0;
+
+
+      /* compute size of glyph image */
+      switch ( image_format )
+      {
+      case 1:  /* byte-padded formats */
+      case 6:
+        {
+          FT_Int  line_length;
+
+
+          switch ( pix_bits )
+          {
+          case 1:  line_length = ( glyph_width + 7 ) >> 3;   break;
+          case 2:  line_length = ( glyph_width + 3 ) >> 2;   break;
+          case 4:  line_length = ( glyph_width + 1 ) >> 1;   break;
+          default: line_length =   glyph_width;
+          }
+
+          glyph_size = glyph_height * line_length;
+          pad_bytes  = 1;
+        }
+        break;
+
+      case 2:
+      case 5:
+      case 7:
+        line_bits  =   glyph_width  * pix_bits;
+        glyph_size = ( glyph_height * line_bits + 7 ) >> 3;
+        break;
+
+      default:  /* invalid format */
+        return SFNT_Err_Invalid_File_Format;
+      }
+
+      /* Now read data and draw glyph into target pixmap       */
+      if ( ACCESS_Frame( glyph_size ) )
+        goto Exit;
+
+      /* don't forget to multiply `x_offset' by `map->pix_bits' as */
+      /* the sbit blitter doesn't make a difference between pixmap */
+      /* depths.                                                   */
+      blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,
+                 x_offset * pix_bits, y_offset );
+
+      FORGET_Frame();
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_Error
+  Load_SBit_Image( TT_SBit_Strike*   strike,
+                   TT_SBit_Range*    range,
+                   FT_ULong          ebdt_pos,
+                   FT_ULong          glyph_offset,
+                   FT_Bitmap*        map,
+                   FT_Int            x_offset,
+                   FT_Int            y_offset,
+                   FT_Stream         stream,
+                   TT_SBit_Metrics*  metrics )
+  {
+    FT_Memory  memory = stream->memory;
+    FT_Error   error;
+
+
+    /* place stream at beginning of glyph data and read metrics */
+    if ( FILE_Seek( ebdt_pos + glyph_offset ) )
+      goto Exit;
+
+    error = Load_SBit_Metrics( stream, range, metrics );
+    if ( error )
+      goto Exit;
+
+    /* this function is recursive.  At the top-level call, the */
+    /* field map.buffer is NULL.  We thus begin by finding the */
+    /* dimensions of the higher-level glyph to allocate the    */
+    /* final pixmap buffer                                     */
+    if ( map->buffer == 0 )
+    {
+      FT_Long  size;
+
+
+      map->width = metrics->width;
+      map->rows  = metrics->height;
+
+      switch ( strike->bit_depth )
+      {
+      case 1:
+        map->pixel_mode = ft_pixel_mode_mono;
+        map->pitch      = ( map->width + 7 ) >> 3;
+        break;
+
+      case 2:
+        map->pixel_mode = ft_pixel_mode_pal2;
+        map->pitch      = ( map->width + 3 ) >> 2;
+        break;
+
+      case 4:
+        map->pixel_mode = ft_pixel_mode_pal4;
+        map->pitch      = ( map->width + 1 ) >> 1;
+        break;
+
+      case 8:
+        map->pixel_mode = ft_pixel_mode_grays;
+        map->pitch      = map->width;
+        break;
+
+      default:
+        return SFNT_Err_Invalid_File_Format;
+      }
+
+      size = map->rows * map->pitch;
+
+      /* check that there is no empty image */
+      if ( size == 0 )
+        goto Exit;     /* exit successfully! */
+
+      if ( ALLOC( map->buffer, size ) )
+        goto Exit;
+    }
+
+    switch ( range->image_format )
+    {
+    case 1:  /* single sbit image - load it */
+    case 2:
+    case 5:
+    case 6:
+    case 7:
+      return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,
+                               range->image_format, metrics, stream );
+
+    case 8:  /* compound format */
+      FT_Skip_Stream( stream, 1L );
+      /* fallthrough */
+
+    case 9:
+      break;
+
+    default: /* invalid image format */
+      return SFNT_Err_Invalid_File_Format;
+    }
+
+    /* All right, we have a compound format.  First of all, read */
+    /* the array of elements.                                    */
+    {
+      TT_SBit_Component*  components;
+      TT_SBit_Component*  comp;
+      FT_UShort           num_components, count;
+
+
+      if ( READ_UShort( num_components )                                ||
+           ALLOC_ARRAY( components, num_components, TT_SBit_Component ) )
+        goto Exit;
+
+      count = num_components;
+
+      if ( ACCESS_Frame( 4L * num_components ) )
+        goto Fail_Memory;
+
+      for ( comp = components; count > 0; count--, comp++ )
+      {
+        comp->glyph_code = GET_UShort();
+        comp->x_offset   = GET_Char();
+        comp->y_offset   = GET_Char();
+      }
+
+      FORGET_Frame();
+
+      /* Now recursively load each element glyph */
+      count = num_components;
+      comp  = components;
+      for ( ; count > 0; count--, comp++ )
+      {
+        TT_SBit_Range*   elem_range;
+        TT_SBit_Metrics  elem_metrics;
+        FT_ULong         elem_offset;
+
+
+        /* find the range for this element */
+        error = Find_SBit_Range( comp->glyph_code,
+                                 strike,
+                                 &elem_range,
+                                 &elem_offset );
+        if ( error )
+          goto Fail_Memory;
+
+        /* now load the element, recursively */
+        error = Load_SBit_Image( strike,
+                                 elem_range,
+                                 ebdt_pos,
+                                 elem_offset,
+                                 map,
+                                 x_offset + comp->x_offset,
+                                 y_offset + comp->y_offset,
+                                 stream,
+                                 &elem_metrics );
+        if ( error )
+          goto Fail_Memory;
+      }
+
+    Fail_Memory:
+      FREE( components );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Load_SBit_Image                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Loads a given glyph sbit image from the font resource.  This also  */
+  /*    returns its metrics.                                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    face         :: The target face object.                            */
+  /*                                                                       */
+  /*    strike_index :: The current strike index.                          */
+  /*                                                                       */
+  /*    glyph_index  :: The current glyph index.                           */
+  /*                                                                       */
+  /*    load_flags   :: The glyph load flags (the code checks for the flag */
+  /*                    FT_LOAD_CROP_BITMAP).                              */
+  /*                                                                       */
+  /*    stream       :: The input stream.                                  */
+  /*                                                                       */
+  /* <Output>                                                              */
+  /*    map          :: The target pixmap.                                 */
+  /*                                                                       */
+  /*    metrics      :: A big sbit metrics structure for the glyph image.  */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.  Returns an error if no     */
+  /*    glyph sbit exists for the index.                                   */
+  /*                                                                       */
+  /*  <Note>                                                               */
+  /*    The `map.buffer' field is always freed before the glyph is loaded. */
+  /*                                                                       */
+  FT_LOCAL_DEF FT_Error
+  TT_Load_SBit_Image( TT_Face           face,
+                      FT_ULong          strike_index,
+                      FT_UInt           glyph_index,
+                      FT_UInt           load_flags,
+                      FT_Stream         stream,
+                      FT_Bitmap        *map,
+                      TT_SBit_Metrics  *metrics )
+  {
+    FT_Error         error;
+    FT_Memory        memory = stream->memory;
+    FT_ULong         ebdt_pos, glyph_offset;
+
+    TT_SBit_Strike*  strike;
+    TT_SBit_Range*   range;
+
+
+    /* Check whether there is a glyph sbit for the current index */
+    error = Find_SBit_Image( face, glyph_index, strike_index,
+                             &range, &strike, &glyph_offset );
+    if ( error )
+      goto Exit;
+
+    /* now, find the location of the `EBDT' table in */
+    /* the font file                                 */
+    error = face->goto_table( face, TTAG_EBDT, stream, 0 );
+    if ( error )
+      error = face->goto_table( face, TTAG_bdat, stream, 0 );
+    if (error)
+      goto Exit;
+
+    ebdt_pos = FILE_Pos();
+
+    /* clear the bitmap & load the bitmap */
+    if ( face->root.glyph->flags & ft_glyph_own_bitmap )
+      FREE( map->buffer );
+
+    map->rows = map->pitch = map->width = 0;
+
+    error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset,
+                             map, 0, 0, stream, metrics );
+    if ( error )
+      goto Exit;
+
+    /* the glyph slot owns this bitmap buffer */
+    face->root.glyph->flags |= ft_glyph_own_bitmap;
+
+    /* setup vertical metrics if needed */
+    if ( strike->flags & 1 )
+    {
+      /* in case of a horizontal strike only */
+      FT_Int  advance;
+
+
+      advance = strike->hori.ascender - strike->hori.descender;
+
+      /* some heuristic values */
+
+      metrics->vertBearingX = (FT_Char)(-metrics->width / 2 );
+      metrics->vertBearingY = (FT_Char)( advance / 10 );
+      metrics->vertAdvance  = (FT_Char)( advance * 12 / 10 );
+    }
+
+    /* Crop the bitmap now, unless specified otherwise */
+    if ( load_flags & FT_LOAD_CROP_BITMAP )
+      Crop_Bitmap( map, metrics );
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/type1.c b/libraries/freetype-2.0.5/type1.c
new file mode 100644 (file)
index 0000000..ccc12be
--- /dev/null
@@ -0,0 +1,33 @@
+/***************************************************************************/
+/*                                                                         */
+/*  type1.c                                                                */
+/*                                                                         */
+/*    FreeType Type 1 driver component (body only).                        */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "t1parse.c"
+#include "t1load.c"
+#include "t1objs.c"
+#include "t1driver.c"
+#include "t1gload.c"
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "t1afm.c"
+#endif
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/type1cid.c b/libraries/freetype-2.0.5/type1cid.c
new file mode 100644 (file)
index 0000000..0b866e9
--- /dev/null
@@ -0,0 +1,29 @@
+/***************************************************************************/
+/*                                                                         */
+/*  type1cid.c                                                             */
+/*                                                                         */
+/*    FreeType OpenType driver component (body only).                      */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include <ft2build.h>
+#include "cidparse.c"
+#include "cidload.c"
+#include "cidobjs.c"
+#include "cidriver.c"
+#include "cidgload.c"
+
+
+/* END */
diff --git a/libraries/freetype-2.0.5/winfnt.c b/libraries/freetype-2.0.5/winfnt.c
new file mode 100644 (file)
index 0000000..5297697
--- /dev/null
@@ -0,0 +1,661 @@
+/***************************************************************************/
+/*                                                                         */
+/*  winfnt.c                                                               */
+/*                                                                         */
+/*    FreeType font driver for Windows FNT/FON files                       */
+/*                                                                         */
+/*  Copyright 1996-2001 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_FNT_TYPES_H
+
+#include "winfnt.h"
+
+#include "fnterrs.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_winfnt
+
+
+  static
+  const FT_Frame_Field  winmz_header_fields[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  WinMZ_Header
+
+    FT_FRAME_START( 64 ),
+      FT_FRAME_USHORT_LE ( magic ),
+      FT_FRAME_SKIP_BYTES( 29 * 2 ),
+      FT_FRAME_ULONG_LE  ( lfanew ),
+    FT_FRAME_END
+  };
+
+  static
+  const FT_Frame_Field  winne_header_fields[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  WinNE_Header
+
+    FT_FRAME_START( 40 ),
+      FT_FRAME_USHORT_LE ( magic ),
+      FT_FRAME_SKIP_BYTES( 34 ),
+      FT_FRAME_USHORT_LE ( resource_tab_offset ),
+      FT_FRAME_USHORT_LE ( rname_tab_offset ),
+    FT_FRAME_END
+  };
+
+  static
+  const FT_Frame_Field  winfnt_header_fields[] =
+  {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  WinFNT_Header
+
+    FT_FRAME_START( 134 ),
+      FT_FRAME_USHORT_LE( version ),
+      FT_FRAME_ULONG_LE ( file_size ),
+      FT_FRAME_BYTES    ( copyright, 60 ),
+      FT_FRAME_USHORT_LE( file_type ),
+      FT_FRAME_USHORT_LE( nominal_point_size ),
+      FT_FRAME_USHORT_LE( vertical_resolution ),
+      FT_FRAME_USHORT_LE( horizontal_resolution ),
+      FT_FRAME_USHORT_LE( ascent ),
+      FT_FRAME_USHORT_LE( internal_leading ),
+      FT_FRAME_USHORT_LE( external_leading ),
+      FT_FRAME_BYTE     ( italic ),
+      FT_FRAME_BYTE     ( underline ),
+      FT_FRAME_BYTE     ( strike_out ),
+      FT_FRAME_USHORT_LE( weight ),
+      FT_FRAME_BYTE     ( charset ),
+      FT_FRAME_USHORT_LE( pixel_width ),
+      FT_FRAME_USHORT_LE( pixel_height ),
+      FT_FRAME_BYTE     ( pitch_and_family ),
+      FT_FRAME_USHORT_LE( avg_width ),
+      FT_FRAME_USHORT_LE( max_width ),
+      FT_FRAME_BYTE     ( first_char ),
+      FT_FRAME_BYTE     ( last_char ),
+      FT_FRAME_BYTE     ( default_char ),
+      FT_FRAME_BYTE     ( break_char ),
+      FT_FRAME_USHORT_LE( bytes_per_row ),
+      FT_FRAME_ULONG_LE ( device_offset ),
+      FT_FRAME_ULONG_LE ( face_name_offset ),
+      FT_FRAME_ULONG_LE ( bits_pointer ),
+      FT_FRAME_ULONG_LE ( bits_offset ),
+      FT_FRAME_BYTE     ( reserved ),
+      FT_FRAME_ULONG_LE ( flags ),
+      FT_FRAME_USHORT_LE( A_space ),
+      FT_FRAME_USHORT_LE( B_space ),
+      FT_FRAME_USHORT_LE( C_space ),
+      FT_FRAME_USHORT_LE( color_table_offset ),
+      FT_FRAME_BYTES    ( reserved, 4 ),
+    FT_FRAME_END
+  };
+
+
+  static void
+  fnt_font_done( FNT_Font*  font,
+                 FT_Stream  stream )
+  {
+    if ( font->fnt_frame )
+      RELEASE_Frame( font->fnt_frame );
+
+    font->fnt_size  = 0;
+    font->fnt_frame = 0;
+  }
+
+
+  static FT_Error
+  fnt_font_load( FNT_Font*  font,
+                 FT_Stream  stream )
+  {
+    FT_Error        error;
+    WinFNT_Header*  header = &font->header;
+
+
+    /* first of all, read the FNT header */
+    if ( FILE_Seek( font->offset )                   ||
+         READ_Fields( winfnt_header_fields, header ) )
+      goto Exit;
+
+    /* check header */
+    if ( header->version != 0x200 &&
+         header->version != 0x300 )
+    {
+      FT_TRACE2(( "[not a valid FNT file]\n" ));
+      error = FNT_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    if ( header->file_type & 1 )
+    {
+      FT_TRACE2(( "[can't handle vector FNT fonts]\n" ));
+      error = FNT_Err_Unknown_File_Format;
+      goto Exit;
+    }
+
+    /* small fixup -- some fonts have the `pixel_width' field set to 0 */
+    if ( header->pixel_width == 0 )
+      header->pixel_width = header->pixel_height;
+
+    /* this is a FNT file/table, we now extract its frame */
+    if ( FILE_Seek( font->offset )                           ||
+         EXTRACT_Frame( header->file_size, font->fnt_frame ) )
+      goto Exit;
+
+  Exit:
+    return error;
+  }
+
+
+  static void
+  fnt_face_done_fonts( FNT_Face  face )
+  {
+    FT_Memory  memory = FT_FACE(face)->memory;
+    FT_Stream  stream = FT_FACE(face)->stream;
+    FNT_Font*  cur    = face->fonts;
+    FNT_Font*  limit  = cur + face->num_fonts;
+
+
+    for ( ; cur < limit; cur++ )
+      fnt_font_done( cur, stream );
+
+    FREE( face->fonts );
+    face->num_fonts = 0;
+  }
+
+
+  static FT_Error
+  fnt_face_get_dll_fonts( FNT_Face  face )
+  {
+    FT_Error      error;
+    FT_Stream     stream = FT_FACE(face)->stream;
+    FT_Memory     memory = FT_FACE(face)->memory;
+    WinMZ_Header  mz_header;
+
+
+    face->fonts     = 0;
+    face->num_fonts = 0;
+
+    /* does it begin with a MZ header? */
+    if ( FILE_Seek( 0 )                                 ||
+         READ_Fields( winmz_header_fields, &mz_header ) )
+      goto Exit;
+
+    error = FNT_Err_Unknown_File_Format;
+    if ( mz_header.magic == WINFNT_MZ_MAGIC )
+    {
+      /* yes, now look for a NE header in the file */
+      WinNE_Header  ne_header;
+
+
+      if ( FILE_Seek( mz_header.lfanew )                  ||
+           READ_Fields( winne_header_fields, &ne_header ) )
+        goto Exit;
+
+      error = FNT_Err_Unknown_File_Format;
+      if ( ne_header.magic == WINFNT_NE_MAGIC )
+      {
+        /* good, now look in the resource table for each FNT resource */
+        FT_ULong   res_offset = mz_header.lfanew +
+                                ne_header.resource_tab_offset;
+
+        FT_UShort  size_shift;
+        FT_UShort  font_count  = 0;
+        FT_ULong   font_offset = 0;
+
+
+        if ( FILE_Seek( res_offset ) ||
+             ACCESS_Frame( ne_header.rname_tab_offset -
+                           ne_header.resource_tab_offset ) )
+          goto Exit;
+
+        size_shift = GET_UShortLE();
+
+        for (;;)
+        {
+          FT_UShort  type_id, count;
+
+
+          type_id = GET_UShortLE();
+          if ( !type_id )
+            break;
+
+          count = GET_UShortLE();
+
+          if ( type_id == 0x8008 )
+          {
+            font_count  = count;
+            font_offset = (FT_ULong)( FILE_Pos() + 4 +
+                                      ( stream->cursor - stream->limit ) );
+            break;
+          }
+
+          stream->cursor += 4 + count * 12;
+        }
+        FORGET_Frame();
+
+        if ( !font_count || !font_offset )
+        {
+          FT_TRACE2(( "this file doesn't contain any FNT resources!\n" ));
+          error = FNT_Err_Unknown_File_Format;
+          goto Exit;
+        }
+
+        if ( FILE_Seek( font_offset )                         ||
+             ALLOC_ARRAY( face->fonts, font_count, FNT_Font ) )
+          goto Exit;
+
+        face->num_fonts = font_count;
+
+        if ( ACCESS_Frame( (FT_Long)font_count * 12 ) )
+          goto Exit;
+
+        /* now read the offset and position of each FNT font */
+        {
+          FNT_Font*  cur   = face->fonts;
+          FNT_Font*  limit = cur + font_count;
+
+
+          for ( ; cur < limit; cur++ )
+          {
+            cur->offset     = (FT_ULong)GET_UShortLE() << size_shift;
+            cur->fnt_size   = (FT_ULong)GET_UShortLE() << size_shift;
+            cur->size_shift = size_shift;
+            stream->cursor += 8;
+          }
+        }
+        FORGET_Frame();
+
+        /* finally, try to load each font there */
+        {
+          FNT_Font*  cur   = face->fonts;
+          FNT_Font*  limit = cur + font_count;
+
+
+          for ( ; cur < limit; cur++ )
+          {
+            error = fnt_font_load( cur, stream );
+            if ( error )
+              goto Fail;
+          }
+        }
+      }
+    }
+
+  Fail:
+    if ( error )
+      fnt_face_done_fonts( face );
+
+  Exit:
+    return error;
+  }
+
+
+  static void
+  FNT_Face_Done( FNT_Face  face )
+  {
+    FT_Memory  memory = FT_FACE_MEMORY( face );
+
+
+    fnt_face_done_fonts( face );
+
+    FREE( face->root.available_sizes );
+    face->root.num_fixed_sizes = 0;
+  }
+
+
+  static FT_Error
+  FNT_Face_Init( FT_Stream      stream,
+                 FNT_Face       face,
+                 FT_Int         face_index,
+                 FT_Int         num_params,
+                 FT_Parameter*  params )
+  {
+    FT_Error   error;
+    FT_Memory  memory = FT_FACE_MEMORY( face );
+
+    FT_UNUSED( num_params );
+    FT_UNUSED( params );
+    FT_UNUSED( face_index );
+
+
+    /* try to load several fonts from a DLL */
+    error = fnt_face_get_dll_fonts( face );
+    if ( error )
+    {
+      /* this didn't work, now try to load a single FNT font */
+      FNT_Font*  font;
+
+      if ( ALLOC( face->fonts, sizeof ( *face->fonts ) ) )
+        goto Exit;
+
+      face->num_fonts = 1;
+      font            = face->fonts;
+
+      font->offset   = 0;
+      font->fnt_size = stream->size;
+
+      error = fnt_font_load( font, stream );
+      if ( error )
+        goto Fail;
+    }
+
+    /* all right, one or more fonts were loaded; we now need to */
+    /* fill the root FT_Face fields with relevant information   */
+    {
+      FT_Face    root  = FT_FACE( face );
+      FNT_Font*  fonts = face->fonts;
+      FNT_Font*  limit = fonts + face->num_fonts;
+      FNT_Font*  cur;
+
+
+      root->num_faces  = 1;
+      root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
+                         FT_FACE_FLAG_HORIZONTAL;
+
+      if ( fonts->header.avg_width == fonts->header.max_width )
+        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+      if ( fonts->header.italic )
+        root->style_flags |= FT_STYLE_FLAG_ITALIC;
+
+      if ( fonts->header.weight >= 800 )
+        root->style_flags |= FT_STYLE_FLAG_BOLD;
+
+      /* Setup the `fixed_sizes' array */
+      if ( ALLOC_ARRAY( root->available_sizes, face->num_fonts,
+                        FT_Bitmap_Size ) )
+        goto Fail;
+
+      root->num_fixed_sizes = face->num_fonts;
+
+      {
+        FT_Bitmap_Size*  size = root->available_sizes;
+
+
+        for ( cur = fonts; cur < limit; cur++, size++ )
+        {
+          size->width  = cur->header.pixel_width;
+          size->height = cur->header.pixel_height;
+        }
+      }
+
+      /* Setup the `charmaps' array */
+      root->charmaps     = &face->charmap_handle;
+      root->num_charmaps = 1;
+
+      face->charmap.encoding    = ft_encoding_unicode;
+      face->charmap.platform_id = 3;
+      face->charmap.encoding_id = 1;
+      face->charmap.face        = root;
+
+      face->charmap_handle = &face->charmap;
+
+      root->charmap = face->charmap_handle;
+
+      /* setup remaining flags */
+      root->num_glyphs = fonts->header.last_char -
+                         fonts->header.first_char + 1;
+
+      root->family_name = (FT_String*)fonts->fnt_frame +
+                          fonts->header.face_name_offset;
+      root->style_name  = (char *)"Regular";
+
+      if ( root->style_flags & FT_STYLE_FLAG_BOLD )
+      {
+        if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
+          root->style_name = (char *)"Bold Italic";
+        else
+          root->style_name = (char *)"Bold";
+      }
+      else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
+        root->style_name = (char *)"Italic";
+    }
+
+  Fail:
+    if ( error )
+      FNT_Face_Done( face );
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_Error
+  FNT_Size_Set_Pixels( FNT_Size  size )
+  {
+    /* look up a font corresponding to the current pixel size */
+    FNT_Face   face  = (FNT_Face)FT_SIZE_FACE( size );
+    FNT_Font*  cur   = face->fonts;
+    FNT_Font*  limit = cur + face->num_fonts;
+
+
+    size->font = 0;
+    for ( ; cur < limit; cur++ )
+    {
+      /* we only compare the character height, as fonts used some strange */
+      /* values                                                           */
+      if ( cur->header.pixel_height == size->root.metrics.y_ppem )
+      {
+        size->font = cur;
+
+        size->root.metrics.ascender  = cur->header.ascent * 64;
+        size->root.metrics.descender = ( cur->header.pixel_height -
+                                           cur->header.ascent ) * 64;
+        size->root.metrics.height    = cur->header.pixel_height * 64;
+        break;
+      }
+    }
+
+    return ( size->font ? FNT_Err_Ok : FNT_Err_Invalid_Pixel_Size );
+  }
+
+
+  static FT_UInt
+  FNT_Get_Char_Index( FT_CharMap  charmap,
+                      FT_Long     char_code )
+  {
+    FT_Long  result = char_code;
+
+
+    if ( charmap )
+    {
+      FNT_Font*  font  = ((FNT_Face)charmap->face)->fonts;
+      FT_Long    first = font->header.first_char;
+      FT_Long    count = font->header.last_char - first + 1;
+
+
+      char_code -= first;
+      if ( char_code < count )
+        result = char_code + 1;
+      else
+        result = 0;
+    }
+
+    return result;
+  }
+
+
+  static FT_Error
+  FNT_Load_Glyph( FT_GlyphSlot  slot,
+                  FNT_Size      size,
+                  FT_UInt       glyph_index,
+                  FT_Int        load_flags )
+  {
+    FNT_Font*   font  = size->font;
+    FT_Error    error = 0;
+    FT_Byte*    p;
+    FT_Int      len;
+    FT_Bitmap*  bitmap = &slot->bitmap;
+    FT_ULong    offset;
+    FT_Bool     new_format;
+
+    FT_UNUSED( slot );
+    FT_UNUSED( load_flags );
+
+
+    if ( !font )
+    {
+      error = FNT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
+    if ( glyph_index > 0 )
+      glyph_index--;
+    else
+      glyph_index = font->header.default_char - font->header.first_char;
+
+    new_format = FT_BOOL( font->header.version == 0x300 );
+    len        = new_format ? 6 : 4;
+
+    /* jump to glyph entry */
+    p = font->fnt_frame + 118 + len * glyph_index;
+
+    bitmap->width = NEXT_ShortLE(p);
+
+    if ( new_format )
+      offset = NEXT_ULongLE(p);
+    else
+      offset = NEXT_UShortLE(p);
+
+    /* jump to glyph data */
+    p = font->fnt_frame + /* font->header.bits_offset */ + offset;
+
+    /* allocate and build bitmap */
+    {
+      FT_Memory  memory = FT_FACE_MEMORY( slot->face );
+      FT_Int     pitch  = ( bitmap->width + 7 ) >> 3;
+      FT_Byte*   column;
+      FT_Byte*   write;
+
+
+      bitmap->pitch      = pitch;
+      bitmap->rows       = font->header.pixel_height;
+      bitmap->pixel_mode = ft_pixel_mode_mono;
+
+      if ( ALLOC( bitmap->buffer, pitch * bitmap->rows ) )
+        goto Exit;
+
+      column = (FT_Byte*)bitmap->buffer;
+
+      for ( ; pitch > 0; pitch--, column++ )
+      {
+        FT_Byte*  limit = p + bitmap->rows;
+
+
+        for ( write = column; p < limit; p++, write += bitmap->pitch )
+          write[0] = p[0];
+      }
+    }
+
+    slot->flags       = ft_glyph_own_bitmap;
+    slot->bitmap_left = 0;
+    slot->bitmap_top  = font->header.ascent;
+    slot->format      = ft_glyph_format_bitmap;
+
+    /* now set up metrics */
+    slot->metrics.horiAdvance  = bitmap->width << 6;
+    slot->metrics.horiBearingX = 0;
+    slot->metrics.horiBearingY = slot->bitmap_top << 6;
+
+    slot->linearHoriAdvance    = (FT_Fixed)bitmap->width << 16;
+    slot->format               = ft_glyph_format_bitmap;
+
+  Exit:
+    return error;
+  }
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FT_Driver_Class  winfnt_driver_class =
+  {
+    {
+      ft_module_font_driver,
+      sizeof ( FT_DriverRec ),
+
+      "winfonts",
+      0x10000L,
+      0x20000L,
+
+      0,
+
+      (FT_Module_Constructor)0,
+      (FT_Module_Destructor) 0,
+      (FT_Module_Requester)  0
+    },
+
+    sizeof( FNT_FaceRec ),
+    sizeof( FNT_SizeRec ),
+    sizeof( FT_GlyphSlotRec ),
+
+    (FTDriver_initFace)     FNT_Face_Init,
+    (FTDriver_doneFace)     FNT_Face_Done,
+    (FTDriver_initSize)     0,
+    (FTDriver_doneSize)     0,
+    (FTDriver_initGlyphSlot)0,
+    (FTDriver_doneGlyphSlot)0,
+
+    (FTDriver_setCharSizes) FNT_Size_Set_Pixels,
+    (FTDriver_setPixelSizes)FNT_Size_Set_Pixels,
+
+    (FTDriver_loadGlyph)    FNT_Load_Glyph,
+    (FTDriver_getCharIndex) FNT_Get_Char_Index,
+
+    (FTDriver_getKerning)   0,
+    (FTDriver_attachFile)   0,
+    (FTDriver_getAdvances)  0
+  };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    getDriverClass                                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used when compiling the TrueType driver as a      */
+  /*    shared library (`.DLL' or `.so').  It will be used by the          */
+  /*    high-level library of FreeType to retrieve the address of the      */
+  /*    driver's generic interface.                                        */
+  /*                                                                       */
+  /*    It shouldn't be implemented in a static build, as each driver must */
+  /*    have the same function as an exported entry point.                 */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    The address of the TrueType's driver generic interface.  The       */
+  /*    format-specific interface can then be retrieved through the method */
+  /*    interface->get_format_interface.                                   */
+  /*                                                                       */
+  FT_EXPORT_DEF( const FT_Driver_Class* )
+  getDriverClass( void )
+  {
+    return &winfnt_driver_class;
+  }
+
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
diff --git a/libraries/libart_lgpl-2.3.7/AUTHORS b/libraries/libart_lgpl-2.3.7/AUTHORS
new file mode 100644 (file)
index 0000000..fbb51b3
--- /dev/null
@@ -0,0 +1 @@
+Raph Levien <raph@acm.org>
diff --git a/libraries/libart_lgpl-2.3.7/COPYING b/libraries/libart_lgpl-2.3.7/COPYING
new file mode 100644 (file)
index 0000000..bf50f20
--- /dev/null
@@ -0,0 +1,482 @@
+                 GNU LIBRARY GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+                   59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+                 GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the 
+    Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
+    Boston, MA  02111-1307  USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/libraries/libart_lgpl-2.3.7/ChangeLog b/libraries/libart_lgpl-2.3.7/ChangeLog
new file mode 100644 (file)
index 0000000..2d7de12
--- /dev/null
@@ -0,0 +1,866 @@
+2001-10-31  Anders Carlsson  <andersca@gnu.org>
+
+       * Release 2.3.7
+
+2001-10-15  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp_intersect.c (art_svp_intersect_horiz): Minor
+       logic fix so that horiz segments successfully cross
+       zero length segments in the active list.
+
+       (art_svp_intersect_test_cross): Flags indicating whether to
+       do add_point (potentially breaking neighbors) to left and
+       to right.
+
+       (art_svp_intersect_insert_cross): Provide ART_BREAK_LEFT and
+       ART_BREAK_RIGHT flags to art_svp_intersect_test_cross,
+       depending on direction of search.
+
+       (art_svp_intersect_advance_cursor): Provide flags (allow
+       both left and right breaking) to test_cross.
+       
+2001-10-15  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp_intersect.c (CHEAP_SANITYCHECK): Added an inexpensive
+       sanitycheck to detect multiple insertions of a segment into the
+       horiz list.
+
+       (art_svp_writer_rewind_add_point): Avoid breaking lines below
+       their bottom point.
+
+       (art_svp_intersect_test_cross): Handle cases correctly where
+       intersection point matches y0 of left or right segment. These _do_
+       happen in real world examples. Also, do add_point on newly
+       inserted intersection point.
+
+2001-10-14  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp_intersect.c (art_svp_intersect_add_point): Fixed
+       rather subtle logic bug that misplaced insertion point
+       when seg argument was NULL.
+
+2001-10-11  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp_render_aa.c (art_svp_render_aa_iter_step): Got rid
+       of qsort of steps, and now keep the step list in sorted order.
+       Further, we combine duplicate steps with the same x value,
+       which bounds the size of the step list to x1 - x0, so we
+       don't need to dynamically resize it. Thanks greatly to
+       Bruce Q. Hammond for the original version of this patch.
+
+2001-10-09  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp_intersect.c (art_svp_intersect_test_cross): Breaks
+       bottom part of line segments in "too close" cases.
+
+2001-10-09  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp_intersect.c (art_svp_writer_rewind_add_point): Fixed
+       bbox computation.
+       (art_svp_intersector): Handle degenerate case where input
+       SVP has 0 segments.
+
+       * art_svp_intersect.h: Moved definition of art_svp_intersector
+       inside #ifdef __cplusplus, so it links properly against C++
+
+2001-10-09  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp_intersect.c (art_svp_intersect_break): Handle
+       case when break y equals sweep line correctly. Also adds
+       first try at winding number sanitychecker, but that makes
+       too many false positives.
+
+2001-10-07  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp.c (EPSILON): Set to zero if new intersector is
+       in use - we want svp's to be in strict sorted order.
+
+       * art_svp_intersect.c (art_svp_intersect_test_cross): Explicitly
+       check that top points are equal, and swap immediately if b is out
+       of order.
+       (art_svp_intersect_horiz): Break segments that intersect
+       horizontal lines. Now passes "two squares with offset" test.
+
+2001-10-05  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp_intersect.c: Major changes to accommodate
+       horizontal lines. Intersections of horizontal lines
+       aren't fully processed, but should work a lot better
+       than before.
+
+       * testart.c: Minor tweaks. testpat now frees memory
+       so it can be run under memprof to detect leaks.
+
+2001-10-03  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp_intersect.c (art_svp_intersect_advance_cursor):
+       Made test_cross for inserted segments common between
+       intersection processing and cursor advance, and also took
+       care of a case that hadn't been handled before. Also added
+       invariant sanitychecker for debugging purposes.
+
+2001-10-02  Raph Levien  <raph@pixel.artofcode.com>
+
+       * art_svp_ops.c: ART_USE_NEW_INTERSECTOR variants of svp
+       ops changed to do shallow free of merged svp.
+
+2001-10-01  Raph Levien  <raph@acm.org>
+
+       * art_svp_intersect.c:
+       * art_svp_intersect.h:
+       * Makefile.am:
+       * art_misc.h:
+       * art_svp_wind.h: First commit of new intersector code. It is
+         turned off by default, but can be enabled by #defining
+         ART_USE_NEW_INTERSECTOR in art_misc.h.
+
+       * art_svp_ops.c: Make svp ops use new intersector if enabled.
+
+       * art_svp_vpath_stroke.c: Make vpath stroking use new intersector
+       if enabled.
+       
+       * testart.c: New test case for intersector.
+
+Wed Sep 26 03:48:13 2001  George Lebl <jirka@5z.com>
+
+       * Release 2.3.6
+
+Wed Sep 26 03:11:40 2001  George Lebl <jirka@5z.com>
+
+       * gen_art_config.c: Fix 64bit issues, cast sizeof return when
+         using %d to print it.
+
+2001-09-13  Havoc Pennington  <hp@redhat.com>
+
+       * Makefile.am: rename library to libart_lgpl_2
+
+       * libart-2.0.pc.in (Cflags): move includes
+
+       * libart-config.in: move includes
+
+       * Makefile.am: delete libartConf.sh, rename libart-config
+       (EXTRA_DIST): don't install m4 files
+       (libart_lgplincdir): move headers
+
+2001-08-03  Michael Meeks  <michael@ximian.com>
+
+       * Version 2.3.5 for the API freeze.
+
+2001-07-12  Darin Adler  <darin@bentspoon.com>
+
+       * art_affine.c: (art_affine_expansion): Fix handling of
+       negative numbers. We ran into this bug a while back when
+       figuring out why librsvg couldn't handle certain svg files.
+
+2001-07-12  Darin Adler  <darin@bentspoon.com>
+
+       * art_misc.h: Change art_expand macro so it's a single
+       statement, using the do while (0) trick, which gets rid
+       of some warnings.
+       * art_pixbuf.c: Add a missing include.
+       * art_vpath_svp.c: (art_vpath_from_svp): Initialize a
+       variable to avoid a compiler warning.
+       * gen_art_config.c: Add a missing include.
+
+2001-03-24  Martin Baulig  <baulig@suse.de>
+
+       Applied the patch from Alexander Larsson which was sitting
+       in gnome-libs/patches/libart.diff since February.
+       [FIXME: Alex, can you please provide a ChangeLog?])
+
+       * art_rgb_a_affine.[ch]: New files.
+
+2001-01-07  Hans Breuer <Hans@Breuer.Org>
+       * art_misc.c : embryonic change to use libart_lgpl on win32
+       * libart.def : new file, exported functions for win32 dll
+       * makefile.msc : handwritten for MSVC compiler
+
+2000-09-30  Martin Baulig  <baulig@suse.de>
+
+       * libart-2.0.pc.in: Provide pkg-config script.
+
+       * configure.in: Create libart-2.0.pc from libart-2.0.pc.in.
+       * Makefile.am (pkgconfig_DATA): Install the libart-2.0.pc
+       script in `$(libdir)/pkgconfig'.
+
+2000-08-15  Raph Levien  <raph@acm.org>
+
+       * art_render.c (art_render_image_solid_negotiate): Only
+       sets ART_IMAGE_SOURCE_CAN_COMPOSITE when a compositing
+       callback is selected. Previously was causing segfaults on
+       non-alpha images. Thanks to Leonard Rosenthol for spotting
+       the bug.
+
+Fri Jun 30 22:56:58 2000  Raph Levien  <raph@acm.org>
+
+       * art_render.c (art_render_composite): Fixed a bug that caused
+       it to ignore the alpha setting. Also art_render_composite_8().
+
+2000-06-01  John Sullivan  <sullivan@eazel.com>
+
+       * art_svp_render_aa.c: (art_svp_render_aa_iter_step):
+       Made it build by correcting struct member name from
+       Raph's previous checkin.
+
+Wed May 31 11:10:58 2000  Raph Levien  <raph@acm.org>
+
+       * art_svp_render_aa.c (art_svp_render_aa_iter_step): Updated
+       n_steps_max in iter structure after steps reallocation.
+
+Tue May 30 10:33:13 2000  Raph Levien  <raph@acm.org>
+
+       * art_svp_render_aa.c (art_svp_render_aa_iter_step): Fixed not
+       updating iter->steps when steps gets reallocated.
+
+2000-05-30  Pavel Cisler <pavel@eazel.com>
+
+       * art_rgba.c:
+       Make it build -- fix a broken include.
+
+Tue May 30 00:09:21 2000  Raph Levien  <raph@acm.org>
+
+       * art_render_gradient.c (art_render_gradient_setpix): Fixed
+       an off-by-one loop error.
+
+Mon May 29 15:00:39 2000  Raph Levien  <raph@acm.org>
+
+       * Makefile.am: Moved relevant .h files into HEADERS stanza.
+
+Mon May 29 13:48:49 2000  Raph Levien  <raph@acm.org>
+
+       This is a fairly major commit, as it adds both the new, modular
+       rendering architecture and gradients. Quite a bit of the code
+       feels like "reference code" now, in that it is (hopefully)
+       correct, but not necessarily very fast. In addition, there remain
+       a few things not done, including the use of SVP's as non-driver
+       mask sources. AlphaGamma and filter level also remain
+       unimplemented. No compositing modes other than ART_NORMAL are
+       implemented. All in good time!
+       
+       * configure.in: added -Wmissing-prototypes flag. Bumped version
+       number to 2.3.0.
+
+       * art_render.h:
+       * art_render.c: Added new rendering architecture.
+
+       * art_render_svp.h:
+       * art_render_svp.c: Added renderers to use SVP's as mask
+       sources in new rendering architecture.
+
+       * art_render_gradient.h:
+       * art_render_gradient.c: Added linear and radial gradients
+       as image sources in new rendering architecture.
+
+       * art_rgba.h:
+       * art_rgba.c: Added functions for manipulating and compositing
+       RGBA pixels.
+
+       * art_svp_wind.c: Added static to trap_epsilon(), #ifdef'd out
+       traverse().
+
+       * art_uta_ops.c: Added #include "art_uta_ops.h".
+
+       * art_uta_rect.c: Added #include "art_uta_rect.h".
+
+       * art_uta_svp.h: fixed __ART_UTA_SVP_H__ name.
+
+       * art_misc.h: Added ART_GNUC_NORETURN attribute, added that
+       to the prototype for art_die(). Added "static" to function
+       declarations to avoid warnings when compiled with
+
+       * testart.c: Added gradient test.
+
+Thu May 25 23:30:39 2000  Raph Levien  <raph@acm.org>
+
+       * art_svp_render_aa.h:
+       * art_svp_render_aa.c: Added art_svp_render_aa_iter functions,
+       suitable for iterative rendering of an svp, one scan line at a
+       time.
+
+       * configure.in: Bumped version to 2.2.0.
+
+Tue May 16 15:03:35 2000  Raph Levien  <raph@acm.org>
+
+       * art_rgb_pixbuf_affine.c: Included corresponding .h file.
+
+       * art_rgb_pixbuf_affine.h: Put recursive #includes inside
+       LIBART_COMPILATION test.
+
+       * art_gray_svp.c:
+       * art_rgb_svp.c: Explicit casts for callback data. Also removed
+       "render the steps into tmpbuf" comment.
+
+       * gen_art_config.c:
+       * Makefile.am:
+       * configure.in: Added code to automatically generate an
+       art_config.h file, to be installed in libart's include dir. This
+       file defines ART_SIZEOF_{CHAR,SHORT,INT,LONG} and art_u{8,16,32}.
+
+       * art_misc.h: Moved definition of art_u8 and art_u32 into
+       art_config.h. Added GCC printf format attributes.
+
+       * art_svp_wind.c (traverse): Fixed UMR bug here. The function
+       isn't actually used, so it's just for cleanliness.
+
+2000-04-18  Lauris Kaplinski  <lauris@ariman.ee>
+
+       * art_affine.c (art_affine_to_string): Replaced snprinf with
+       art_ftoa to avoid localisation of generated numbers
+
+2000-04-18  ERDI Gergo  <cactus@cactus.rulez.org>
+
+       * art_rgb_pixbuf_affine.h: Included the ArtPixBuf declaration
+
+Fri Apr 14 16:33:55 2000  Raph Levien  <raph@acm.org>
+
+       * art_svp_wind.c (art_svp_uncross, art_svp_rewind_uncrossed):
+       Fixed uninitialized memory reads when inserting new segment into
+       active_segs.
+
+       * art_bpath.c (art_bpath_affine_transform): Made it avoid
+       potential uninitialized memory reads when not all the coordinates
+       are needed. Thanks to Morten Welinder for spotting both of these
+       problems.
+
+2000-04-05  Raph Levien  <raph@gimp.org>
+
+       * art_svp_wind.c: Make "colinear" warnings go to stderr instead
+       of stdout. Of course, when I finish the new intersector, these
+       will go away entirely.
+
+2000-04-04  Raph Levien  <raph@gimp.org>
+
+       * art_uta_vpath.c (art_uta_add_line): Fixed bug that was causing
+       segfaults on alphas. Thanks to msw for localizing it.
+
+2000-01-17  Raph Levien  <raph@gimp.org>
+
+       * art_svp_vpath_stroke.c (art_svp_vpath_stroke): Typo in api
+       header (thanks rak).
+
+2000-01-16  Timur Bakeyev  <timur@gnu.org>
+
+       * autoconf.sh: Instead of jumping between srdir and builddir just process
+       all the auto* staff in srcdir. In fact, just saying the same things in 
+       other words.
+
+2000-01-10  Elliot Lee  <sopwith@redhat.com>
+
+       * Makefile.am, *.h: Add rather bad hacks to the header files to allow compilation
+
+       * Makefile.am: Distribute libart-config.in
+
+2000-01-09  Raph Levien  <raph@gimp.org>
+
+       art_rgb_pixbuf_affine.c, art_rgb_rgba_affine.c, art_rgb_svp.c,
+       art_svp.c, art_svp_ops.c, art_svp_point.c, art_svp_render_aa.c,
+       art_svp_vpath.c, art_svp_vpath_stroke.c, art_svp_wind.c,
+       art_uta.c, art_uta_ops.c, art_uta_rect.c, art_uta_svp.c,
+       art_uta_vpath.c, art_vpath.c, art_vpath_bpath.c, art_vpath_dash.c,
+       art_vpath_svp.c: Added API documentation.
+
+Fri Sep 24 17:53:21 1999  Raph Levien  <raph@acm.org>
+
+       * art_svp_render_aa.c (art_svp_render_insert_active): Avoid
+       reading undefined memory (thanks to Morten Welinder).
+
+1999-09-19  Raph Levien  <raph@gimp.org>
+
+       * art_pixbuf.c (art_pixbuf_duplicate): Added a duplicate function
+       at the request of Michael Meeks.
+
+1999-09-11  Raph Levien  <raph@gimp.org>
+
+       * art_affine.c (art_affine_to_string): Tightened the predicate for
+       matching rotate-only affines, which was too weak. Thanks to lewing
+       for spotting it!
+
+1999-09-01  Raph Levien  <raph@gimp.org>
+
+       * art_affine.c, art_alphagamma.c, art_bpath.c, art_gray_svp.c,
+       art_misc.c, art_pixbuf.c, art_rect.c, art_rect_svp.c,
+       art_rect_uta.c, art_rgb.c, art_rgb_affine.c,
+       art_rgb_bitmap_affine.c: Updates to api doc headers.
+
+1999-08-24  Raph Levien  <raph@gimp.org>
+
+       * art_affine.c, art_alphagamma.c, art_alphagamma.h, art_bpath.c,
+       art_bpath.h, art_gray_svp.c, art_misc.c, art_pixbuf.c,
+       art_pixbuf.h, art_point.h, art_rect.c, art_rect.h: Added api
+       documentation headers.
+
+       * testart.c: Added "dash" test, for testing the vpath_dash
+       functions.
+
+       * art_rgb_pixbuf_affine.h: Fixed the #ifdef for conditional
+       inclusion. Thanks to Kristian Hogsberg Kristensen for spotting
+       the bug.
+
+1999-08-24  Raph Levien  <raph@gimp.org>
+
+       * art_svp_render_aa.c (art_svp_render_aa): Added some tests to
+       avoid NaN for infinite slopes, which were causing problems on
+       Alphas. Closes bug #1966.
+
+1999-08-20  Federico Mena Quintero  <federico@redhat.com>
+
+       * configure.in: Fixed library's libtool version number.
+
+1999-08-03  Larry Ewing  <lewing@gimp.org>
+
+       * art_vpath_dash.c (art_vpath_dash): fix a bug/typo that was causing
+       certain paths to loop infinitely.
+
+1999-07-28  Raph Levien  <raph@gimp.org>
+
+       * art_vpath_dash.[ch]: Added a function to add a dash style
+       to vpaths. It is tested, but has a couple of rough edges (see
+       code for details).
+
+       * testart.c: added tests for the new vpath_dash functionality.
+
+       * Makefile.am: added art_vpath_dash.[ch] files.
+
+1999-07-26  Raph Levien  <raph@gimp.org>
+
+       * art_rgb.c (art_rgb_fill_run): fixed incorrect test for
+       big-endianness. Thanks to Michael Zucchi for spotting it.
+
+Fri Jul 16 23:42:59 1999  Tim Janik  <timj@gtk.org>
+
+       * art_affine.c (art_affine_flip): flip translation matrixes as well, by
+       inverting matrix[4] if (horz) and inverting matrix[5] if (vert).
+
+Fri Jul 16 23:03:26 1999  Tim Janik  <timj@gtk.org>
+
+       * art_pixbuf.[hc]: deprecated art_pixbuf_free_shallow(), people should
+       always free pixbufs with art_pixbuf_free() and use the _dnotify variants
+       for specific destruction behaviour.
+       added art_pixbuf_new_rgb_dnotify() and art_pixbuf_new_rgba_dnotify()
+       which allow for a destruction notification function. (this involved
+       adding two extra pointers to the ArtPixBuf structure, and removal of
+       the recently introduced int flags field).
+
+Mon Jul 12 01:13:23 1999  Tim Janik  <timj@gtk.org>
+
+       * art_affine.[hc]: added art_affine_equal(), which checks two
+       matrixes for equality within grid alignment.
+
+Fri Jul  9 17:50:19 1999  Tim Janik  <timj@gtk.org>
+
+       * art_affine.[hc]: added art_affine_flip() to flip a matrix horizontally
+       and/or vertically, or just copy it.
+       added art_affine_shear() to setup a shearing matrix.
+
+Tue Jul  6 19:03:39 1999  Tim Janik  <timj@gtk.org>
+
+       * art_pixbuf.h: added an int flags; member to the end of the
+       structure, it currently only holds information about whether the
+       pixels member should be freed. (raph: i think flags is more generic
+       than free_pixels, so we can reuse that field if further demands popup
+       in the future).
+
+       * art_pixbuf.c:
+       (art_pixbuf_new_const_rgba):
+       (art_pixbuf_new_const_rgb): new functions that prevent the pixels
+       member from being freed upon art_pixbuf_free ().
+       (art_pixbuf_free): only free the pixels member if it is non-NULL and
+       the PIXBUF_FLAG_DESTROY_PIXELS is set.
+
+1999-07-02  Raph Levien  <raph@gimp.org>
+
+       * art_vpath_bpath.c (art_vpath_render_bez): Bad bad uninitialized
+       variables.
+
+       * configure.in: added compile warnings. Guess why :)
+
+1999-06-28  Raph Levien  <raph@gimp.org>
+
+       * art_svp_point.h:
+       * art_svp_point.c: Added methods for insideness and distance
+       testing, very useful for ::point methods in canvas items.
+
+       * testart.c: test code to exercise the art_svp_point functions.
+
+       * Makefile.am: Additional entries for art_svp_point.
+
+1999-06-28  Raph Levien  <raph@gimp.org>
+
+       * art_svp_render_aa.c (art_svp_render_aa): Subtle boundary
+       case in realloc code -- was causing nasty segfaults.
+
+Wed Jun 23 15:05:43 1999  Raph Levien  <raph@gimp.org>
+
+       * art_rgb_svp.c (art_rgb_svp_alpha_opaque_callback): Missed a
+       case in the anti-segfault crusade. Thanks lewing!
+
+Wed Jun 23 11:16:42 1999  Raph Levien  <raph@gimp.org>
+
+       * art_rgb_svp.c: Made these routines so they won't segfault even
+       if alpha is out of range. Of course, that begs the question of
+       fixing the render routines so they won't _make_ alpha go out of
+       range, but all in good time.
+
+Fri Jun 18 17:32:34 1999  Raph Levien  <raph@acm.org>
+
+       * art_vpath_bpath.c (art_bez_path_to_vec): Switched to a new
+       adaptive subdivision algorithm, which (finally!) takes flatness
+       into account. This should result in both smoother curves and
+       faster operation.
+
+Sun Jun 13 21:07:20 1999  Raph Levien  <raph@gimp.org>
+
+       * art_svp_wind.c (art_svp_rewind_uncrossed): Made the winding
+       rule logic even more correct :). I somehow missed the fact that
+       a clockwise path should be given a winding number of zero;
+       last night's commit tried to make it -1 (which worked for the
+       test cases I was using).
+
+Sun Jun 13 01:23:14 1999  Raph Levien  <raph@gimp.org>
+
+       * art_svp_wind.c (art_svp_rewind_uncrossed): Change to winding
+       rule logic so that it correctly handles the case where the
+       leftmost segment is negative.
+
+       * Makefile.am (libart_lgplinc_HEADERS): made art_svp_wind.h
+       a public headerfile. This is needed for the bpath canvas item.
+       I'm not sure this is the correct way to do it, but it will do
+       for now.
+
+       * art_vpath_bpath.h: 
+       * art_vpath_bpath.c (art_bez_path_to_vec): Added const to arg.
+
+       * art_vpath_bpath.h: Embarrassing typo.
+
+       * art_bpath.h: Minor tweaks to the #include paths. It is now
+       consistent with the other header files.
+
+Wed Jun  9 20:24:45 1999  Raph Levien  <raph@gimp.org>
+
+       * art_svp_vpath_stroke.c: Added all remaining line join and cap
+       types, including round, which takes flatness into account. Several
+       new internal functions (art_svp_vpath_stroke_arc) and added
+       flatness argument to a few internal functions. I might want to
+       change the BEVEL join type to MITER for very small turn angles
+       (i.e. within a flatness threshold) for efficiency.
+
+       * art_misc.h: Added M_SQRT2 constant.
+
+Wed Jun  2 21:56:30 1999  Raph Levien  <raph@gimp.org>
+
+       * art_svp_vpath_stroke.c (art_svp_vpath_stroke_raw): Made the
+       closed path detection capable of PostScript semantics (i.e. it
+       now senses the difference between ART_MOVETO and ART_MOVETO_OPEN).
+
+       * art_svp_vpath_stroke.c (art_svp_vpath_stroke_raw): it now
+       filters out successive points that are (nearly) coincident. This
+       fixes some of the crashes and hangs, including Tim Janik's
+       singularity (trying to stroke MOVETO 50, 50; LINETO 50, 50; END).
+
+       * art_svp_wind.c (art_svp_rewind_uncrossed): added a test to
+       correctly handle empty input svp's.
+
+       * art_svp_wind.c (art_svp_uncross): added a test to correctly
+       handle empty input svp's.
+
+Sun Jan 17 20:53:40 1999  Jeff Garzik  <jgarzik@pobox.com>
+
+       * art_affine.c:
+       Include string.h for memcpy.
+
+       * art_svp_vpath.c:
+       Remove conflicting static func definition.
+
+       * art_uta_svp.c:
+       Include art_vpath_svp.h for func definition.
+
+Mon Jan  4 12:47:47 1999  Raph Levien  <raph@acm.org>
+
+       * art_bpath.c (art_bpath_affine_transform): Stupid misnaming
+       of this function (forgot the "art_").
+
+Thu Dec 31 09:04:23 1998  Raph Levien  <raph@gimp.org>
+
+       * art_affine.c (art_affine_rectilinear): Added this function.
+
+       * art_rect.c (art_drect_affine_transform): Corrected the name (it
+       was right in the .h). Also made it work with non-rectilinear
+       transforms, while I was at it.
+
+Thu Dec 17 11:58:24 1998  Raph Levien  <raph@acm.org>
+
+       * art_alphagamma.h:
+       * art_alphagamma.c: The real code for alphagamma.
+
+Wed Dec 16 14:18:46 1998  Raph Levien  <raph@gimp.org>
+
+       * art_alphagamma.h:
+       * art_alphagamma.c: Added. At present, it only contains a dummy
+       stub. When the real code is added, it supports doing alpha
+       compositing in a gamma-corrected color space (suppressing
+       jaggies).
+
+       * art_pixbuf.h:
+       * art_pixbuf.c: Added. This is a virtualization layer over
+       a few different kinds of image formats.
+
+       * art_rgb_pixbuf_affine.h:
+       * art_rgb_pixbuf_affine.c: Added. Supports compositing of
+       generic images over an rgb buffer.
+
+       * art_affine.h: 
+       * art_affine.c (art_affine_expansion): Added this function,
+       which reports the exact scale factor in the case of rotation,
+       scaling, and transformation (an approximate number in the
+       case of shearing or anamorphic distortion).
+
+       * art_misc.h:
+       * art_misc.c (art_warn): Added.
+
+       * art_rgb_affine.h:
+       * art_rgb_affine.c: Added alphagamma argument (not yet implemented).
+
+       * art_rgb_affine_private.c: Fixed typo bug that was causing
+       repaint problems for nonsquare images.
+
+       * art_rgb_bitmap_affine.h:
+       * art_rgb_bitmap_affine.c: Major speed improvement, probably fixed
+       correctness while I was at it. Added alphagamma argument (not yet
+       implemented).
+
+       * art_rgb_svp.h:
+       * art_rgb_svp.c: Added alphagamma argument (only implemented
+       in aa case, not yet alpha case).
+
+       * art_vpath.c: increased perturbation to 2e-3, because the old
+       value (1e-6) was too small.
+
+       * testart.c: added alphagamma.
+       
+       * Makefile.am: added new files
+
+Sun Dec 27 21:45:03 1998  Raph Levien  <raph@gimp.org>
+
+       * art_rect.h: 
+       * art_rect.c: Added DRect versions of the basic ops (double
+       rather than int).
+
+       * art_rect_svp.h:
+       * art_rect_svp.c: Added. This computes the bounding box of
+       an svp.
+
+Wed Dec 16 14:18:46 1998  Raph Levien  <raph@gimp.org>
+
+       * art_alphagamma.h:
+       * art_alphagamma.c: Added. At present, it only contains a dummy
+       stub. When the real code is added, it supports doing alpha
+       compositing in a gamma-corrected color space (suppressing
+       jaggies).
+
+       * art_pixbuf.h:
+       * art_pixbuf.c: Added. This is a virtualization layer over
+       a few different kinds of image formats.
+
+       * art_rgb_pixbuf_affine.h:
+       * art_rgb_pixbuf_affine.c: Added. Supports compositing of
+       generic images over an rgb buffer.
+
+       * art_affine.h: 
+       * art_affine.c (art_affine_expansion): Added this function,
+       which reports the exact scale factor in the case of rotation,
+       scaling, and transformation (an approximate number in the
+       case of shearing or anamorphic distortion).
+
+       * art_misc.h:
+       * art_misc.c (art_warn): Added.
+
+       * art_rgb_affine.h:
+       * art_rgb_affine.c: Added alphagamma argument (not yet implemented).
+
+       * art_rgb_affine_private.c: Fixed typo bug that was causing
+       repaint problems for nonsquare images.
+
+       * art_rgb_bitmap_affine.h:
+       * art_rgb_bitmap_affine.c: Major speed improvement, probably fixed
+       correctness while I was at it. Added alphagamma argument (not yet
+       implemented).
+
+       * art_rgb_svp.h:
+       * art_rgb_svp.c: Added alphagamma argument (only implemented
+       in aa case, not yet alpha case).
+
+       * art_vpath.c: increased perturbation to 2e-3, because the old
+       value (1e-6) was too small.
+
+       * testart.c: added alphagamma.
+       
+       * Makefile.am: added new files
+
+Mon Dec 14 00:16:53 1998  Raph Levien  <raph@gimp.org>
+
+       * art_affine.c (art_affine_to_string): re-added the "scale" method
+       that was accidentally deleted before check-in.
+
+       * Makefile.am: added new files
+
+Sun Dec 13 00:52:39 1998  Raph Levien  <raph@gimp.org>
+
+       * art_affine.h:
+       * art_affine.c: Added. Everything you ever wanted to do with an
+       affine transform. Especially check the functions that generate
+       concise PostScript strings for affine transforms.       
+
+       * art_filterlevel.h: A simple enum for selecting filtering
+       style.
+
+       * art_rgb_affine.h:
+       * art_rgb_affine.c (art_rgb_affine): Added. This function
+       composites an (opaque) rgb image over an rgb pixel buffer. At
+       present, it's slow and only nearest neighbor filtering is enabled.
+
+       * art_rgb_rgba_affine.h:
+       * art_rgb_rgba_affine.c: Analogous, but for compositing rgba
+       images.
+
+       * art_rgb_bitmap_affine.h:
+       * art_rgb_bitmap_affine.c: Analogous, but for compositing bitmap
+       images.
+
+       * art_rgb_affine_private.c (art_rgb_affine_run): Added. This is
+       a common function used by all the rgb_affine modules to move
+       testing for source image bbox out of the inner loop.
+
+       * Makefile.am: added the new files
+
+       * testart.c: exercise the image compositors
+
+Wed Dec  9 23:36:35 1998  Raph Levien  <raph@gimp.org>
+
+       * art_vpath.c (art_vpath_perturb): Made it deal correctly
+       with closed paths (the MOVETO and closing LINETO have to
+       agree).
+
+       * art_svp_wind.c: Made the bbox calculations for the resulting
+       svp's correct.
+
+       * art_svp.h:
+       * art_svp.c: The art_svp_seg_compare function moved here, because
+       it's required in art_svp_ops.
+
+       * art_svp.c (art_svp_add_segment): It now does bbox calculations.
+
+       * art_svp_ops.h: 
+       * art_svp_ops.c: Added. Populated with basic union, intersection,
+       and diff functions.
+
+       * art_vpath_svp.h: 
+       * art_vpath_svp.c: Added. Populated with a function to convert
+       from sorted to unsorted vector paths
+
+       * Makefile.am: added the new files
+
+       * testart.c: exercise the stroke outline and vector path
+       operations.
+
+1998-12-08  Herbert Valerio Riedel  <hvr@hvrlab.ml.org>
+
+       * art_svp_wind.c: added #include <string.h> for memcpy()
+
+Sun Dec  6 22:15:12 1998  Raph Levien  <raph@gimp.org>
+
+       * art_svp_wind.[ch], art_svp_vpath_stroke.[ch]: Added, but it
+       doesn't work yet. These will do stroke outline and basic
+       vector ops like union, intersect, etc.
+
+       * art_svp_render_aa.c: Added a simple speedup based on bbox
+       culling. I will want to do more speedups, but none of this is
+       necessary for the freeze.
+
+       * art_svp_vpath.c: Fixed some bugs in the art_svp_from_vpath in
+       cases where there is more than one subpath.
+
+       * art_vpath.h:
+       * art_vpath.c (art_vpath_perturb): Added this function.  This will
+       help cheat as long as the basic vector ops have numerical
+       stability problems.
+
+Fri Dec  4 18:00:38 1998  Raph Levien  <raph@gimp.org>
+
+       * art_svp_render_aa.c (art_svp_render_aa): Changed the api
+       slightly, to guarantee that the steps are all within the range
+       from x0 (inclusive) to x1 (exclusive).
+
+       * art_gray_svp.c, art_gray_svp.h: Added. Populated with functions
+       to render into a simple graymap.
+
+       * art_rgb.c, art_rgb.c: Added. Populated with fill_run and
+       run_alpha methods.
+
+       * art_rgb_svp.c, art_rgb_svp.h: Added. Populated with functions to
+       render into an RGB buffer, and to composite over an RGB buffer.
+
+       * Makefile.am: added art_gray_svp, art_rgb, and art_rgb_svp.
+
+       * testart.c: test the color and layered rendering.
+
+Mon Nov 30 01:30:25 1998  Raph Levien  <raph@gimp.org>
+
+       * testart.c: added vector path rendering stuff. Some of it needs
+       to go out of the test framework and into the module, but the
+       api hasn't settled down entirely yet (in the real code, all
+       x's in the step field are within bounds).
+
+       * art_svp_render_aa.c, art_svp_render_aa.c.h: added.
+
+       * art_svp_vpath.c, art_svp_vpath.h: added.
+
+       * art_pathcode.h: added ART_MOVETO_OPEN (libart uses an
+       ART_MOVETO_OPEN code at the beginning to indicate an open path,
+       while PostScript uses the lack of a closepath at the end).
+
+       * art_vpath_bpath.c, art_vpath_bpath.h: fixed it up, added
+       flatness arg to api.
+
+       * Makefile.am: added new source files.
+
+Wed Nov 25 17:19:44 1998  Raph Levien  <raph@gimp.org>
+
+       * art_svp.h, art_svp.c: added, basic constructors for sorted
+       vector paths.
+
+Sun Nov 22 23:21:09 1998  Raph Levien  <raph@gimp.org>
+
+       * Makefile.am (libart_lgplincdir): Fixed stupid bug in naming of
+       the variable.
+
+Sun Nov 22 21:41:13 1998  Raph Levien  <raph@gimp.org>
+
+       * art_uta_vpath.c: moved art_uta_union into art_uta_ops.
+
+       * art_uta_ops.[ch]: added, populated with art_uta_union.
+
+Thu Nov 19 00:19:40 1998  Raph Levien  <raph@gimp.org>
+
+       * libartConf.sh.in: added
+
+       * Makefile.am: added creation of libartConf.sh, added -version-info
+       * configure.in: added LIBART_VERSION_INFO, support for libartConf.sh
+       
+       * libart.m4: updated version history :)
+
+Wed Nov 18 18:15:20 1998  Raph Levien  <raph@gimp.org>
+
+       * configure.in (LIBART_VERSION): set this, so that libart-config
+       --version now works.
+
+Wed Nov 18 16:50:58 1998  Raph Levien  <raph@gimp.org>
+
+       * libart.m4: added (just copied from esound)
+       * configure.in, Makefile.am: added support for libart-config
+       * libart-config.in: added (mostly copied from esound)
+
+Tue Nov 10 12:43:30 1998  Raph Levien  <raph@acm.org>
+
+       * Getting the library in shape for initial checkin to CVS.
+
+
diff --git a/libraries/libart_lgpl-2.3.7/INSTALL b/libraries/libart_lgpl-2.3.7/INSTALL
new file mode 100644 (file)
index 0000000..b42a17a
--- /dev/null
@@ -0,0 +1,182 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/libraries/libart_lgpl-2.3.7/Makefile b/libraries/libart_lgpl-2.3.7/Makefile
new file mode 100644 (file)
index 0000000..4f21baf
--- /dev/null
@@ -0,0 +1,547 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = ../..
+
+prefix = /usr/local/rrdtool-1.1.0
+exec_prefix = ${prefix}
+
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libexecdir = ${exec_prefix}/libexec
+datadir = ${prefix}/share
+sysconfdir = ${prefix}/etc
+sharedstatedir = ${prefix}/com
+localstatedir = ${prefix}/var
+libdir = ${exec_prefix}/lib
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/rrdtool
+pkglibdir = $(libdir)/rrdtool
+pkgincludedir = $(includedir)/rrdtool
+top_builddir = ../..
+
+ACLOCAL = ${SHELL} /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/missing --run aclocal
+AUTOCONF = ${SHELL} /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/missing --run autoconf
+AUTOMAKE = ${SHELL} /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/missing --run automake
+AUTOHEADER = ${SHELL} /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/missing --run autoheader
+
+INSTALL = /usr/sepp/bin/ginstall -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = s,x,x,
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = 
+host_triplet = sparc-sun-solaris2.8
+AMTAR = ${SHELL} /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/missing --run tar
+ART_LIB_DIR = libraries/libart_lgpl-2.3.7
+AS = @AS@
+AWK = gawk
+CC = gcc
+CGI_LIB_DIR = libraries/cgilib-0.4
+COMP_PERL = perl_piped perl_shared
+CPP = gcc -E
+DEPDIR = .deps
+DLLTOOL = @DLLTOOL@
+ECHO = /usr/ucb/echo
+EXEEXT = 
+FREETYPE_LIB_DIR = libraries/freetype-2.0.5
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LN_S = ln -s
+NROFF = /usr/sepp/bin/gnroff
+OBJDUMP = @OBJDUMP@
+OBJEXT = o
+PACKAGE = rrdtool
+PERL = /usr/bin/perl
+PERLFLAGS = 
+PERL_MAKE_OPTIONS = 
+PNG_LIB_DIR = libraries/libpng-1.2.0
+RANLIB = ranlib
+SO_EXT = so
+STRIP = strip
+TCL_LD_SEARCH_FLAGS = 
+TCL_PACKAGE_PATH = 
+TCL_PREFIX = 
+TCL_SHLIB_CFLAGS = 
+TCL_SHLIB_LD = 
+TCL_SHLIB_SUFFIX = 
+TROFF = /usr/sepp/bin/groff
+VERSION = 1.1.0
+ZLIB_CFLAGS = -g -O2 -Wall -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline  -fPIC
+ZLIB_LIB_DIR = libraries/zlib-1.1.3
+am__include = include
+am__quote = 
+install_sh = /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/install-sh
+
+noinst_LTLIBRARIES = librrd_art.la
+noinst_PROGRAMS = gen_art_config
+
+BUILT_SOURCES = art_config.h
+
+EXTRA_DIST = \
+       libart-config.in        \
+       libart-2.0.pc.in
+
+
+librrd_art_la_SOURCES = \
+       art_affine.c \
+       art_alphagamma.c \
+       art_bpath.c \
+       art_gray_svp.c \
+       art_misc.c \
+       art_pixbuf.c \
+       art_rect.c \
+       art_rect_svp.c \
+       art_rect_uta.c \
+       art_render.c \
+       art_render_gradient.c \
+       art_render_svp.c \
+       art_rgb.c \
+       art_rgb_affine.c \
+       art_rgb_affine_private.c \
+       art_rgb_affine_private.h \
+       art_rgb_bitmap_affine.c \
+       art_rgb_pixbuf_affine.c \
+       art_rgb_rgba_affine.c \
+       art_rgb_a_affine.c \
+       art_rgba.c \
+       art_rgb_svp.c \
+       art_svp.c \
+       art_svp_intersect.c \
+       art_svp_ops.c \
+       art_svp_point.c \
+       art_svp_render_aa.c \
+       art_svp_vpath.c \
+       art_svp_vpath_stroke.c \
+       art_svp_wind.c \
+       art_uta.c \
+       art_uta_ops.c \
+       art_uta_rect.c \
+       art_uta_vpath.c \
+       art_uta_svp.c \
+       art_vpath.c \
+       art_vpath_bpath.c \
+       art_vpath_dash.c \
+       art_vpath_svp.c \
+       libart-features.c
+
+
+librrd_artincdir = $(includedir)/libart-2.0/libart_lgpl
+librrd_artinc_HEADERS = \
+       art_affine.h \
+       art_alphagamma.h \
+       art_bpath.h \
+       art_config.h \
+       art_filterlevel.h \
+       art_gray_svp.h \
+       art_misc.h \
+       art_pathcode.h \
+       art_pixbuf.h \
+       art_point.h \
+       art_rect.h \
+       art_rect_svp.h \
+       art_rect_uta.h \
+       art_render.h \
+       art_render_gradient.h \
+       art_render_svp.h \
+       art_rgb.h \
+       art_rgb_affine.h \
+       art_rgb_bitmap_affine.h \
+       art_rgb_pixbuf_affine.h \
+       art_rgb_rgba_affine.h \
+       art_rgb_a_affine.h \
+       art_rgb_svp.h \
+       art_rgba.h \
+       art_svp.h \
+       art_svp_intersect.h \
+       art_svp_ops.h \
+       art_svp_point.h \
+       art_svp_render_aa.h \
+       art_svp_vpath.h \
+       art_svp_vpath_stroke.h \
+       art_svp_wind.h \
+       art_uta.h \
+       art_uta_ops.h \
+       art_uta_rect.h \
+       art_uta_vpath.h \
+       art_uta_svp.h \
+       art_vpath.h \
+       art_vpath_bpath.h \
+       art_vpath_dash.h \
+       art_vpath_svp.h \
+       libart.h        \
+       libart-features.h
+
+
+INCLUDES = -I$(top_srcdir) -I$(top_builddir) -DLIBART_COMPILATION
+subdir = libraries/libart_lgpl-2.3.7
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+
+librrd_art_la_LDFLAGS =
+librrd_art_la_LIBADD =
+am_librrd_art_la_OBJECTS = art_affine.lo art_alphagamma.lo art_bpath.lo \
+       art_gray_svp.lo art_misc.lo art_pixbuf.lo art_rect.lo \
+       art_rect_svp.lo art_rect_uta.lo art_render.lo \
+       art_render_gradient.lo art_render_svp.lo art_rgb.lo \
+       art_rgb_affine.lo art_rgb_affine_private.lo \
+       art_rgb_bitmap_affine.lo art_rgb_pixbuf_affine.lo \
+       art_rgb_rgba_affine.lo art_rgb_a_affine.lo art_rgba.lo \
+       art_rgb_svp.lo art_svp.lo art_svp_intersect.lo art_svp_ops.lo \
+       art_svp_point.lo art_svp_render_aa.lo art_svp_vpath.lo \
+       art_svp_vpath_stroke.lo art_svp_wind.lo art_uta.lo \
+       art_uta_ops.lo art_uta_rect.lo art_uta_vpath.lo art_uta_svp.lo \
+       art_vpath.lo art_vpath_bpath.lo art_vpath_dash.lo \
+       art_vpath_svp.lo libart-features.lo
+librrd_art_la_OBJECTS = $(am_librrd_art_la_OBJECTS)
+noinst_PROGRAMS = gen_art_config$(EXEEXT)
+PROGRAMS = $(noinst_PROGRAMS)
+
+gen_art_config_SOURCES = gen_art_config.c
+gen_art_config_OBJECTS = gen_art_config.$(OBJEXT)
+gen_art_config_LDADD = $(LDADD)
+gen_art_config_DEPENDENCIES =
+gen_art_config_LDFLAGS =
+
+DEFS = -DHAVE_CONFIG_H
+DEFAULT_INCLUDES =  -I. -I$(srcdir) -I$(top_builddir)/config
+CPPFLAGS = 
+LDFLAGS = 
+LIBS = -lm 
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+DEP_FILES = $(DEPDIR)/art_affine.Plo \
+       $(DEPDIR)/art_alphagamma.Plo \
+       $(DEPDIR)/art_bpath.Plo $(DEPDIR)/art_gray_svp.Plo \
+       $(DEPDIR)/art_misc.Plo $(DEPDIR)/art_pixbuf.Plo \
+       $(DEPDIR)/art_rect.Plo $(DEPDIR)/art_rect_svp.Plo \
+       $(DEPDIR)/art_rect_uta.Plo $(DEPDIR)/art_render.Plo \
+       $(DEPDIR)/art_render_gradient.Plo \
+       $(DEPDIR)/art_render_svp.Plo $(DEPDIR)/art_rgb.Plo \
+       $(DEPDIR)/art_rgb_a_affine.Plo \
+       $(DEPDIR)/art_rgb_affine.Plo \
+       $(DEPDIR)/art_rgb_affine_private.Plo \
+       $(DEPDIR)/art_rgb_bitmap_affine.Plo \
+       $(DEPDIR)/art_rgb_pixbuf_affine.Plo \
+       $(DEPDIR)/art_rgb_rgba_affine.Plo \
+       $(DEPDIR)/art_rgb_svp.Plo $(DEPDIR)/art_rgba.Plo \
+       $(DEPDIR)/art_svp.Plo \
+       $(DEPDIR)/art_svp_intersect.Plo \
+       $(DEPDIR)/art_svp_ops.Plo \
+       $(DEPDIR)/art_svp_point.Plo \
+       $(DEPDIR)/art_svp_render_aa.Plo \
+       $(DEPDIR)/art_svp_vpath.Plo \
+       $(DEPDIR)/art_svp_vpath_stroke.Plo \
+       $(DEPDIR)/art_svp_wind.Plo $(DEPDIR)/art_uta.Plo \
+       $(DEPDIR)/art_uta_ops.Plo \
+       $(DEPDIR)/art_uta_rect.Plo \
+       $(DEPDIR)/art_uta_svp.Plo \
+       $(DEPDIR)/art_uta_vpath.Plo $(DEPDIR)/art_vpath.Plo \
+       $(DEPDIR)/art_vpath_bpath.Plo \
+       $(DEPDIR)/art_vpath_dash.Plo \
+       $(DEPDIR)/art_vpath_svp.Plo \
+       $(DEPDIR)/gen_art_config.Po \
+       $(DEPDIR)/libart-features.Plo
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
+       $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CFLAGS = -g -O2 -Wall -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline  -fPIC
+DIST_SOURCES = $(librrd_art_la_SOURCES) gen_art_config.c
+HEADERS = $(librrd_artinc_HEADERS)
+
+DIST_COMMON = README $(librrd_artinc_HEADERS) AUTHORS COPYING ChangeLog \
+       INSTALL Makefile.am Makefile.in NEWS install-sh missing \
+       mkinstalldirs
+SOURCES = $(librrd_art_la_SOURCES) gen_art_config.c
+
+all: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  libraries/libart_lgpl-2.3.7/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) && \
+         CONFIG_HEADERS= CONFIG_LINKS= \
+         CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+librrd_art.la: $(librrd_art_la_OBJECTS) $(librrd_art_la_DEPENDENCIES) 
+       $(LINK)  $(librrd_art_la_LDFLAGS) $(librrd_art_la_OBJECTS) $(librrd_art_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+       -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+gen_art_config$(EXEEXT): $(gen_art_config_OBJECTS) $(gen_art_config_DEPENDENCIES) 
+       @rm -f gen_art_config$(EXEEXT)
+       $(LINK) $(gen_art_config_LDFLAGS) $(gen_art_config_OBJECTS) $(gen_art_config_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+       -rm -f *.tab.c
+
+include $(DEPDIR)/art_affine.Plo
+include $(DEPDIR)/art_alphagamma.Plo
+include $(DEPDIR)/art_bpath.Plo
+include $(DEPDIR)/art_gray_svp.Plo
+include $(DEPDIR)/art_misc.Plo
+include $(DEPDIR)/art_pixbuf.Plo
+include $(DEPDIR)/art_rect.Plo
+include $(DEPDIR)/art_rect_svp.Plo
+include $(DEPDIR)/art_rect_uta.Plo
+include $(DEPDIR)/art_render.Plo
+include $(DEPDIR)/art_render_gradient.Plo
+include $(DEPDIR)/art_render_svp.Plo
+include $(DEPDIR)/art_rgb.Plo
+include $(DEPDIR)/art_rgb_a_affine.Plo
+include $(DEPDIR)/art_rgb_affine.Plo
+include $(DEPDIR)/art_rgb_affine_private.Plo
+include $(DEPDIR)/art_rgb_bitmap_affine.Plo
+include $(DEPDIR)/art_rgb_pixbuf_affine.Plo
+include $(DEPDIR)/art_rgb_rgba_affine.Plo
+include $(DEPDIR)/art_rgb_svp.Plo
+include $(DEPDIR)/art_rgba.Plo
+include $(DEPDIR)/art_svp.Plo
+include $(DEPDIR)/art_svp_intersect.Plo
+include $(DEPDIR)/art_svp_ops.Plo
+include $(DEPDIR)/art_svp_point.Plo
+include $(DEPDIR)/art_svp_render_aa.Plo
+include $(DEPDIR)/art_svp_vpath.Plo
+include $(DEPDIR)/art_svp_vpath_stroke.Plo
+include $(DEPDIR)/art_svp_wind.Plo
+include $(DEPDIR)/art_uta.Plo
+include $(DEPDIR)/art_uta_ops.Plo
+include $(DEPDIR)/art_uta_rect.Plo
+include $(DEPDIR)/art_uta_svp.Plo
+include $(DEPDIR)/art_uta_vpath.Plo
+include $(DEPDIR)/art_vpath.Plo
+include $(DEPDIR)/art_vpath_bpath.Plo
+include $(DEPDIR)/art_vpath_dash.Plo
+include $(DEPDIR)/art_vpath_svp.Plo
+include $(DEPDIR)/gen_art_config.Po
+include $(DEPDIR)/libart-features.Plo
+
+distclean-depend:
+       -rm -rf $(DEPDIR)
+
+.c.o:
+       source='$<' object='$@' libtool=no \
+       depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \
+       $(CCDEPMODE) $(depcomp) \
+       $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$<
+
+.c.obj:
+       source='$<' object='$@' libtool=no \
+       depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \
+       $(CCDEPMODE) $(depcomp) \
+       $(COMPILE) -c `cygpath -w $<`
+
+.c.lo:
+       source='$<' object='$@' libtool=yes \
+       depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' \
+       $(CCDEPMODE) $(depcomp) \
+       $(LTCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+CCDEPMODE = depmode=gcc
+uninstall-info-am:
+install-librrd_artincHEADERS: $(librrd_artinc_HEADERS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(librrd_artincdir)
+       @list='$(librrd_artinc_HEADERS)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f="`echo $$p | sed -e 's|^.*/||'`"; \
+         echo " $(INSTALL_HEADER) $$d$$p $(DESTDIR)$(librrd_artincdir)/$$f"; \
+         $(INSTALL_HEADER) $$d$$p $(DESTDIR)$(librrd_artincdir)/$$f; \
+       done
+
+uninstall-librrd_artincHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(librrd_artinc_HEADERS)'; for p in $$list; do \
+         f="`echo $$p | sed -e 's|^.*/||'`"; \
+         echo " rm -f $(DESTDIR)$(librrd_artincdir)/$$f"; \
+         rm -f $(DESTDIR)$(librrd_artincdir)/$$f; \
+       done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || etags $(ETAGS_ARGS) $$tags  $$unique $(LISP)
+
+GTAGS:
+       here=`CDPATH=: && cd $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           $(mkinstalldirs) "$(distdir)/$$dir"; \
+         fi; \
+         if test -d $$d/$$file; then \
+           cp -pR $$d/$$file $(distdir) \
+           || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+
+installdirs:
+       $(mkinstalldirs) $(DESTDIR)$(librrd_artincdir)
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+       clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+       distclean-generic distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-librrd_artincHEADERS
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+uninstall-am: uninstall-info-am uninstall-librrd_artincHEADERS
+
+.PHONY: GTAGS all all-am check check-am clean clean-generic \
+       clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+       distclean distclean-compile distclean-depend distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am info \
+       info-am install install-am install-data install-data-am \
+       install-exec install-exec-am install-info install-info-am \
+       install-librrd_artincHEADERS install-man install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool tags uninstall \
+       uninstall-am uninstall-info-am uninstall-librrd_artincHEADERS
+
+
+art_config.h:  gen_art_config
+       ./gen_art_config > art_config.h
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libraries/libart_lgpl-2.3.7/Makefile.am b/libraries/libart_lgpl-2.3.7/Makefile.am
new file mode 100644 (file)
index 0000000..7bb9426
--- /dev/null
@@ -0,0 +1,102 @@
+noinst_LTLIBRARIES  = librrd_art.la
+noinst_PROGRAMS = gen_art_config
+
+BUILT_SOURCES = art_config.h
+
+art_config.h:  gen_art_config
+       ./gen_art_config > art_config.h
+
+EXTRA_DIST =                   \
+       libart-config.in        \
+       libart-2.0.pc.in
+
+librrd_art_la_SOURCES = \
+       art_affine.c \
+       art_alphagamma.c \
+       art_bpath.c \
+       art_gray_svp.c \
+       art_misc.c \
+       art_pixbuf.c \
+       art_rect.c \
+       art_rect_svp.c \
+       art_rect_uta.c \
+       art_render.c \
+       art_render_gradient.c \
+       art_render_svp.c \
+       art_rgb.c \
+       art_rgb_affine.c \
+       art_rgb_affine_private.c \
+       art_rgb_affine_private.h \
+       art_rgb_bitmap_affine.c \
+       art_rgb_pixbuf_affine.c \
+       art_rgb_rgba_affine.c \
+       art_rgb_a_affine.c \
+       art_rgba.c \
+       art_rgb_svp.c \
+       art_svp.c \
+       art_svp_intersect.c \
+       art_svp_ops.c \
+       art_svp_point.c \
+       art_svp_render_aa.c \
+       art_svp_vpath.c \
+       art_svp_vpath_stroke.c \
+       art_svp_wind.c \
+       art_uta.c \
+       art_uta_ops.c \
+       art_uta_rect.c \
+       art_uta_vpath.c \
+       art_uta_svp.c \
+       art_vpath.c \
+       art_vpath_bpath.c \
+       art_vpath_dash.c \
+       art_vpath_svp.c \
+       libart-features.c
+
+librrd_artincdir = $(includedir)/libart-2.0/libart_lgpl
+librrd_artinc_HEADERS = \
+       art_affine.h \
+       art_alphagamma.h \
+       art_bpath.h \
+       art_config.h \
+       art_filterlevel.h \
+       art_gray_svp.h \
+       art_misc.h \
+       art_pathcode.h \
+       art_pixbuf.h \
+       art_point.h \
+       art_rect.h \
+       art_rect_svp.h \
+       art_rect_uta.h \
+       art_render.h \
+       art_render_gradient.h \
+       art_render_svp.h \
+       art_rgb.h \
+       art_rgb_affine.h \
+       art_rgb_bitmap_affine.h \
+       art_rgb_pixbuf_affine.h \
+       art_rgb_rgba_affine.h \
+       art_rgb_a_affine.h \
+       art_rgb_svp.h \
+       art_rgba.h \
+       art_svp.h \
+       art_svp_intersect.h \
+       art_svp_ops.h \
+       art_svp_point.h \
+       art_svp_render_aa.h \
+       art_svp_vpath.h \
+       art_svp_vpath_stroke.h \
+       art_svp_wind.h \
+       art_uta.h \
+       art_uta_ops.h \
+       art_uta_rect.h \
+       art_uta_vpath.h \
+       art_uta_svp.h \
+       art_vpath.h \
+       art_vpath_bpath.h \
+       art_vpath_dash.h \
+       art_vpath_svp.h \
+       libart.h        \
+       libart-features.h
+
+INCLUDES = -I$(top_srcdir) -I$(top_builddir) -DLIBART_COMPILATION
+
diff --git a/libraries/libart_lgpl-2.3.7/Makefile.in b/libraries/libart_lgpl-2.3.7/Makefile.in
new file mode 100644 (file)
index 0000000..c131d4e
--- /dev/null
@@ -0,0 +1,547 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AMTAR = @AMTAR@
+ART_LIB_DIR = @ART_LIB_DIR@
+AS = @AS@
+AWK = @AWK@
+CC = @CC@
+CGI_LIB_DIR = @CGI_LIB_DIR@
+COMP_PERL = @COMP_PERL@
+CPP = @CPP@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+EXEEXT = @EXEEXT@
+FREETYPE_LIB_DIR = @FREETYPE_LIB_DIR@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+NROFF = @NROFF@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PERL = @PERL@
+PERLFLAGS = @PERLFLAGS@
+PERL_MAKE_OPTIONS = @PERL_MAKE_OPTIONS@
+PNG_LIB_DIR = @PNG_LIB_DIR@
+RANLIB = @RANLIB@
+SO_EXT = @SO_EXT@
+STRIP = @STRIP@
+TCL_LD_SEARCH_FLAGS = @TCL_LD_SEARCH_FLAGS@
+TCL_PACKAGE_PATH = @TCL_PACKAGE_PATH@
+TCL_PREFIX = @TCL_PREFIX@
+TCL_SHLIB_CFLAGS = @TCL_SHLIB_CFLAGS@
+TCL_SHLIB_LD = @TCL_SHLIB_LD@
+TCL_SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@
+TROFF = @TROFF@
+VERSION = @VERSION@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIB_DIR = @ZLIB_LIB_DIR@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
+
+noinst_LTLIBRARIES = librrd_art.la
+noinst_PROGRAMS = gen_art_config
+
+BUILT_SOURCES = art_config.h
+
+EXTRA_DIST = \
+       libart-config.in        \
+       libart-2.0.pc.in
+
+
+librrd_art_la_SOURCES = \
+       art_affine.c \
+       art_alphagamma.c \
+       art_bpath.c \
+       art_gray_svp.c \
+       art_misc.c \
+       art_pixbuf.c \
+       art_rect.c \
+       art_rect_svp.c \
+       art_rect_uta.c \
+       art_render.c \
+       art_render_gradient.c \
+       art_render_svp.c \
+       art_rgb.c \
+       art_rgb_affine.c \
+       art_rgb_affine_private.c \
+       art_rgb_affine_private.h \
+       art_rgb_bitmap_affine.c \
+       art_rgb_pixbuf_affine.c \
+       art_rgb_rgba_affine.c \
+       art_rgb_a_affine.c \
+       art_rgba.c \
+       art_rgb_svp.c \
+       art_svp.c \
+       art_svp_intersect.c \
+       art_svp_ops.c \
+       art_svp_point.c \
+       art_svp_render_aa.c \
+       art_svp_vpath.c \
+       art_svp_vpath_stroke.c \
+       art_svp_wind.c \
+       art_uta.c \
+       art_uta_ops.c \
+       art_uta_rect.c \
+       art_uta_vpath.c \
+       art_uta_svp.c \
+       art_vpath.c \
+       art_vpath_bpath.c \
+       art_vpath_dash.c \
+       art_vpath_svp.c \
+       libart-features.c
+
+
+librrd_artincdir = $(includedir)/libart-2.0/libart_lgpl
+librrd_artinc_HEADERS = \
+       art_affine.h \
+       art_alphagamma.h \
+       art_bpath.h \
+       art_config.h \
+       art_filterlevel.h \
+       art_gray_svp.h \
+       art_misc.h \
+       art_pathcode.h \
+       art_pixbuf.h \
+       art_point.h \
+       art_rect.h \
+       art_rect_svp.h \
+       art_rect_uta.h \
+       art_render.h \
+       art_render_gradient.h \
+       art_render_svp.h \
+       art_rgb.h \
+       art_rgb_affine.h \
+       art_rgb_bitmap_affine.h \
+       art_rgb_pixbuf_affine.h \
+       art_rgb_rgba_affine.h \
+       art_rgb_a_affine.h \
+       art_rgb_svp.h \
+       art_rgba.h \
+       art_svp.h \
+       art_svp_intersect.h \
+       art_svp_ops.h \
+       art_svp_point.h \
+       art_svp_render_aa.h \
+       art_svp_vpath.h \
+       art_svp_vpath_stroke.h \
+       art_svp_wind.h \
+       art_uta.h \
+       art_uta_ops.h \
+       art_uta_rect.h \
+       art_uta_vpath.h \
+       art_uta_svp.h \
+       art_vpath.h \
+       art_vpath_bpath.h \
+       art_vpath_dash.h \
+       art_vpath_svp.h \
+       libart.h        \
+       libart-features.h
+
+
+INCLUDES = -I$(top_srcdir) -I$(top_builddir) -DLIBART_COMPILATION
+subdir = libraries/libart_lgpl-2.3.7
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+
+librrd_art_la_LDFLAGS =
+librrd_art_la_LIBADD =
+am_librrd_art_la_OBJECTS = art_affine.lo art_alphagamma.lo art_bpath.lo \
+       art_gray_svp.lo art_misc.lo art_pixbuf.lo art_rect.lo \
+       art_rect_svp.lo art_rect_uta.lo art_render.lo \
+       art_render_gradient.lo art_render_svp.lo art_rgb.lo \
+       art_rgb_affine.lo art_rgb_affine_private.lo \
+       art_rgb_bitmap_affine.lo art_rgb_pixbuf_affine.lo \
+       art_rgb_rgba_affine.lo art_rgb_a_affine.lo art_rgba.lo \
+       art_rgb_svp.lo art_svp.lo art_svp_intersect.lo art_svp_ops.lo \
+       art_svp_point.lo art_svp_render_aa.lo art_svp_vpath.lo \
+       art_svp_vpath_stroke.lo art_svp_wind.lo art_uta.lo \
+       art_uta_ops.lo art_uta_rect.lo art_uta_vpath.lo art_uta_svp.lo \
+       art_vpath.lo art_vpath_bpath.lo art_vpath_dash.lo \
+       art_vpath_svp.lo libart-features.lo
+librrd_art_la_OBJECTS = $(am_librrd_art_la_OBJECTS)
+noinst_PROGRAMS = gen_art_config$(EXEEXT)
+PROGRAMS = $(noinst_PROGRAMS)
+
+gen_art_config_SOURCES = gen_art_config.c
+gen_art_config_OBJECTS = gen_art_config.$(OBJEXT)
+gen_art_config_LDADD = $(LDADD)
+gen_art_config_DEPENDENCIES =
+gen_art_config_LDFLAGS =
+
+DEFS = @DEFS@
+DEFAULT_INCLUDES =  -I. -I$(srcdir) -I$(top_builddir)/config
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+@AMDEP_TRUE@DEP_FILES = $(DEPDIR)/art_affine.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_alphagamma.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_bpath.Plo $(DEPDIR)/art_gray_svp.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_misc.Plo $(DEPDIR)/art_pixbuf.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_rect.Plo $(DEPDIR)/art_rect_svp.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_rect_uta.Plo $(DEPDIR)/art_render.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_render_gradient.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_render_svp.Plo $(DEPDIR)/art_rgb.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_rgb_a_affine.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_rgb_affine.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_rgb_affine_private.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_rgb_bitmap_affine.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_rgb_pixbuf_affine.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_rgb_rgba_affine.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_rgb_svp.Plo $(DEPDIR)/art_rgba.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_svp.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_svp_intersect.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_svp_ops.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_svp_point.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_svp_render_aa.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_svp_vpath.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_svp_vpath_stroke.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_svp_wind.Plo $(DEPDIR)/art_uta.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_uta_ops.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_uta_rect.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_uta_svp.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_uta_vpath.Plo $(DEPDIR)/art_vpath.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_vpath_bpath.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_vpath_dash.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/art_vpath_svp.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/gen_art_config.Po \
+@AMDEP_TRUE@   $(DEPDIR)/libart-features.Plo
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
+       $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+DIST_SOURCES = $(librrd_art_la_SOURCES) gen_art_config.c
+HEADERS = $(librrd_artinc_HEADERS)
+
+DIST_COMMON = README $(librrd_artinc_HEADERS) AUTHORS COPYING ChangeLog \
+       INSTALL Makefile.am Makefile.in NEWS install-sh missing \
+       mkinstalldirs
+SOURCES = $(librrd_art_la_SOURCES) gen_art_config.c
+
+all: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  libraries/libart_lgpl-2.3.7/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) && \
+         CONFIG_HEADERS= CONFIG_LINKS= \
+         CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+librrd_art.la: $(librrd_art_la_OBJECTS) $(librrd_art_la_DEPENDENCIES) 
+       $(LINK)  $(librrd_art_la_LDFLAGS) $(librrd_art_la_OBJECTS) $(librrd_art_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+       -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+gen_art_config$(EXEEXT): $(gen_art_config_OBJECTS) $(gen_art_config_DEPENDENCIES) 
+       @rm -f gen_art_config$(EXEEXT)
+       $(LINK) $(gen_art_config_LDFLAGS) $(gen_art_config_OBJECTS) $(gen_art_config_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_affine.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_alphagamma.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_bpath.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_gray_svp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_misc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_pixbuf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rect.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rect_svp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rect_uta.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_render.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_render_gradient.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_render_svp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rgb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rgb_a_affine.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rgb_affine.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rgb_affine_private.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rgb_bitmap_affine.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rgb_pixbuf_affine.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rgb_rgba_affine.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rgb_svp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_rgba.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_svp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_svp_intersect.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_svp_ops.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_svp_point.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_svp_render_aa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_svp_vpath.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_svp_vpath_stroke.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_svp_wind.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_uta.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_uta_ops.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_uta_rect.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_uta_svp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_uta_vpath.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_vpath.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_vpath_bpath.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_vpath_dash.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/art_vpath_svp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/gen_art_config.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libart-features.Plo@am__quote@
+
+distclean-depend:
+       -rm -rf $(DEPDIR)
+
+.c.o:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$<
+
+.c.obj:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(COMPILE) -c `cygpath -w $<`
+
+.c.lo:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LTCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+CCDEPMODE = @CCDEPMODE@
+uninstall-info-am:
+install-librrd_artincHEADERS: $(librrd_artinc_HEADERS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(librrd_artincdir)
+       @list='$(librrd_artinc_HEADERS)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f="`echo $$p | sed -e 's|^.*/||'`"; \
+         echo " $(INSTALL_HEADER) $$d$$p $(DESTDIR)$(librrd_artincdir)/$$f"; \
+         $(INSTALL_HEADER) $$d$$p $(DESTDIR)$(librrd_artincdir)/$$f; \
+       done
+
+uninstall-librrd_artincHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(librrd_artinc_HEADERS)'; for p in $$list; do \
+         f="`echo $$p | sed -e 's|^.*/||'`"; \
+         echo " rm -f $(DESTDIR)$(librrd_artincdir)/$$f"; \
+         rm -f $(DESTDIR)$(librrd_artincdir)/$$f; \
+       done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || etags $(ETAGS_ARGS) $$tags  $$unique $(LISP)
+
+GTAGS:
+       here=`CDPATH=: && cd $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           $(mkinstalldirs) "$(distdir)/$$dir"; \
+         fi; \
+         if test -d $$d/$$file; then \
+           cp -pR $$d/$$file $(distdir) \
+           || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+
+installdirs:
+       $(mkinstalldirs) $(DESTDIR)$(librrd_artincdir)
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+       clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+       distclean-generic distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-librrd_artincHEADERS
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+uninstall-am: uninstall-info-am uninstall-librrd_artincHEADERS
+
+.PHONY: GTAGS all all-am check check-am clean clean-generic \
+       clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+       distclean distclean-compile distclean-depend distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am info \
+       info-am install install-am install-data install-data-am \
+       install-exec install-exec-am install-info install-info-am \
+       install-librrd_artincHEADERS install-man install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool tags uninstall \
+       uninstall-am uninstall-info-am uninstall-librrd_artincHEADERS
+
+
+art_config.h:  gen_art_config
+       ./gen_art_config > art_config.h
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libraries/libart_lgpl-2.3.7/NEWS b/libraries/libart_lgpl-2.3.7/NEWS
new file mode 100644 (file)
index 0000000..a48e792
--- /dev/null
@@ -0,0 +1 @@
+Please see http://www.levien.com/libart/ for the latest news.
diff --git a/libraries/libart_lgpl-2.3.7/README b/libraries/libart_lgpl-2.3.7/README
new file mode 100644 (file)
index 0000000..8f5fc82
--- /dev/null
@@ -0,0 +1,15 @@
+This is the LGPL'd component of libart. All functions needed for
+running the Gnome canvas, and for printing support, will be going in
+here. The GPL'd component will be getting various enhanced functions
+for specific applications.
+
+Libart is free software. It is also for sale. For information about
+licensing libart, please contact Raph Levien
+<raph@acm.org>. Contributions to the codebase are also very welcome,
+but the copyright must be assigned in writing to preserve the
+licensing flexibility.
+
+
+For more information about libart, see the web page:
+
+   http://www.levien.com/libart/
diff --git a/libraries/libart_lgpl-2.3.7/art_affine.c b/libraries/libart_lgpl-2.3.7/art_affine.c
new file mode 100644 (file)
index 0000000..99202df
--- /dev/null
@@ -0,0 +1,457 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Simple manipulations with affine transformations */
+
+#include <math.h>
+#include <stdio.h> /* for sprintf */
+#include <string.h> /* for strcpy */
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+
+
+/* According to a strict interpretation of the libart structure, this
+   routine should go into its own module, art_point_affine.  However,
+   it's only two lines of code, and it can be argued that it is one of
+   the natural basic functions of an affine transformation.
+*/
+
+/**
+ * art_affine_point: Do an affine transformation of a point.
+ * @dst: Where the result point is stored.
+ * @src: The original point.
+ @ @affine: The affine transformation.
+ **/
+void
+art_affine_point (ArtPoint *dst, const ArtPoint *src,
+                 const double affine[6])
+{
+  double x, y;
+
+  x = src->x;
+  y = src->y;
+  dst->x = x * affine[0] + y * affine[2] + affine[4];
+  dst->y = x * affine[1] + y * affine[3] + affine[5];
+}
+
+/**
+ * art_affine_invert: Find the inverse of an affine transformation.
+ * @dst: Where the resulting affine is stored.
+ * @src: The original affine transformation.
+ *
+ * All non-degenerate affine transforms are invertible. If the original
+ * affine is degenerate or nearly so, expect numerical instability and
+ * very likely core dumps on Alpha and other fp-picky architectures.
+ * Otherwise, @dst multiplied with @src, or @src multiplied with @dst
+ * will be (to within roundoff error) the identity affine.
+ **/
+void
+art_affine_invert (double dst[6], const double src[6])
+{
+  double r_det;
+
+  r_det = 1.0 / (src[0] * src[3] - src[1] * src[2]);
+  dst[0] = src[3] * r_det;
+  dst[1] = -src[1] * r_det;
+  dst[2] = -src[2] * r_det;
+  dst[3] = src[0] * r_det;
+  dst[4] = -src[4] * dst[0] - src[5] * dst[2];
+  dst[5] = -src[4] * dst[1] - src[5] * dst[3];
+}
+
+/**
+ * art_affine_flip: Flip an affine transformation horizontally and/or vertically.
+ * @dst_affine: Where the resulting affine is stored.
+ * @src_affine: The original affine transformation.
+ * @horiz: Whether or not to flip horizontally.
+ * @vert: Whether or not to flip horizontally.
+ *
+ * Flips the affine transform. FALSE for both @horiz and @vert implements
+ * a simple copy operation. TRUE for both @horiz and @vert is a
+ * 180 degree rotation. It is ok for @src_affine and @dst_affine to
+ * be equal pointers.
+ **/
+void
+art_affine_flip (double dst_affine[6], const double src_affine[6], int horz, int vert)
+{
+  dst_affine[0] = horz ? - src_affine[0] : src_affine[0];
+  dst_affine[1] = horz ? - src_affine[1] : src_affine[1];
+  dst_affine[2] = vert ? - src_affine[2] : src_affine[2];
+  dst_affine[3] = vert ? - src_affine[3] : src_affine[3];
+  dst_affine[4] = horz ? - src_affine[4] : src_affine[4];
+  dst_affine[5] = vert ? - src_affine[5] : src_affine[5];
+}
+
+#define EPSILON 1e-6
+
+/* It's ridiculous I have to write this myself. This is hardcoded to
+   six digits of precision, which is good enough for PostScript.
+
+   The return value is the number of characters (i.e. strlen (str)).
+   It is no more than 12. */
+static int
+art_ftoa (char str[80], double x)
+{
+  char *p = str;
+  int i, j;
+
+  p = str;
+  if (fabs (x) < EPSILON / 2)
+    {
+      strcpy (str, "0");
+      return 1;
+    }
+  if (x < 0)
+    {
+      *p++ = '-';
+      x = -x;
+    }
+  if ((int)floor ((x + EPSILON / 2) < 1))
+    {
+      *p++ = '0';
+      *p++ = '.';
+      i = sprintf (p, "%06d", (int)floor ((x + EPSILON / 2) * 1e6));
+      while (i && p[i - 1] == '0')
+       i--;
+      if (i == 0)
+       i--;
+      p += i;
+    }
+  else if (x < 1e6)
+    {
+      i = sprintf (p, "%d", (int)floor (x + EPSILON / 2));
+      p += i;
+      if (i < 6)
+       {
+         int ix;
+
+         *p++ = '.';
+         x -= floor (x + EPSILON / 2);
+         for (j = i; j < 6; j++)
+           x *= 10;
+         ix = floor (x + 0.5);
+
+         for (j = 0; j < i; j++)
+           ix *= 10;
+
+         /* A cheap hack, this routine can round wrong for fractions
+            near one. */
+         if (ix == 1000000)
+           ix = 999999;
+
+         sprintf (p, "%06d", ix);
+         i = 6 - i;
+         while (i && p[i - 1] == '0')
+           i--;
+         if (i == 0)
+           i--;
+         p += i;
+       }
+    }
+  else
+    p += sprintf (p, "%g", x);
+
+  *p = '\0';
+  return p - str;
+}
+
+
+
+#include <stdlib.h>
+/**
+ * art_affine_to_string: Convert affine transformation to concise PostScript string representation.
+ * @str: Where to store the resulting string.
+ * @src: The affine transform.
+ *
+ * Converts an affine transform into a bit of PostScript code that
+ * implements the transform. Special cases of scaling, rotation, and
+ * translation are detected, and the corresponding PostScript
+ * operators used (this greatly aids understanding the output
+ * generated). The identity transform is mapped to the null string.
+ **/
+void
+art_affine_to_string (char str[128], const double src[6])
+{
+  char tmp[80];
+  int i, ix;
+
+#if 0
+  for (i = 0; i < 1000; i++)
+    {
+      double d = rand () * .1 / RAND_MAX;
+      art_ftoa (tmp, d);
+      printf ("%g %f %s\n", d, d, tmp);
+    }
+#endif
+  if (fabs (src[4]) < EPSILON && fabs (src[5]) < EPSILON)
+    {
+      /* could be scale or rotate */
+      if (fabs (src[1]) < EPSILON && fabs (src[2]) < EPSILON)
+       {
+         /* scale */
+         if (fabs (src[0] - 1) < EPSILON && fabs (src[3] - 1) < EPSILON)
+           {
+             /* identity transform */
+             str[0] = '\0';
+             return;
+           }
+         else
+           {
+             ix = 0;
+             ix += art_ftoa (str + ix, src[0]);
+             str[ix++] = ' ';
+             ix += art_ftoa (str + ix, src[3]);
+             strcpy (str + ix, " scale");
+             return;
+           }
+       }
+      else
+       {
+         /* could be rotate */
+         if (fabs (src[0] - src[3]) < EPSILON &&
+             fabs (src[1] + src[2]) < EPSILON &&
+             fabs (src[0] * src[0] + src[1] * src[1] - 1) < 2 * EPSILON)
+           {
+             double theta;
+
+             theta = (180 / M_PI) * atan2 (src[1], src[0]);
+             art_ftoa (tmp, theta);
+             sprintf (str, "%s rotate", tmp);
+             return;
+           }
+       }
+    }
+  else
+    {
+      /* could be translate */
+      if (fabs (src[0] - 1) < EPSILON && fabs (src[1]) < EPSILON &&
+         fabs (src[2]) < EPSILON && fabs (src[3] - 1) < EPSILON)
+       {
+         ix = 0;
+         ix += art_ftoa (str + ix, src[4]);
+         str[ix++] = ' ';
+         ix += art_ftoa (str + ix, src[5]);
+         strcpy (str + ix, " translate");
+         return;
+       }
+    }
+
+  ix = 0;
+  str[ix++] = '[';
+  str[ix++] = ' ';
+  for (i = 0; i < 6; i++)
+    {
+      ix += art_ftoa (str + ix, src[i]);
+      str[ix++] = ' ';
+    }
+  strcpy (str + ix, "] concat");
+}
+
+/**
+ * art_affine_multiply: Multiply two affine transformation matrices.
+ * @dst: Where to store the result.
+ * @src1: The first affine transform to multiply.
+ * @src2: The second affine transform to multiply.
+ *
+ * Multiplies two affine transforms together, i.e. the resulting @dst
+ * is equivalent to doing first @src1 then @src2. Note that the
+ * PostScript concat operator multiplies on the left, i.e.  "M concat"
+ * is equivalent to "CTM = multiply (M, CTM)";
+ *
+ * It is safe to call this function with @dst equal to @src1 or @src2.
+ **/
+void
+art_affine_multiply (double dst[6], const double src1[6], const double src2[6])
+{
+  double d0, d1, d2, d3, d4, d5;
+
+  d0 = src1[0] * src2[0] + src1[1] * src2[2];
+  d1 = src1[0] * src2[1] + src1[1] * src2[3];
+  d2 = src1[2] * src2[0] + src1[3] * src2[2];
+  d3 = src1[2] * src2[1] + src1[3] * src2[3];
+  d4 = src1[4] * src2[0] + src1[5] * src2[2] + src2[4];
+  d5 = src1[4] * src2[1] + src1[5] * src2[3] + src2[5];
+  dst[0] = d0;
+  dst[1] = d1;
+  dst[2] = d2;
+  dst[3] = d3;
+  dst[4] = d4;
+  dst[5] = d5;
+}
+
+/**
+ * art_affine_identity: Set up the identity matrix.
+ * @dst: Where to store the resulting affine transform.
+ *
+ * Sets up an identity matrix.
+ **/
+void
+art_affine_identity (double dst[6])
+{
+  dst[0] = 1;
+  dst[1] = 0;
+  dst[2] = 0;
+  dst[3] = 1;
+  dst[4] = 0;
+  dst[5] = 0;
+}
+
+
+/**
+ * art_affine_scale: Set up a scaling matrix.
+ * @dst: Where to store the resulting affine transform.
+ * @sx: X scale factor.
+ * @sy: Y scale factor.
+ *
+ * Sets up a scaling matrix.
+ **/
+void
+art_affine_scale (double dst[6], double sx, double sy)
+{
+  dst[0] = sx;
+  dst[1] = 0;
+  dst[2] = 0;
+  dst[3] = sy;
+  dst[4] = 0;
+  dst[5] = 0;
+}
+
+/**
+ * art_affine_rotate: Set up a rotation affine transform.
+ * @dst: Where to store the resulting affine transform.
+ * @theta: Rotation angle in degrees.
+ *
+ * Sets up a rotation matrix. In the standard libart coordinate
+ * system, in which increasing y moves downward, this is a
+ * counterclockwise rotation. In the standard PostScript coordinate
+ * system, which is reversed in the y direction, it is a clockwise
+ * rotation.
+ **/
+void
+art_affine_rotate (double dst[6], double theta)
+{
+  double s, c;
+
+  s = sin (theta * M_PI / 180.0);
+  c = cos (theta * M_PI / 180.0);
+  dst[0] = c;
+  dst[1] = s;
+  dst[2] = -s;
+  dst[3] = c;
+  dst[4] = 0;
+  dst[5] = 0;
+}
+
+/**
+ * art_affine_shear: Set up a shearing matrix.
+ * @dst: Where to store the resulting affine transform.
+ * @theta: Shear angle in degrees.
+ *
+ * Sets up a shearing matrix. In the standard libart coordinate system
+ * and a small value for theta, || becomes \\. Horizontal lines remain
+ * unchanged.
+ **/
+void
+art_affine_shear (double dst[6], double theta)
+{
+  double t;
+
+  t = tan (theta * M_PI / 180.0);
+  dst[0] = 1;
+  dst[1] = 0;
+  dst[2] = t;
+  dst[3] = 1;
+  dst[4] = 0;
+  dst[5] = 0;
+}
+
+/**
+ * art_affine_translate: Set up a translation matrix.
+ * @dst: Where to store the resulting affine transform.
+ * @tx: X translation amount.
+ * @tx: Y translation amount.
+ *
+ * Sets up a translation matrix.
+ **/
+void
+art_affine_translate (double dst[6], double tx, double ty)
+{
+  dst[0] = 1;
+  dst[1] = 0;
+  dst[2] = 0;
+  dst[3] = 1;
+  dst[4] = tx;
+  dst[5] = ty;
+}
+
+/**
+ * art_affine_expansion: Find the affine's expansion factor.
+ * @src: The affine transformation.
+ *
+ * Finds the expansion factor, i.e. the square root of the factor
+ * by which the affine transform affects area. In an affine transform
+ * composed of scaling, rotation, shearing, and translation, returns
+ * the amount of scaling.
+ *
+ * Return value: the expansion factor.
+ **/
+double
+art_affine_expansion (const double src[6])
+{
+  return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
+}
+
+/**
+ * art_affine_rectilinear: Determine whether the affine transformation is rectilinear.
+ * @src: The original affine transformation.
+ *
+ * Determines whether @src is rectilinear, i.e.  grid-aligned
+ * rectangles are transformed to other grid-aligned rectangles.  The
+ * implementation has epsilon-tolerance for roundoff errors.
+ *
+ * Return value: TRUE if @src is rectilinear.
+ **/
+int
+art_affine_rectilinear (const double src[6])
+{
+  return ((fabs (src[1]) < EPSILON && fabs (src[2]) < EPSILON) ||
+         (fabs (src[0]) < EPSILON && fabs (src[3]) < EPSILON));
+}
+
+/**
+ * art_affine_equal: Determine whether two affine transformations are equal.
+ * @matrix1: An affine transformation.
+ * @matrix2: Another affine transformation.
+ *
+ * Determines whether @matrix1 and @matrix2 are equal, with
+ * epsilon-tolerance for roundoff errors.
+ *
+ * Return value: TRUE if @matrix1 and @matrix2 are equal.
+ **/
+int
+art_affine_equal (double matrix1[6], double matrix2[6])
+{
+  return (fabs (matrix1[0] - matrix2[0]) < EPSILON &&
+         fabs (matrix1[1] - matrix2[1]) < EPSILON &&
+         fabs (matrix1[2] - matrix2[2]) < EPSILON &&
+         fabs (matrix1[3] - matrix2[3]) < EPSILON &&
+         fabs (matrix1[4] - matrix2[4]) < EPSILON &&
+         fabs (matrix1[5] - matrix2[5]) < EPSILON);
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_affine.h b/libraries/libart_lgpl-2.3.7/art_affine.h
new file mode 100644 (file)
index 0000000..4be7207
--- /dev/null
@@ -0,0 +1,93 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_AFFINE_H__
+#define __ART_AFFINE_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_point.h"
+#else
+#include <art_point.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_affine_point (ArtPoint *dst, const ArtPoint *src,
+                 const double affine[6]);
+
+void
+art_affine_invert (double dst_affine[6], const double src_affine[6]);
+
+/* flip the matrix, FALSE, FALSE is a simple copy operation, and
+   TRUE, TRUE equals a rotation by 180 degrees */
+void
+art_affine_flip (double dst_affine[6], const double src_affine[6],
+                 int horz, int vert);
+
+void
+art_affine_to_string (char str[128], const double src[6]);
+
+void
+art_affine_multiply (double dst[6],
+                    const double src1[6], const double src2[6]);
+
+/* set up the identity matrix */
+void
+art_affine_identity (double dst[6]);
+
+/* set up a scaling matrix */
+void
+art_affine_scale (double dst[6], double sx, double sy);
+
+/* set up a rotation matrix; theta is given in degrees */
+void
+art_affine_rotate (double dst[6], double theta);
+
+/* set up a shearing matrix; theta is given in degrees */
+void
+art_affine_shear (double dst[6], double theta);
+
+/* set up a translation matrix */
+void
+art_affine_translate (double dst[6], double tx, double ty);
+
+
+/* find the affine's "expansion factor", i.e. the scale amount */
+double
+art_affine_expansion (const double src[6]);
+
+/* Determine whether the affine transformation is rectilinear,
+   i.e. whether a rectangle aligned to the grid is transformed into
+   another rectangle aligned to the grid. */
+int
+art_affine_rectilinear (const double src[6]);
+
+/* Determine whether two affine transformations are equal within grid allignment */
+int
+art_affine_equal (double matrix1[6], double matrix2[6]);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_AFFINE_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_alphagamma.c b/libraries/libart_lgpl-2.3.7/art_alphagamma.c
new file mode 100644 (file)
index 0000000..e3c1098
--- /dev/null
@@ -0,0 +1,85 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Some functions to build alphagamma tables */
+
+#include <math.h>
+#include "art_misc.h"
+
+#include "art_alphagamma.h"
+
+/**
+ * art_alphagamma_new: Create a new #ArtAlphaGamma.
+ * @gamma: Gamma value.
+ *
+ * Create a new #ArtAlphaGamma for a specific value of @gamma. When
+ * correctly implemented (which is generally not the case in libart),
+ * alpha compositing with an alphagamma parameter is equivalent to
+ * applying the gamma transformation to source images, doing the alpha
+ * compositing (in linear intensity space), then applying the inverse
+ * gamma transformation, bringing it back to a gamma-adjusted
+ * intensity space.
+ *
+ * Return value: The newly created #ArtAlphaGamma.
+ **/
+ArtAlphaGamma *
+art_alphagamma_new (double gamma)
+{
+  int tablesize;
+  ArtAlphaGamma *alphagamma;
+  int i;
+  int *table;
+  art_u8 *invtable;
+  double s, r_gamma;
+
+  tablesize = ceil (gamma * 8);
+  if (tablesize < 10)
+    tablesize = 10;
+
+  alphagamma = (ArtAlphaGamma *)art_alloc (sizeof(ArtAlphaGamma) +
+                                          ((1 << tablesize) - 1) *
+                                          sizeof(art_u8));
+  alphagamma->gamma = gamma;
+  alphagamma->invtable_size = tablesize;
+
+  table = alphagamma->table;
+  for (i = 0; i < 256; i++)
+    table[i] = (int)floor (((1 << tablesize) - 1) *
+                          pow (i * (1.0 / 255), gamma) + 0.5);
+
+  invtable = alphagamma->invtable;
+  s = 1.0 / ((1 << tablesize) - 1);
+  r_gamma = 1.0 / gamma;
+  for (i = 0; i < 1 << tablesize; i++)
+    invtable[i] = (int)floor (255 * pow (i * s, r_gamma) + 0.5);
+
+  return alphagamma;
+}
+
+/**
+ * art_alphagamma_free: Free an #ArtAlphaGamma.
+ * @alphagamma: An #ArtAlphaGamma.
+ *
+ * Frees the #ArtAlphaGamma.
+ **/
+void
+art_alphagamma_free (ArtAlphaGamma *alphagamma)
+{
+  art_free (alphagamma);
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_alphagamma.h b/libraries/libart_lgpl-2.3.7/art_alphagamma.h
new file mode 100644 (file)
index 0000000..817e044
--- /dev/null
@@ -0,0 +1,55 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_ALPHAGAMMA_H__
+#define __ART_ALPHAGAMMA_H__
+
+/* Alphagamma tables */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef LIBART_COMPILATION
+#include "art_misc.h"
+#else
+#include <art_misc.h>
+#endif
+
+typedef struct _ArtAlphaGamma ArtAlphaGamma;
+
+struct _ArtAlphaGamma {
+  /*< private >*/
+  double gamma;
+  int invtable_size;
+  int table[256];
+  art_u8 invtable[1];
+};
+
+ArtAlphaGamma *
+art_alphagamma_new (double gamma);
+
+void
+art_alphagamma_free (ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_bpath.c b/libraries/libart_lgpl-2.3.7/art_bpath.c
new file mode 100644 (file)
index 0000000..4fc995d
--- /dev/null
@@ -0,0 +1,92 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Basic constructors and operations for bezier paths */
+
+#include <math.h>
+
+#include "art_misc.h"
+
+#include "art_bpath.h"
+
+/**
+ * art_bpath_affine_transform: Affine transform an #ArtBpath.
+ * @src: The source #ArtBpath.
+ * @matrix: The affine transform.
+ *
+ * Affine transform the bezpath, returning a newly allocated #ArtBpath
+ * (allocated using art_alloc()).
+ *
+ * Result (x', y') = (matrix[0] * x + matrix[2] * y + matrix[4],
+ *                    matrix[1] * x + matrix[3] * y + matrix[5])
+ *
+ * Return value: the transformed #ArtBpath.
+ **/
+ArtBpath *
+art_bpath_affine_transform (const ArtBpath *src, const double matrix[6])
+{
+  int i;
+  int size;
+  ArtBpath *new;
+  ArtPathcode code;
+  double x, y;
+
+  for (i = 0; src[i].code != ART_END; i++);
+  size = i;
+
+  new = art_new (ArtBpath, size + 1);
+
+  for (i = 0; i < size; i++)
+    {
+      code = src[i].code;
+      new[i].code = code;
+      if (code == ART_CURVETO)
+       {
+         x = src[i].x1;
+         y = src[i].y1;
+         new[i].x1 = matrix[0] * x + matrix[2] * y + matrix[4];
+         new[i].y1 = matrix[1] * x + matrix[3] * y + matrix[5];
+         x = src[i].x2;
+         y = src[i].y2;
+         new[i].x2 = matrix[0] * x + matrix[2] * y + matrix[4];
+         new[i].y2 = matrix[1] * x + matrix[3] * y + matrix[5];
+       }
+      else
+       {
+         new[i].x1 = 0;
+         new[i].y1 = 0;
+         new[i].x2 = 0;
+         new[i].y2 = 0;
+       }
+      x = src[i].x3;
+      y = src[i].y3;
+      new[i].x3 = matrix[0] * x + matrix[2] * y + matrix[4];
+      new[i].y3 = matrix[1] * x + matrix[3] * y + matrix[5];
+    }
+  new[i].code = ART_END;
+  new[i].x1 = 0;
+  new[i].y1 = 0;
+  new[i].x2 = 0;
+  new[i].y2 = 0;
+  new[i].x3 = 0;
+  new[i].y3 = 0;
+
+  return new;
+}
+
diff --git a/libraries/libart_lgpl-2.3.7/art_bpath.h b/libraries/libart_lgpl-2.3.7/art_bpath.h
new file mode 100644 (file)
index 0000000..788356d
--- /dev/null
@@ -0,0 +1,57 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_BPATH_H__
+#define __ART_BPATH_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_point.h"
+#include "art_pathcode.h"
+#else
+#include <art_point.h>
+#include <art_pathcode.h>
+#endif
+
+/* Basic data structures and constructors for bezier paths */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtBpath ArtBpath;
+
+struct _ArtBpath {
+  /*< public >*/
+  ArtPathcode code;
+  double x1;
+  double y1;
+  double x2;
+  double y2;
+  double x3;
+  double y3;
+};
+
+ArtBpath *
+art_bpath_affine_transform (const ArtBpath *src, const double matrix[6]);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_BPATH_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_config.h b/libraries/libart_lgpl-2.3.7/art_config.h
new file mode 100644 (file)
index 0000000..b0e74ad
--- /dev/null
@@ -0,0 +1,10 @@
+/* Automatically generated by gen_art_config.c */
+
+#define ART_SIZEOF_CHAR 1
+#define ART_SIZEOF_SHORT 2
+#define ART_SIZEOF_INT 4
+#define ART_SIZEOF_LONG 4
+
+typedef unsigned char art_u8;
+typedef unsigned short art_u16;
+typedef unsigned int art_u32;
diff --git a/libraries/libart_lgpl-2.3.7/art_filterlevel.h b/libraries/libart_lgpl-2.3.7/art_filterlevel.h
new file mode 100644 (file)
index 0000000..1f4be48
--- /dev/null
@@ -0,0 +1,68 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_FILTERLEVEL_H__
+#define __ART_FILTERLEVEL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+  ART_FILTER_NEAREST,
+  ART_FILTER_TILES,
+  ART_FILTER_BILINEAR,
+  ART_FILTER_HYPER
+} ArtFilterLevel;
+
+/* NEAREST is nearest neighbor. It is the fastest and lowest quality.
+
+   TILES is an accurate simulation of the PostScript image operator
+   without any interpolation enabled; each pixel is rendered as a tiny
+   parallelogram of solid color, the edges of which are implemented
+   with antialiasing. It resembles nearest neighbor for enlargement,
+   and bilinear for reduction.
+
+   BILINEAR is bilinear interpolation. For enlargement, it is
+   equivalent to point-sampling the ideal bilinear-interpolated
+   image. For reduction, it is equivalent to laying down small tiles
+   and integrating over the coverage area.
+
+   HYPER is the highest quality reconstruction function. It is derived
+   from the hyperbolic filters in Wolberg's "Digital Image Warping,"
+   and is formally defined as the hyperbolic-filter sampling the ideal
+   hyperbolic-filter interpolated image (the filter is designed to be
+   idempotent for 1:1 pixel mapping). It is the slowest and highest
+   quality.
+
+   Note: at this stage of implementation, most filter modes are likely
+   not to be implemented.
+
+   Note: cubic filtering is missing from this list, because there isn't
+   much point - hyper is just as fast to implement and slightly better
+   in quality.
+
+*/
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_PATHCODE_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_gray_svp.c b/libraries/libart_lgpl-2.3.7/art_gray_svp.c
new file mode 100644 (file)
index 0000000..d5fabe3
--- /dev/null
@@ -0,0 +1,121 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Render a sorted vector path into a graymap. */
+
+#include <string.h>    /* for memset */
+#include "art_misc.h"
+
+#include "art_svp.h"
+#include "art_svp_render_aa.h"
+#include "art_gray_svp.h"
+
+typedef struct _ArtGraySVPData ArtGraySVPData;
+
+struct _ArtGraySVPData {
+  art_u8 *buf;
+  int rowstride;
+  int x0, x1;
+};
+
+static void
+art_gray_svp_callback (void *callback_data, int y,
+                      int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+  ArtGraySVPData *data = (ArtGraySVPData *)callback_data;
+  art_u8 *linebuf;
+  int run_x0, run_x1;
+  int running_sum = start;
+  int x0, x1;
+  int k;
+
+#if 0
+  printf ("start = %d", start);
+  running_sum = start;
+  for (k = 0; k < n_steps; k++)
+    {
+      running_sum += steps[k].delta;
+      printf (" %d:%d", steps[k].x, running_sum >> 16);
+    }
+  printf ("\n");
+#endif
+
+  linebuf = data->buf;
+  x0 = data->x0;
+  x1 = data->x1;
+
+  if (n_steps > 0)
+    {
+      run_x1 = steps[0].x;
+      if (run_x1 > x0)
+       memset (linebuf, running_sum >> 16, run_x1 - x0);
+
+      for (k = 0; k < n_steps - 1; k++)
+       {
+         running_sum += steps[k].delta;
+         run_x0 = run_x1;
+         run_x1 = steps[k + 1].x;
+         if (run_x1 > run_x0)
+           memset (linebuf + run_x0 - x0, running_sum >> 16, run_x1 - run_x0);
+       }
+      running_sum += steps[k].delta;
+      if (x1 > run_x1)
+       memset (linebuf + run_x1 - x0, running_sum >> 16, x1 - run_x1);
+    }
+  else
+    {
+      memset (linebuf, running_sum >> 16, x1 - x0);
+    }
+
+  data->buf += data->rowstride;
+}
+
+/**
+ * art_gray_svp_aa: Render the vector path into the bytemap.
+ * @svp: The SVP to render.
+ * @x0: The view window's left coord.
+ * @y0: The view window's top coord.
+ * @x1: The view window's right coord.
+ * @y1: The view window's bottom coord.
+ * @buf: The buffer where the bytemap is stored.
+ * @rowstride: the rowstride for @buf.
+ *
+ * Each pixel gets a value proportional to the area within the pixel
+ * overlapping the (filled) SVP. Pixel (x, y) is stored at:
+ *
+ *    @buf[(y - * @y0) * @rowstride + (x - @x0)]
+ *
+ * All pixels @x0 <= x < @x1, @y0 <= y < @y1 are generated. A
+ * stored value of zero is no coverage, and a value of 255 is full
+ * coverage. The area within the pixel (x, y) is the region covered
+ * by [x..x+1] and [y..y+1].
+ **/
+void
+art_gray_svp_aa (const ArtSVP *svp,
+                int x0, int y0, int x1, int y1,
+                art_u8 *buf, int rowstride)
+{
+  ArtGraySVPData data;
+
+  data.buf = buf;
+  data.rowstride = rowstride;
+  data.x0 = x0;
+  data.x1 = x1;
+  art_svp_render_aa (svp, x0, y0, x1, y1, art_gray_svp_callback, &data);
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_gray_svp.h b/libraries/libart_lgpl-2.3.7/art_gray_svp.h
new file mode 100644 (file)
index 0000000..16cd19a
--- /dev/null
@@ -0,0 +1,44 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Render a sorted vector path into a graymap. */
+
+#ifndef __ART_GRAY_SVP_H__
+#define __ART_GRAY_SVP_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#else
+#include <art_svp.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_gray_svp_aa (const ArtSVP *svp,
+                int x0, int y0, int x1, int y1,
+                art_u8 *buf, int rowstride);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_GRAY_SVP_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_misc.c b/libraries/libart_lgpl-2.3.7/art_misc.c
new file mode 100644 (file)
index 0000000..7b3a03f
--- /dev/null
@@ -0,0 +1,61 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Various utility functions RLL finds useful. */
+
+#include "config.h"
+#ifdef HAVE_UINSTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include "art_misc.h"
+
+/**
+ * art_die: Print the error message to stderr and exit with a return code of 1.
+ * @fmt: The printf-style format for the error message.
+ *
+ * Used for dealing with severe errors.
+ **/
+void
+art_die (const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+  exit (1);
+}
+
+/**
+ * art_die: Print the error message to stderr.
+ * @fmt: The printf-style format for the error message.
+ *
+ * Used for generating warnings.
+ **/
+void
+art_warn (const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_misc.h b/libraries/libart_lgpl-2.3.7/art_misc.h
new file mode 100644 (file)
index 0000000..947a63e
--- /dev/null
@@ -0,0 +1,96 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Simple macros to set up storage allocation and basic types for libart
+   functions. */
+
+#ifndef __ART_MISC_H__
+#define __ART_MISC_H__
+
+#include <stdlib.h> /* for malloc, etc. */
+
+/* The art_config.h file is automatically generated by
+   gen_art_config.c and contains definitions of
+   ART_SIZEOF_{CHAR,SHORT,INT,LONG} and art_u{8,16,32}. */
+#ifdef LIBART_COMPILATION
+#include "art_config.h"
+#else
+#include <art_config.h>
+#endif
+
+#define art_alloc malloc
+#define art_free free
+#define art_realloc realloc
+
+/* These aren't, strictly speaking, configuration macros, but they're
+   damn handy to have around, and may be worth playing with for
+   debugging. */
+#define art_new(type, n) ((type *)art_alloc ((n) * sizeof(type)))
+
+#define art_renew(p, type, n) ((type *)art_realloc (p, (n) * sizeof(type)))
+
+/* This one must be used carefully - in particular, p and max should
+   be variables. They can also be pstruct->el lvalues. */
+#define art_expand(p, type, max) do { if(max) { p = art_renew (p, type, max <<= 1); } else { max = 1; p = art_new(type, 1); } } while (0)
+
+typedef int art_boolean;
+#define ART_FALSE 0
+#define ART_TRUE 1
+
+/* define pi */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif  /*  M_PI  */
+
+#ifndef M_SQRT2
+#define M_SQRT2         1.41421356237309504880  /* sqrt(2) */
+#endif  /* M_SQRT2 */
+
+/* Provide macros to feature the GCC function attribute.
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
+#define ART_GNUC_PRINTF( format_idx, arg_idx )    \
+  __attribute__((format (printf, format_idx, arg_idx)))
+#define ART_GNUC_NORETURN                         \
+  __attribute__((noreturn))
+#else   /* !__GNUC__ */
+#define ART_GNUC_PRINTF( format_idx, arg_idx )
+#define ART_GNUC_NORETURN
+#endif  /* !__GNUC__ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ART_GNUC_NORETURN
+art_die (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
+
+void
+art_warn (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Currently, the use of the new intersector is a compile-time option.
+   I'll leave it unset in CVS until I have considerable confidence in
+   the new intersector. */
+#define noART_USE_NEW_INTERSECTOR
+
+#endif /* __ART_MISC_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_pathcode.h b/libraries/libart_lgpl-2.3.7/art_pathcode.h
new file mode 100644 (file)
index 0000000..87979ce
--- /dev/null
@@ -0,0 +1,39 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_PATHCODE_H__
+#define __ART_PATHCODE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+  ART_MOVETO,
+  ART_MOVETO_OPEN,
+  ART_CURVETO,
+  ART_LINETO,
+  ART_END
+} ArtPathcode;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_PATHCODE_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_pixbuf.c b/libraries/libart_lgpl-2.3.7/art_pixbuf.c
new file mode 100644 (file)
index 0000000..a3a16bc
--- /dev/null
@@ -0,0 +1,283 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "art_misc.h"
+#include "art_pixbuf.h"
+#include <string.h>
+
+/**
+ * art_pixbuf_new_rgb_dnotify: Create a new RGB #ArtPixBuf with explicit destroy notification.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ * @dfunc_data: The private data passed to @dfunc.
+ * @dfunc: The destroy notification function.
+ *
+ * Creates a generic data structure for holding a buffer of RGB
+ * pixels.  It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * @dfunc is called with @dfunc_data and @pixels as arguments when the
+ * #ArtPixBuf is destroyed. Using a destroy notification function
+ * allows a wide range of memory management disciplines for the pixel
+ * memory. A NULL value for @dfunc is also allowed and means that no
+ * special action will be taken on destruction.
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_rgb_dnotify (art_u8 *pixels, int width, int height, int rowstride,
+                           void *dfunc_data, ArtDestroyNotify dfunc)
+{
+  ArtPixBuf *pixbuf;
+
+  pixbuf = art_new (ArtPixBuf, 1);
+
+  pixbuf->format = ART_PIX_RGB;
+  pixbuf->n_channels = 3;
+  pixbuf->has_alpha = 0;
+  pixbuf->bits_per_sample = 8;
+
+  pixbuf->pixels = (art_u8 *) pixels;
+  pixbuf->width = width;
+  pixbuf->height = height;
+  pixbuf->rowstride = rowstride;
+  pixbuf->destroy_data = dfunc_data;
+  pixbuf->destroy = dfunc;
+
+  return pixbuf;
+}
+
+/**
+ * art_pixbuf_new_rgba_dnotify: Create a new RGBA #ArtPixBuf with explicit destroy notification.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ * @dfunc_data: The private data passed to @dfunc.
+ * @dfunc: The destroy notification function.
+ *
+ * Creates a generic data structure for holding a buffer of RGBA
+ * pixels.  It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * @dfunc is called with @dfunc_data and @pixels as arguments when the
+ * #ArtPixBuf is destroyed. Using a destroy notification function
+ * allows a wide range of memory management disciplines for the pixel
+ * memory. A NULL value for @dfunc is also allowed and means that no
+ * special action will be taken on destruction.
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_rgba_dnotify (art_u8 *pixels, int width, int height, int rowstride,
+                            void *dfunc_data, ArtDestroyNotify dfunc)
+{
+  ArtPixBuf *pixbuf;
+
+  pixbuf = art_new (ArtPixBuf, 1);
+
+  pixbuf->format = ART_PIX_RGB;
+  pixbuf->n_channels = 4;
+  pixbuf->has_alpha = 1;
+  pixbuf->bits_per_sample = 8;
+
+  pixbuf->pixels = (art_u8 *) pixels;
+  pixbuf->width = width;
+  pixbuf->height = height;
+  pixbuf->rowstride = rowstride;
+  pixbuf->destroy_data = dfunc_data;
+  pixbuf->destroy = dfunc;
+
+  return pixbuf;
+}
+
+/**
+ * art_pixbuf_new_const_rgb: Create a new RGB #ArtPixBuf with constant pixel data.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ *
+ * Creates a generic data structure for holding a buffer of RGB
+ * pixels.  It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * No action is taken when the #ArtPixBuf is destroyed. Thus, this
+ * function is useful when the pixel data is constant or statically
+ * allocated.
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_const_rgb (const art_u8 *pixels, int width, int height, int rowstride)
+{
+  return art_pixbuf_new_rgb_dnotify ((art_u8 *) pixels, width, height, rowstride, NULL, NULL);
+}
+
+/**
+ * art_pixbuf_new_const_rgba: Create a new RGBA #ArtPixBuf with constant pixel data.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ *
+ * Creates a generic data structure for holding a buffer of RGBA
+ * pixels.  It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * No action is taken when the #ArtPixBuf is destroyed. Thus, this
+ * function is suitable when the pixel data is constant or statically
+ * allocated.
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_const_rgba (const art_u8 *pixels, int width, int height, int rowstride)
+{
+  return art_pixbuf_new_rgba_dnotify ((art_u8 *) pixels, width, height, rowstride, NULL, NULL);
+}
+
+static void
+art_pixel_destroy (void *func_data, void *data)
+{
+  art_free (data);
+}
+
+/**
+ * art_pixbuf_new_rgb: Create a new RGB #ArtPixBuf.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ *
+ * Creates a generic data structure for holding a buffer of RGB
+ * pixels.  It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * The @pixels buffer is freed with art_free() when the #ArtPixBuf is
+ * destroyed. Thus, this function is suitable when the pixel data is
+ * allocated with art_alloc().
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_rgb (art_u8 *pixels, int width, int height, int rowstride)
+{
+  return art_pixbuf_new_rgb_dnotify (pixels, width, height, rowstride, NULL, art_pixel_destroy);
+}
+
+/**
+ * art_pixbuf_new_rgba: Create a new RGBA #ArtPixBuf.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ *
+ * Creates a generic data structure for holding a buffer of RGBA
+ * pixels.  It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * The @pixels buffer is freed with art_free() when the #ArtPixBuf is
+ * destroyed. Thus, this function is suitable when the pixel data is
+ * allocated with art_alloc().
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_rgba (art_u8 *pixels, int width, int height, int rowstride)
+{
+  return art_pixbuf_new_rgba_dnotify (pixels, width, height, rowstride, NULL, art_pixel_destroy);
+}
+
+/**
+ * art_pixbuf_free: Destroy an #ArtPixBuf.
+ * @pixbuf: The #ArtPixBuf to be destroyed.
+ *
+ * Destroys the #ArtPixBuf, calling the destroy notification function
+ * (if non-NULL) so that the memory for the pixel buffer can be
+ * properly reclaimed.
+ **/
+void
+art_pixbuf_free (ArtPixBuf *pixbuf)
+{
+  ArtDestroyNotify destroy = pixbuf->destroy;
+  void *destroy_data = pixbuf->destroy_data;
+  art_u8 *pixels = pixbuf->pixels;
+
+  pixbuf->pixels = NULL;
+  pixbuf->destroy = NULL;
+  pixbuf->destroy_data = NULL;
+
+  if (destroy)
+    destroy (destroy_data, pixels);
+
+  art_free (pixbuf);
+}
+
+/**
+ * art_pixbuf_free_shallow:
+ * @pixbuf: The #ArtPixBuf to be destroyed.
+ *
+ * Destroys the #ArtPixBuf without calling the destroy notification function.
+ *
+ * This function is deprecated. Use the _dnotify variants for
+ * allocation instead.
+ **/
+void
+art_pixbuf_free_shallow (ArtPixBuf *pixbuf)
+{
+  art_free (pixbuf);
+}
+
+/**
+ * art_pixbuf_duplicate: Duplicate a pixbuf.
+ * @pixbuf: The #ArtPixBuf to duplicate.
+ *
+ * Duplicates a pixbuf, including duplicating the buffer.
+ *
+ * Return value: The duplicated pixbuf.
+ **/
+ArtPixBuf *
+art_pixbuf_duplicate (const ArtPixBuf *pixbuf)
+{
+  ArtPixBuf *result;
+  int size;
+
+  result = art_new (ArtPixBuf, 1);
+
+  result->format = pixbuf->format;
+  result->n_channels = pixbuf->n_channels;
+  result->has_alpha = pixbuf->has_alpha;
+  result->bits_per_sample = pixbuf->bits_per_sample;
+
+  size = (pixbuf->height - 1) * pixbuf->rowstride +
+    pixbuf->width * ((pixbuf->n_channels * pixbuf->bits_per_sample + 7) >> 3);
+  result->pixels = art_alloc (size);
+  memcpy (result->pixels, pixbuf->pixels, size);
+
+  result->width = pixbuf->width;
+  result->height = pixbuf->height;
+  result->rowstride = pixbuf->rowstride;
+  result->destroy_data = NULL;
+  result->destroy = art_pixel_destroy;
+
+  return result;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_pixbuf.h b/libraries/libart_lgpl-2.3.7/art_pixbuf.h
new file mode 100644 (file)
index 0000000..e092ea2
--- /dev/null
@@ -0,0 +1,98 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_PIXBUF_H__
+#define __ART_PIXBUF_H__
+
+/* A generic data structure for holding a buffer of pixels. One way
+   to think about this module is as a virtualization over specific
+   pixel buffer formats. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef void (*ArtDestroyNotify) (void *func_data, void *data);
+
+typedef struct _ArtPixBuf ArtPixBuf;
+
+typedef enum {
+  ART_PIX_RGB
+  /* gray, cmyk, lab, ... ? */
+} ArtPixFormat;
+
+
+/* The pixel buffer consists of width * height pixels, each of which
+   has n_channels samples. It is stored in simple packed format. */
+
+struct _ArtPixBuf {
+  /*< public >*/
+  ArtPixFormat format;
+  int n_channels;
+  int has_alpha;
+  int bits_per_sample;
+
+  art_u8 *pixels;
+  int width;
+  int height;
+  int rowstride;
+  void *destroy_data;
+  ArtDestroyNotify destroy;
+};
+
+/* allocate an ArtPixBuf from art_alloc()ed pixels (automated destruction) */
+ArtPixBuf *
+art_pixbuf_new_rgb (art_u8 *pixels, int width, int height, int rowstride);
+
+ArtPixBuf *
+art_pixbuf_new_rgba (art_u8 *pixels, int width, int height, int rowstride);
+
+/* allocate an ArtPixBuf from constant pixels (no destruction) */
+ArtPixBuf *
+art_pixbuf_new_const_rgb (const art_u8 *pixels, int width, int height, int rowstride);
+
+ArtPixBuf *
+art_pixbuf_new_const_rgba (const art_u8 *pixels, int width, int height, int rowstride);
+
+/* allocate an ArtPixBuf and notify creator upon destruction */
+ArtPixBuf *
+art_pixbuf_new_rgb_dnotify (art_u8 *pixels, int width, int height, int rowstride,
+                           void *dfunc_data, ArtDestroyNotify dfunc);
+
+ArtPixBuf *
+art_pixbuf_new_rgba_dnotify (art_u8 *pixels, int width, int height, int rowstride,
+                            void *dfunc_data, ArtDestroyNotify dfunc);
+
+/* free an ArtPixBuf with destroy notification */
+void
+art_pixbuf_free (ArtPixBuf *pixbuf);
+
+/* deprecated function, use the _dnotify variants for allocation instead */
+void
+art_pixbuf_free_shallow (ArtPixBuf *pixbuf);
+
+ArtPixBuf *
+art_pixbuf_duplicate (const ArtPixBuf *pixbuf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/art_point.h b/libraries/libart_lgpl-2.3.7/art_point.h
new file mode 100644 (file)
index 0000000..1efcda6
--- /dev/null
@@ -0,0 +1,38 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_POINT_H__
+#define __ART_POINT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtPoint ArtPoint;
+
+struct _ArtPoint {
+  /*< public >*/
+  double x, y;
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_POINT_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_rect.c b/libraries/libart_lgpl-2.3.7/art_rect.c
new file mode 100644 (file)
index 0000000..25276b2
--- /dev/null
@@ -0,0 +1,214 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include "art_misc.h"
+#include "art_rect.h"
+
+#ifndef MAX
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+#ifndef MIN
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+/* rectangle primitives stolen from gzilla */
+
+/**
+ * art_irect_copy: Make a copy of an integer rectangle.
+ * @dest: Where the copy is stored.
+ * @src: The source rectangle.
+ *
+ * Copies the rectangle.
+ **/
+void
+art_irect_copy (ArtIRect *dest, const ArtIRect *src) {
+  dest->x0 = src->x0;
+  dest->y0 = src->y0;
+  dest->x1 = src->x1;
+  dest->y1 = src->y1;
+}
+
+/**
+ * art_irect_union: Find union of two integer rectangles.
+ * @dest: Where the result is stored.
+ * @src1: A source rectangle.
+ * @src2: Another source rectangle.
+ *
+ * Finds the smallest rectangle that includes @src1 and @src2.
+ **/
+void
+art_irect_union (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *src2) {
+  if (art_irect_empty (src1)) {
+    art_irect_copy (dest, src2);
+  } else if (art_irect_empty (src2)) {
+    art_irect_copy (dest, src1);
+  } else {
+    dest->x0 = MIN (src1->x0, src2->x0);
+    dest->y0 = MIN (src1->y0, src2->y0);
+    dest->x1 = MAX (src1->x1, src2->x1);
+    dest->y1 = MAX (src1->y1, src2->y1);
+  }
+}
+
+/**
+ * art_irect_intersection: Find intersection of two integer rectangles.
+ * @dest: Where the result is stored.
+ * @src1: A source rectangle.
+ * @src2: Another source rectangle.
+ *
+ * Finds the intersection of @src1 and @src2.
+ **/
+void
+art_irect_intersect (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *src2) {
+  dest->x0 = MAX (src1->x0, src2->x0);
+  dest->y0 = MAX (src1->y0, src2->y0);
+  dest->x1 = MIN (src1->x1, src2->x1);
+  dest->y1 = MIN (src1->y1, src2->y1);
+}
+
+/**
+ * art_irect_empty: Determine whether integer rectangle is empty.
+ * @src: The source rectangle.
+ *
+ * Return value: TRUE if @src is an empty rectangle, FALSE otherwise.
+ **/
+int
+art_irect_empty (const ArtIRect *src) {
+  return (src->x1 <= src->x0 || src->y1 <= src->y0);
+}
+
+#if 0
+gboolean irect_point_inside (ArtIRect *rect, GzwPoint *point) {
+  return (point->x >= rect->x0 && point->y >= rect->y0 &&
+         point->x < rect->x1 && point->y < rect->y1);
+}
+#endif
+
+/**
+ * art_drect_copy: Make a copy of a rectangle.
+ * @dest: Where the copy is stored.
+ * @src: The source rectangle.
+ *
+ * Copies the rectangle.
+ **/
+void
+art_drect_copy (ArtDRect *dest, const ArtDRect *src) {
+  dest->x0 = src->x0;
+  dest->y0 = src->y0;
+  dest->x1 = src->x1;
+  dest->y1 = src->y1;
+}
+
+/**
+ * art_drect_union: Find union of two rectangles.
+ * @dest: Where the result is stored.
+ * @src1: A source rectangle.
+ * @src2: Another source rectangle.
+ *
+ * Finds the smallest rectangle that includes @src1 and @src2.
+ **/
+void
+art_drect_union (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
+  if (art_drect_empty (src1)) {
+    art_drect_copy (dest, src2);
+  } else if (art_drect_empty (src2)) {
+    art_drect_copy (dest, src1);
+  } else {
+    dest->x0 = MIN (src1->x0, src2->x0);
+    dest->y0 = MIN (src1->y0, src2->y0);
+    dest->x1 = MAX (src1->x1, src2->x1);
+    dest->y1 = MAX (src1->y1, src2->y1);
+  }
+}
+
+/**
+ * art_drect_intersection: Find intersection of two rectangles.
+ * @dest: Where the result is stored.
+ * @src1: A source rectangle.
+ * @src2: Another source rectangle.
+ *
+ * Finds the intersection of @src1 and @src2.
+ **/
+void
+art_drect_intersect (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
+  dest->x0 = MAX (src1->x0, src2->x0);
+  dest->y0 = MAX (src1->y0, src2->y0);
+  dest->x1 = MIN (src1->x1, src2->x1);
+  dest->y1 = MIN (src1->y1, src2->y1);
+}
+
+/**
+ * art_irect_empty: Determine whether rectangle is empty.
+ * @src: The source rectangle.
+ *
+ * Return value: TRUE if @src is an empty rectangle, FALSE otherwise.
+ **/
+int
+art_drect_empty (const ArtDRect *src) {
+  return (src->x1 <= src->x0 || src->y1 <= src->y0);
+}
+
+/**
+ * art_drect_affine_transform: Affine transform rectangle.
+ * @dst: Where to store the result.
+ * @src: The source rectangle.
+ * @matrix: The affine transformation.
+ *
+ * Find the smallest rectangle enclosing the affine transformed @src.
+ * The result is exactly the affine transformation of @src when
+ * @matrix specifies a rectilinear affine transformation, otherwise it
+ * is a conservative approximation.
+ **/
+void
+art_drect_affine_transform (ArtDRect *dst, const ArtDRect *src, const double matrix[6])
+{
+  double x00, y00, x10, y10;
+  double x01, y01, x11, y11;
+
+  x00 = src->x0 * matrix[0] + src->y0 * matrix[2] + matrix[4];
+  y00 = src->x0 * matrix[1] + src->y0 * matrix[3] + matrix[5];
+  x10 = src->x1 * matrix[0] + src->y0 * matrix[2] + matrix[4];
+  y10 = src->x1 * matrix[1] + src->y0 * matrix[3] + matrix[5];
+  x01 = src->x0 * matrix[0] + src->y1 * matrix[2] + matrix[4];
+  y01 = src->x0 * matrix[1] + src->y1 * matrix[3] + matrix[5];
+  x11 = src->x1 * matrix[0] + src->y1 * matrix[2] + matrix[4];
+  y11 = src->x1 * matrix[1] + src->y1 * matrix[3] + matrix[5];
+  dst->x0 = MIN (MIN (x00, x10), MIN (x01, x11));
+  dst->y0 = MIN (MIN (y00, y10), MIN (y01, y11));
+  dst->x1 = MAX (MAX (x00, x10), MAX (x01, x11));
+  dst->y1 = MAX (MAX (y00, y10), MAX (y01, y11));
+}
+
+/**
+ * art_drect_to_irect: Convert rectangle to integer rectangle.
+ * @dst: Where to store resulting integer rectangle.
+ * @src: The source rectangle.
+ *
+ * Find the smallest integer rectangle that encloses @src.
+ **/
+void
+art_drect_to_irect (ArtIRect *dst, ArtDRect *src)
+{
+  dst->x0 = floor (src->x0);
+  dst->y0 = floor (src->y0);
+  dst->x1 = ceil (src->x1);
+  dst->y1 = ceil (src->y1);
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_rect.h b/libraries/libart_lgpl-2.3.7/art_rect.h
new file mode 100644 (file)
index 0000000..088079f
--- /dev/null
@@ -0,0 +1,78 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RECT_H__
+#define __ART_RECT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _ArtDRect ArtDRect;
+typedef struct _ArtIRect ArtIRect;
+
+struct _ArtDRect {
+  /*< public >*/
+  double x0, y0, x1, y1;
+};
+
+struct _ArtIRect {
+  /*< public >*/
+  int x0, y0, x1, y1;
+};
+
+/* Make a copy of the rectangle. */
+void art_irect_copy (ArtIRect *dest, const ArtIRect *src);
+
+/* Find the smallest rectangle that includes both source rectangles. */
+void art_irect_union (ArtIRect *dest,
+                     const ArtIRect *src1, const ArtIRect *src2);
+
+/* Return the intersection of the two rectangles */
+void art_irect_intersect (ArtIRect *dest,
+                         const ArtIRect *src1, const ArtIRect *src2);
+
+/* Return true if the rectangle is empty. */
+int art_irect_empty (const ArtIRect *src);
+
+/* Make a copy of the rectangle. */
+void art_drect_copy (ArtDRect *dest, const ArtDRect *src);
+
+/* Find the smallest rectangle that includes both source rectangles. */
+void art_drect_union (ArtDRect *dest,
+                     const ArtDRect *src1, const ArtDRect *src2);
+
+/* Return the intersection of the two rectangles */
+void art_drect_intersect (ArtDRect *dest,
+                         const ArtDRect *src1, const ArtDRect *src2);
+
+/* Return true if the rectangle is empty. */
+int art_drect_empty (const ArtDRect *src);
+
+void
+art_drect_affine_transform (ArtDRect *dst, const ArtDRect *src,
+                          const double matrix[6]);
+
+void art_drect_to_irect (ArtIRect *dst, ArtDRect *src);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/art_rect_svp.c b/libraries/libart_lgpl-2.3.7/art_rect_svp.c
new file mode 100644 (file)
index 0000000..9e2656a
--- /dev/null
@@ -0,0 +1,65 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "art_misc.h"
+#include "art_svp.h"
+#include "art_rect.h"
+#include "art_rect_svp.h"
+
+/**
+ * art_drect_svp: Find the bounding box of a sorted vector path.
+ * @bbox: Where to store the bounding box.
+ * @svp: The SVP.
+ *
+ * Finds the bounding box of the SVP.
+ **/
+void
+art_drect_svp (ArtDRect *bbox, const ArtSVP *svp)
+{
+  int i;
+
+  bbox->x0 = 0;
+  bbox->y0 = 0;
+  bbox->x1 = 0;
+  bbox->y1 = 0;
+
+  for (i = 0; i < svp->n_segs; i++)
+    {
+      art_drect_union (bbox, bbox, &svp->segs[i].bbox);
+    }
+}
+
+/**
+ * art_drect_svp_union: Compute the bounding box of the svp and union it in to the existing bounding box.
+ * @bbox: Initial boundin box and where to store the bounding box.
+ * @svp: The SVP.
+ *
+ * Finds the bounding box of the SVP, computing its union with an
+ * existing bbox.
+ **/
+void
+art_drect_svp_union (ArtDRect *bbox, const ArtSVP *svp)
+{
+  int i;
+
+  for (i = 0; i < svp->n_segs; i++)
+    {
+      art_drect_union (bbox, bbox, &svp->segs[i].bbox);
+    }
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_rect_svp.h b/libraries/libart_lgpl-2.3.7/art_rect_svp.h
new file mode 100644 (file)
index 0000000..b4bbab3
--- /dev/null
@@ -0,0 +1,41 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RECT_SVP_H__
+#define __ART_RECT_SVP_H__
+
+/* Find the bounding box of a sorted vector path. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_drect_svp (ArtDRect *bbox, const ArtSVP *svp);
+
+/* Compute the bounding box of the svp and union it in to the
+   existing bounding box. */
+void
+art_drect_svp_union (ArtDRect *bbox, const ArtSVP *svp);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RECT_SVP_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_rect_uta.c b/libraries/libart_lgpl-2.3.7/art_rect_uta.c
new file mode 100644 (file)
index 0000000..88f95c3
--- /dev/null
@@ -0,0 +1,136 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "art_misc.h"
+#include "art_uta.h"
+#include "art_rect.h"
+#include "art_rect_uta.h"
+
+/* Functions to decompose a microtile array into a list of rectangles. */
+
+/**
+ * art_rect_list_from_uta: Decompose uta into list of rectangles.
+ * @uta: The source uta.
+ * @max_width: The maximum width of the resulting rectangles.
+ * @max_height: The maximum height of the resulting rectangles.
+ * @p_nrects: Where to store the number of returned rectangles.
+ *
+ * Allocates a new list of rectangles, sets *@p_nrects to the number
+ * in the list. This list should be freed with art_free().
+ *
+ * Each rectangle bounded in size by (@max_width, @max_height).
+ * However, these bounds must be at least the size of one tile.
+ *
+ * This routine provides a precise implementation, i.e. the rectangles
+ * cover exactly the same area as the uta. It is thus appropriate in
+ * cases where the overhead per rectangle is small compared with the
+ * cost of filling in extra pixels.
+ *
+ * Return value: An array containing the resulting rectangles.
+ **/
+ArtIRect *
+art_rect_list_from_uta (ArtUta *uta, int max_width, int max_height,
+                       int *p_nrects)
+{
+  ArtIRect *rects;
+  int n_rects, n_rects_max;
+  int x, y;
+  int width, height;
+  int ix;
+  int left_ix;
+  ArtUtaBbox *utiles;
+  ArtUtaBbox bb;
+  int x0, y0, x1, y1;
+  int *glom;
+  int glom_rect;
+
+  n_rects = 0;
+  n_rects_max = 1;
+  rects = art_new (ArtIRect, n_rects_max);
+
+  width = uta->width;
+  height = uta->height;
+  utiles = uta->utiles;
+
+  glom = art_new (int, width * height);
+  for (ix = 0; ix < width * height; ix++)
+    glom[ix] = -1;
+
+  ix = 0;
+  for (y = 0; y < height; y++)
+    for (x = 0; x < width; x++)
+      {
+       bb = utiles[ix];
+       if (bb)
+         {
+           x0 = ((uta->x0 + x) << ART_UTILE_SHIFT) + ART_UTA_BBOX_X0(bb);
+           y0 = ((uta->y0 + y) << ART_UTILE_SHIFT) + ART_UTA_BBOX_Y0(bb);
+           y1 = ((uta->y0 + y) << ART_UTILE_SHIFT) + ART_UTA_BBOX_Y1(bb);
+
+           left_ix = ix;
+           /* now try to extend to the right */
+           while (x != width - 1 &&
+                  ART_UTA_BBOX_X1(bb) == ART_UTILE_SIZE &&
+                  (((bb & 0xffffff) ^ utiles[ix + 1]) & 0xffff00ff) == 0 &&
+                  (((uta->x0 + x + 1) << ART_UTILE_SHIFT) +
+                   ART_UTA_BBOX_X1(utiles[ix + 1]) -
+                   x0) <= max_width)
+             {
+               bb = utiles[ix + 1];
+               ix++;
+               x++;
+             }
+           x1 = ((uta->x0 + x) << ART_UTILE_SHIFT) + ART_UTA_BBOX_X1(bb);
+
+
+           /* if rectangle nonempty */
+           if ((x1 ^ x0) | (y1 ^ y0))
+             {
+               /* try to glom onto an existing rectangle */
+               glom_rect = glom[left_ix];
+               if (glom_rect != -1 &&
+                   x0 == rects[glom_rect].x0 &&
+                   x1 == rects[glom_rect].x1 &&
+                   y0 == rects[glom_rect].y1 &&
+                   y1 - rects[glom_rect].y0 <= max_height)
+                 {
+                   rects[glom_rect].y1 = y1;
+                 }
+               else
+                 {
+                   if (n_rects == n_rects_max)
+                     art_expand (rects, ArtIRect, n_rects_max);
+                   rects[n_rects].x0 = x0;
+                   rects[n_rects].y0 = y0;
+                   rects[n_rects].x1 = x1;
+                   rects[n_rects].y1 = y1;
+                   glom_rect = n_rects;
+                   n_rects++;
+                 }
+               if (y != height - 1)
+                 glom[left_ix + width] = glom_rect;
+             }
+         }
+       ix++;
+      }
+
+  art_free (glom);
+  *p_nrects = n_rects;
+  return rects;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_rect_uta.h b/libraries/libart_lgpl-2.3.7/art_rect_uta.h
new file mode 100644 (file)
index 0000000..b4b13f8
--- /dev/null
@@ -0,0 +1,41 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RECT_UTA_H__
+#define __ART_RECT_UTA_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_uta.h"
+#else
+#include <art_uta.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtIRect *
+art_rect_list_from_uta (ArtUta *uta, int max_width, int max_height,
+                       int *p_nrects);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RECT_UTA_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_render.c b/libraries/libart_lgpl-2.3.7/art_render.c
new file mode 100644 (file)
index 0000000..8eed666
--- /dev/null
@@ -0,0 +1,1132 @@
+/*
+ * art_render.c: Modular rendering architecture.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "art_misc.h"
+#include "art_alphagamma.h"
+#include "art_rgb.h"
+
+#include "art_render.h"
+
+typedef struct _ArtRenderPriv ArtRenderPriv;
+
+struct _ArtRenderPriv {
+  ArtRender super;
+
+  ArtImageSource *image_source;
+
+  int n_mask_source;
+  ArtMaskSource **mask_source;
+
+  int n_callbacks;
+  ArtRenderCallback **callbacks;
+};
+
+ArtRender *
+art_render_new (int x0, int y0, int x1, int y1,
+               art_u8 *pixels, int rowstride,
+               int n_chan, int depth, ArtAlphaType alpha_type,
+               ArtAlphaGamma *alphagamma)
+{
+  ArtRenderPriv *priv;
+  ArtRender *result;
+
+  priv = art_new (ArtRenderPriv, 1);
+  result = &priv->super;
+
+  if (n_chan > ART_MAX_CHAN)
+    {
+      art_warn ("art_render_new: n_chan = %d, exceeds %d max\n",
+               n_chan, ART_MAX_CHAN);
+      return NULL;
+    }
+  if (depth > ART_MAX_DEPTH)
+    {
+      art_warn ("art_render_new: depth = %d, exceeds %d max\n",
+               depth, ART_MAX_DEPTH);
+      return NULL;
+    }
+  if (x0 >= x1)
+    {
+      art_warn ("art_render_new: x0 >= x1 (x0 = %d, x1 = %d)\n", x0, x1);
+      return NULL;
+    }
+  result->x0 = x0;
+  result->y0 = y0;
+  result->x1 = x1;
+  result->y1 = y1;
+  result->pixels = pixels;
+  result->rowstride = rowstride;
+  result->n_chan = n_chan;
+  result->depth = depth;
+  result->alpha_type = alpha_type;
+
+  result->clear = ART_FALSE;
+  result->opacity = 0x10000;
+  result->compositing_mode = ART_COMPOSITE_NORMAL;
+  result->alphagamma = alphagamma;
+
+  result->alpha_buf = NULL;
+  result->image_buf = NULL;
+
+  result->run = NULL;
+  result->span_x = NULL;
+
+  result->need_span = ART_FALSE;
+
+  priv->image_source = NULL;
+
+  priv->n_mask_source = 0;
+  priv->mask_source = NULL;
+
+  return result;
+}
+
+/* todo on clear routines: I haven't really figured out what to do
+   with clearing the alpha channel. It _should_ be possible to clear
+   to an arbitrary RGBA color. */
+
+/**
+ * art_render_clear: Set clear color.
+ * @clear_color: Color with which to clear dest.
+ *
+ * Sets clear color, equivalent to actually clearing the destination
+ * buffer before rendering. This is the most general form.
+ **/
+void
+art_render_clear (ArtRender *render, const ArtPixMaxDepth *clear_color)
+{
+  int i;
+  int n_ch = render->n_chan + (render->alpha_type != ART_ALPHA_NONE);
+
+  render->clear = ART_TRUE;
+  for (i = 0; i < n_ch; i++)
+    render->clear_color[i] = clear_color[i];
+}
+
+/**
+ * art_render_clear_rgb: Set clear color, given in RGB format.
+ * @clear_rgb: Clear color, in 0xRRGGBB format.
+ *
+ * Sets clear color, equivalent to actually clearing the destination
+ * buffer before rendering.
+ **/
+void
+art_render_clear_rgb (ArtRender *render, art_u32 clear_rgb)
+{
+  if (render->n_chan != 3)
+    art_warn ("art_render_clear_rgb: called on render with %d channels, only works with 3\n",
+             render->n_chan);
+  else
+    {
+      int r, g, b;
+
+      render->clear = ART_TRUE;
+      r = clear_rgb >> 16;
+      g = (clear_rgb >> 8) & 0xff;
+      b = clear_rgb & 0xff;
+      render->clear_color[0] = ART_PIX_MAX_FROM_8(r);
+      render->clear_color[1] = ART_PIX_MAX_FROM_8(g);
+      render->clear_color[2] = ART_PIX_MAX_FROM_8(b);
+    }
+}
+
+static void
+art_render_nop_done (ArtRenderCallback *self, ArtRender *render)
+{
+}
+
+static void
+art_render_clear_render_rgb8 (ArtRenderCallback *self, ArtRender *render,
+                             art_u8 *dest, int y)
+{
+  int width = render->x1 - render->x0;
+  art_u8 r, g, b;
+  ArtPixMaxDepth color_max;
+
+  color_max = render->clear_color[0];
+  r = ART_PIX_8_FROM_MAX (color_max);
+  color_max = render->clear_color[1];
+  g = ART_PIX_8_FROM_MAX (color_max);
+  color_max = render->clear_color[2];
+  b = ART_PIX_8_FROM_MAX (color_max);
+
+  art_rgb_fill_run (dest, r, g, b, width);
+}
+
+static void
+art_render_clear_render_8 (ArtRenderCallback *self, ArtRender *render,
+                          art_u8 *dest, int y)
+{
+  int width = render->x1 - render->x0;
+  int i, j;
+  int n_ch = render->n_chan + (render->alpha_type != ART_ALPHA_NONE);
+  int ix;
+  art_u8 color[ART_MAX_CHAN + 1];
+
+  for (j = 0; j < n_ch; j++)
+    {
+      ArtPixMaxDepth color_max = render->clear_color[j];
+      color[j] = ART_PIX_8_FROM_MAX (color_max);
+    }
+
+  ix = 0;
+  for (i = 0; i < width; i++)
+    for (j = 0; j < n_ch; j++)
+      dest[ix++] = color[j];
+}
+
+const ArtRenderCallback art_render_clear_rgb8_obj =
+{
+  art_render_clear_render_rgb8,
+  art_render_nop_done
+};
+
+const ArtRenderCallback art_render_clear_8_obj =
+{
+  art_render_clear_render_8,
+  art_render_nop_done
+};
+
+#if ART_MAX_DEPTH >= 16
+
+static void
+art_render_clear_render_16 (ArtRenderCallback *self, ArtRender *render,
+                           art_u8 *dest, int y)
+{
+  int width = render->x1 - render->x0;
+  int i, j;
+  int n_ch = render->n_chan + (render->alpha_type != ART_ALPHA_NONE);
+  int ix;
+  art_u16 *dest_16 = (art_u16 *)dest;
+  art_u8 color[ART_MAX_CHAN + 1];
+
+  for (j = 0; j < n_ch; j++)
+    {
+      int color_16 = render->clear_color[j];
+      color[j] = color_16;
+    }
+
+  ix = 0;
+  for (i = 0; i < width; i++)
+    for (j = 0; j < n_ch; j++)
+      dest_16[ix++] = color[j];
+}
+
+const ArtRenderCallback art_render_clear_16_obj =
+{
+  art_render_clear_render_16,
+  art_render_nop_done
+};
+
+#endif /* ART_MAX_DEPTH >= 16 */
+
+/* todo: inline */
+static ArtRenderCallback *
+art_render_choose_clear_callback (ArtRender *render)
+{
+  ArtRenderCallback *clear_callback;
+
+  if (render->depth == 8)
+    {
+      if (render->n_chan == 3 &&
+         render->alpha_type == ART_ALPHA_NONE)
+       clear_callback = (ArtRenderCallback *)&art_render_clear_rgb8_obj;
+      else
+       clear_callback = (ArtRenderCallback *)&art_render_clear_8_obj;
+    }
+#if ART_MAX_DEPTH >= 16
+  else if (render->depth == 16)
+    clear_callback = (ArtRenderCallback *)&art_render_clear_16_obj;
+#endif
+  else
+    {
+      art_die ("art_render_choose_clear_callback: inconsistent render->depth = %d\n",
+              render->depth);
+    }
+  return clear_callback;
+}
+
+#if 0
+/* todo: get around to writing this */
+static void
+art_render_composite_render_noa_8_norm (ArtRenderCallback *self, ArtRender *render,
+                                       art_u8 *dest, int y)
+{
+  int width = render->x1 - render->x0;
+
+}
+#endif
+
+/* This is the most general form of the function. It is slow but
+   (hopefully) correct. Actually, I'm still worried about roundoff
+   errors in the premul case - it seems to me that an off-by-one could
+   lead to overflow. */
+static void
+art_render_composite (ArtRenderCallback *self, ArtRender *render,
+                                       art_u8 *dest, int y)
+{
+  ArtRenderMaskRun *run = render->run;
+  art_u32 depth = render->depth;
+  int n_run = render->n_run;
+  int x0 = render->x0;
+  int x;
+  int run_x0, run_x1;
+  art_u8 *alpha_buf = render->alpha_buf;
+  art_u8 *image_buf = render->image_buf;
+  int i, j;
+  art_u32 tmp;
+  art_u32 run_alpha;
+  art_u32 alpha;
+  int image_ix;
+  art_u16 src[ART_MAX_CHAN + 1];
+  art_u16 dst[ART_MAX_CHAN + 1];
+  int n_chan = render->n_chan;
+  ArtAlphaType alpha_type = render->alpha_type;
+  int n_ch = n_chan + (alpha_type != ART_ALPHA_NONE);
+  int dst_pixstride = n_ch * (depth >> 3);
+  int buf_depth = render->buf_depth;
+  ArtAlphaType buf_alpha = render->buf_alpha;
+  int buf_n_ch = n_chan + (buf_alpha != ART_ALPHA_NONE);
+  int buf_pixstride = buf_n_ch * (buf_depth >> 3);
+  art_u8 *bufptr;
+  art_u32 src_alpha;
+  art_u32 src_mul;
+  art_u8 *dstptr;
+  art_u32 dst_alpha;
+  art_u32 dst_mul;
+
+  image_ix = 0;
+  for (i = 0; i < n_run - 1; i++)
+    {
+      run_x0 = run[i].x;
+      run_x1 = run[i + 1].x;
+      tmp = run[i].alpha;
+      if (tmp < 0x8100)
+       continue;
+
+      run_alpha = (tmp + (tmp >> 8) + (tmp >> 16) - 0x8000) >> 8; /* range [0 .. 0x10000] */
+      bufptr = image_buf + (run_x0 - x0) * buf_pixstride;
+      dstptr = dest + (run_x0 - x0) * dst_pixstride;
+      for (x = run_x0; x < run_x1; x++)
+       {
+         if (alpha_buf)
+           {
+             if (depth == 8)
+               {
+                 tmp = run_alpha * alpha_buf[x - x0] + 0x80;
+                 /* range 0x80 .. 0xff0080 */
+                 alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
+               }
+             else /* (depth == 16) */
+               {
+                 tmp = ((art_u16 *)alpha_buf)[x - x0];
+                 tmp = (run_alpha * tmp + 0x8000) >> 8;
+                 /* range 0x80 .. 0xffff80 */
+                 alpha = (tmp + (tmp >> 16)) >> 8;
+               }
+           }
+         else
+           alpha = run_alpha;
+         /* alpha is run_alpha * alpha_buf[x], range 0 .. 0x10000 */
+
+         /* convert (src pixel * alpha) to premul alpha form,
+            store in src as 0..0xffff range */
+         if (buf_alpha == ART_ALPHA_NONE)
+           {
+             src_alpha = alpha;
+             src_mul = src_alpha;
+           }
+         else
+           {
+             if (buf_depth == 8)
+               {
+                 tmp = alpha * bufptr[n_chan] + 0x80;
+                 /* range 0x80 .. 0xff0080 */
+                 src_alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
+               }
+             else /* (depth == 16) */
+               {
+                 tmp = ((art_u16 *)bufptr)[n_chan];
+                 tmp = (alpha * tmp + 0x8000) >> 8;
+                 /* range 0x80 .. 0xffff80 */
+                 src_alpha = (tmp + (tmp >> 16)) >> 8;
+               }
+             if (buf_alpha == ART_ALPHA_SEPARATE)
+               src_mul = src_alpha;
+             else /* buf_alpha == (ART_ALPHA_PREMUL) */
+               src_mul = alpha;
+           }
+         /* src_alpha is the (alpha of the source pixel * alpha),
+            range 0..0x10000 */
+
+         if (buf_depth == 8)
+           {
+             src_mul *= 0x101;
+             for (j = 0; j < n_chan; j++)
+               src[j] = (bufptr[j] * src_mul + 0x8000) >> 16;
+           }
+         else if (buf_depth == 16)
+           {
+             for (j = 0; j < n_chan; j++)
+               src[j] = (((art_u16 *)bufptr)[j] * src_mul + 0x8000) >> 16;
+           }
+         bufptr += buf_pixstride;
+
+         /* src[0..n_chan - 1] (range 0..0xffff) and src_alpha (range
+             0..0x10000) now contain the source pixel with
+             premultiplied alpha */
+
+         /* convert dst pixel to premul alpha form,
+            store in dst as 0..0xffff range */
+         if (alpha_type == ART_ALPHA_NONE)
+           {
+             dst_alpha = 0x10000;
+             dst_mul = dst_alpha;
+           }
+         else
+           {
+             if (depth == 8)
+               {
+                 tmp = dstptr[n_chan];
+                 /* range 0..0xff */
+                 dst_alpha = (tmp << 8) + tmp + (tmp >> 7);
+               }
+             else /* (depth == 16) */
+               {
+                 tmp = ((art_u16 *)bufptr)[n_chan];
+                 dst_alpha = (tmp + (tmp >> 15));
+               }
+             if (alpha_type == ART_ALPHA_SEPARATE)
+               dst_mul = dst_alpha;
+             else /* (alpha_type == ART_ALPHA_PREMUL) */
+               dst_mul = 0x10000;
+           }
+         /* dst_alpha is the alpha of the dest pixel,
+            range 0..0x10000 */
+
+         if (depth == 8)
+           {
+             dst_mul *= 0x101;
+             for (j = 0; j < n_chan; j++)
+               dst[j] = (dstptr[j] * dst_mul + 0x8000) >> 16;
+           }
+         else if (buf_depth == 16)
+           {
+             for (j = 0; j < n_chan; j++)
+               dst[j] = (((art_u16 *)dstptr)[j] * dst_mul + 0x8000) >> 16;
+           }
+
+         /* do the compositing, dst = (src over dst) */
+         for (j = 0; j < n_chan; j++)
+           {
+             art_u32 srcv, dstv;
+             art_u32 tmp;
+
+             srcv = src[j];
+             dstv = dst[j];
+             tmp = ((dstv * (0x10000 - src_alpha) + 0x8000) >> 16) + srcv;
+             tmp -= tmp >> 16;
+             dst[j] = tmp;
+           }
+
+         if (alpha_type == ART_ALPHA_NONE)
+           {
+             if (depth == 8)
+               dst_mul = 0xff;
+             else /* (depth == 16) */
+               dst_mul = 0xffff;
+           }
+         else
+           {
+             if (src_alpha >= 0x10000)
+               dst_alpha = 0x10000;
+             else
+               dst_alpha += ((((0x10000 - dst_alpha) * src_alpha) >> 8) + 0x80) >> 8;
+             if (alpha_type == ART_ALPHA_PREMUL || dst_alpha == 0)
+               {
+                 if (depth == 8)
+                   dst_mul = 0xff;
+                 else /* (depth == 16) */
+                   dst_mul = 0xffff;
+               }
+             else /* (ALPHA_TYPE == ART_ALPHA_SEPARATE && dst_alpha != 0) */
+               {
+                 if (depth == 8)
+                   dst_mul = 0xff0000 / dst_alpha;
+                 else /* (depth == 16) */
+                   dst_mul = 0xffff0000 / dst_alpha;
+               }
+           }
+         if (depth == 8)
+           {
+             for (j = 0; j < n_chan; j++)
+               dstptr[j] = (dst[j] * dst_mul + 0x8000) >> 16;
+             if (alpha_type != ART_ALPHA_NONE)
+               dstptr[n_chan] = (dst_alpha * 0xff + 0x8000) >> 16;
+           }
+         else if (depth == 16)
+           {
+             for (j = 0; j < n_chan; j++)
+               ((art_u16 *)dstptr)[j] = (dst[j] * dst_mul + 0x8000) >> 16;
+             if (alpha_type != ART_ALPHA_NONE)
+               dstptr[n_chan] = (dst_alpha * 0xffff + 0x8000) >> 16;
+           }
+         dstptr += dst_pixstride;
+       }
+    }
+}
+
+const ArtRenderCallback art_render_composite_obj =
+{
+  art_render_composite,
+  art_render_nop_done
+};
+
+static void
+art_render_composite_8 (ArtRenderCallback *self, ArtRender *render,
+                       art_u8 *dest, int y)
+{
+  ArtRenderMaskRun *run = render->run;
+  int n_run = render->n_run;
+  int x0 = render->x0;
+  int x;
+  int run_x0, run_x1;
+  art_u8 *alpha_buf = render->alpha_buf;
+  art_u8 *image_buf = render->image_buf;
+  int i, j;
+  art_u32 tmp;
+  art_u32 run_alpha;
+  art_u32 alpha;
+  int image_ix;
+  int n_chan = render->n_chan;
+  ArtAlphaType alpha_type = render->alpha_type;
+  int n_ch = n_chan + (alpha_type != ART_ALPHA_NONE);
+  int dst_pixstride = n_ch;
+  ArtAlphaType buf_alpha = render->buf_alpha;
+  int buf_n_ch = n_chan + (buf_alpha != ART_ALPHA_NONE);
+  int buf_pixstride = buf_n_ch;
+  art_u8 *bufptr;
+  art_u32 src_alpha;
+  art_u32 src_mul;
+  art_u8 *dstptr;
+  art_u32 dst_alpha;
+  art_u32 dst_mul, dst_save_mul;
+
+  image_ix = 0;
+  for (i = 0; i < n_run - 1; i++)
+    {
+      run_x0 = run[i].x;
+      run_x1 = run[i + 1].x;
+      tmp = run[i].alpha;
+      if (tmp < 0x10000)
+       continue;
+
+      run_alpha = (tmp + (tmp >> 8) + (tmp >> 16) - 0x8000) >> 8; /* range [0 .. 0x10000] */
+      bufptr = image_buf + (run_x0 - x0) * buf_pixstride;
+      dstptr = dest + (run_x0 - x0) * dst_pixstride;
+      for (x = run_x0; x < run_x1; x++)
+       {
+         if (alpha_buf)
+           {
+             tmp = run_alpha * alpha_buf[x - x0] + 0x80;
+             /* range 0x80 .. 0xff0080 */
+             alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
+           }
+         else
+           alpha = run_alpha;
+         /* alpha is run_alpha * alpha_buf[x], range 0 .. 0x10000 */
+
+         /* convert (src pixel * alpha) to premul alpha form,
+            store in src as 0..0xffff range */
+         if (buf_alpha == ART_ALPHA_NONE)
+           {
+             src_alpha = alpha;
+             src_mul = src_alpha;
+           }
+         else
+           {
+             tmp = alpha * bufptr[n_chan] + 0x80;
+             /* range 0x80 .. 0xff0080 */
+             src_alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
+
+             if (buf_alpha == ART_ALPHA_SEPARATE)
+               src_mul = src_alpha;
+             else /* buf_alpha == (ART_ALPHA_PREMUL) */
+               src_mul = alpha;
+           }
+         /* src_alpha is the (alpha of the source pixel * alpha),
+            range 0..0x10000 */
+
+         src_mul *= 0x101;
+
+         if (alpha_type == ART_ALPHA_NONE)
+           {
+             dst_alpha = 0x10000;
+             dst_mul = dst_alpha;
+           }
+         else
+           {
+             tmp = dstptr[n_chan];
+             /* range 0..0xff */
+             dst_alpha = (tmp << 8) + tmp + (tmp >> 7);
+             if (alpha_type == ART_ALPHA_SEPARATE)
+               dst_mul = dst_alpha;
+             else /* (alpha_type == ART_ALPHA_PREMUL) */
+               dst_mul = 0x10000;
+           }
+         /* dst_alpha is the alpha of the dest pixel,
+            range 0..0x10000 */
+
+         dst_mul *= 0x101;
+
+         if (alpha_type == ART_ALPHA_NONE)
+           {
+             dst_save_mul = 0xff;
+           }
+         else
+           {
+             if (src_alpha >= 0x10000)
+               dst_alpha = 0x10000;
+             else
+               dst_alpha += ((((0x10000 - dst_alpha) * src_alpha) >> 8) + 0x80) >> 8;
+             if (alpha_type == ART_ALPHA_PREMUL || dst_alpha == 0)
+               {
+                 dst_save_mul = 0xff;
+               }
+             else /* (ALPHA_TYPE == ART_ALPHA_SEPARATE && dst_alpha != 0) */
+               {
+                 dst_save_mul = 0xff0000 / dst_alpha;
+               }
+           }
+         for (j = 0; j < n_chan; j++)
+           {
+             art_u32 src, dst;
+             art_u32 tmp;
+
+             src = (bufptr[j] * src_mul + 0x8000) >> 16;
+             dst = (dstptr[j] * dst_mul + 0x8000) >> 16;
+             tmp = ((dst * (0x10000 - src_alpha) + 0x8000) >> 16) + src;
+             tmp -= tmp >> 16;
+             dstptr[j] = (tmp * dst_save_mul + 0x8000) >> 16;
+           }
+         if (alpha_type != ART_ALPHA_NONE)
+           dstptr[n_chan] = (dst_alpha * 0xff + 0x8000) >> 16;
+
+         bufptr += buf_pixstride;
+         dstptr += dst_pixstride;
+       }
+    }
+}
+
+const ArtRenderCallback art_render_composite_8_obj =
+{
+  art_render_composite_8,
+  art_render_nop_done
+};
+
+/* todo: inline */
+static ArtRenderCallback *
+art_render_choose_compositing_callback (ArtRender *render)
+{
+  if (render->depth == 8 && render->buf_depth == 8)
+    return (ArtRenderCallback *)&art_render_composite_8_obj;
+  return (ArtRenderCallback *)&art_render_composite_obj;
+}
+
+/**
+ * art_render_invoke_callbacks: Invoke the callbacks in the render object.
+ * @render: The render object.
+ * @y: The current Y coordinate value.
+ *
+ * Invokes the callbacks of the render object in the appropriate
+ * order.  Drivers should call this routine once per scanline.
+ *
+ * todo: should management of dest devolve to this routine? very
+ * plausibly yes.
+ **/
+void
+art_render_invoke_callbacks (ArtRender *render, art_u8 *dest, int y)
+{
+  ArtRenderPriv *priv = (ArtRenderPriv *)render;
+  int i;
+
+  for (i = 0; i < priv->n_callbacks; i++)
+    {
+      ArtRenderCallback *callback;
+
+      callback = priv->callbacks[i];
+      callback->render (callback, render, dest, y);
+    }
+}
+
+/**
+ * art_render_invoke: Perform the requested rendering task.
+ * @render: The render object.
+ *
+ * Invokes the renderer and all sources associated with it, to perform
+ * the requested rendering task.
+ **/
+void
+art_render_invoke (ArtRender *render)
+{
+  ArtRenderPriv *priv = (ArtRenderPriv *)render;
+  int width;
+  int best_driver, best_score;
+  int i;
+  int n_callbacks, n_callbacks_max;
+  ArtImageSource *image_source;
+  ArtImageSourceFlags image_flags;
+  int buf_depth;
+  ArtAlphaType buf_alpha;
+  art_boolean first = ART_TRUE;
+
+  if (render == NULL)
+    {
+      art_warn ("art_render_invoke: called with render == NULL\n");
+      return;
+    }
+  if (priv->image_source == NULL)
+    {
+      art_warn ("art_render_invoke: no image source given\n");
+      return;
+    }
+
+  width = render->x1 - render->x0;
+
+  render->run = art_new (ArtRenderMaskRun, width + 1);
+
+  /* Elect a mask source as driver. */
+  best_driver = -1;
+  best_score = 0;
+  for (i = 0; i < priv->n_mask_source; i++)
+    {
+      int score;
+      ArtMaskSource *mask_source;
+
+      mask_source = priv->mask_source[i];
+      score = mask_source->can_drive (mask_source, render);
+      if (score > best_score)
+       {
+         best_score = score;
+         best_driver = i;
+       }
+    }
+
+  /* Allocate alpha buffer if needed. */
+  if (priv->n_mask_source > 1 ||
+      (priv->n_mask_source == 1 && best_driver < 0))
+    {
+      render->alpha_buf = art_new (art_u8, (width * render->depth) >> 3);
+    }
+
+  /* Negotiate image rendering and compositing. */
+  image_source = priv->image_source;
+  image_source->negotiate (image_source, render, &image_flags, &buf_depth,
+                          &buf_alpha);
+
+  /* Build callback list. */
+  n_callbacks_max = priv->n_mask_source + 3;
+  priv->callbacks = art_new (ArtRenderCallback *, n_callbacks_max);
+  n_callbacks = 0;
+  for (i = 0; i < priv->n_mask_source; i++)
+    if (i != best_driver)
+      {
+       ArtMaskSource *mask_source = priv->mask_source[i];
+
+       mask_source->prepare (mask_source, render, first);
+       first = ART_FALSE;
+       priv->callbacks[n_callbacks++] = &mask_source->super;
+      }
+
+  if (render->clear && !(image_flags & ART_IMAGE_SOURCE_CAN_CLEAR))
+    priv->callbacks[n_callbacks++] =
+      art_render_choose_clear_callback (render);
+
+  priv->callbacks[n_callbacks++] = &image_source->super;
+
+  /* Allocate image buffer and add compositing callback if needed. */
+  if (!(image_flags & ART_IMAGE_SOURCE_CAN_COMPOSITE))
+    {
+      int bytespp = ((render->n_chan + (buf_alpha != ART_ALPHA_NONE)) *
+                    buf_depth) >> 3;
+      render->buf_depth = buf_depth;
+      render->buf_alpha = buf_alpha;
+      render->image_buf = art_new (art_u8, width * bytespp);
+      priv->callbacks[n_callbacks++] =
+       art_render_choose_compositing_callback (render);
+    }
+
+  priv->n_callbacks = n_callbacks;
+
+  if (render->need_span)
+    render->span_x = art_new (int, width + 1);
+
+  /* Invoke the driver */
+  if (best_driver >= 0)
+    {
+      ArtMaskSource *driver;
+
+      driver = priv->mask_source[best_driver];
+      driver->invoke_driver (driver, render);
+    }
+  else
+    {
+      art_u8 *dest_ptr = render->pixels;
+      int y;
+
+      /* Dummy driver */
+      render->n_run = 2;
+      render->run[0].x = render->x0;
+      render->run[0].alpha = 0x8000 + 0xff * render->opacity;
+      render->run[1].x = render->x1;
+      render->run[1].alpha = 0x8000;
+      if (render->need_span)
+       {
+         render->n_span = 2;
+         render->span_x[0] = render->x0;
+         render->span_x[1] = render->x1;
+       }
+      for (y = render->y0; y < render->y1; y++)
+       {
+         art_render_invoke_callbacks (render, dest_ptr, y);
+         dest_ptr += render->rowstride;
+       }
+    }
+
+  if (priv->mask_source != NULL)
+    art_free (priv->mask_source);
+
+  /* clean up callbacks */
+  for (i = 0; i < priv->n_callbacks; i++)
+    {
+      ArtRenderCallback *callback;
+
+      callback = priv->callbacks[i];
+      callback->done (callback, render);
+    }
+
+  /* Tear down object */
+  if (render->alpha_buf != NULL)
+    art_free (render->alpha_buf);
+  if (render->image_buf != NULL)
+    art_free (render->image_buf);
+  art_free (render->run);
+  if (render->span_x != NULL)
+    art_free (render->span_x);
+  art_free (priv->callbacks);
+  art_free (render);
+}
+
+/**
+ * art_render_mask_solid: Add a solid translucent mask.
+ * @render: The render object.
+ * @opacity: Opacity in [0..0x10000] form.
+ *
+ * Adds a translucent mask to the rendering object.
+ **/
+void
+art_render_mask_solid (ArtRender *render, int opacity)
+{
+  art_u32 old_opacity = render->opacity;
+  art_u32 new_opacity_tmp;
+
+  if (opacity == 0x10000)
+    /* avoid potential overflow */
+    return;
+  new_opacity_tmp = old_opacity * (art_u32)opacity + 0x8000;
+  render->opacity = new_opacity_tmp >> 16;
+}
+
+/**
+ * art_render_add_mask_source: Add a mask source to the render object.
+ * @render: Render object.
+ * @mask_source: Mask source to add.
+ *
+ * This routine adds a mask source to the render object. In general,
+ * client api's for adding mask sources should just take a render object,
+ * then the mask source creation function should call this function.
+ * Clients should never have to call this function directly, unless of
+ * course they're creating custom mask sources.
+ **/
+void
+art_render_add_mask_source (ArtRender *render, ArtMaskSource *mask_source)
+{
+  ArtRenderPriv *priv = (ArtRenderPriv *)render;
+  int n_mask_source = priv->n_mask_source++;
+
+  if (n_mask_source == 0)
+    priv->mask_source = art_new (ArtMaskSource *, 1);
+  /* This predicate is true iff n_mask_source is a power of two */
+  else if (!(n_mask_source & (n_mask_source - 1)))
+    priv->mask_source = art_renew (priv->mask_source, ArtMaskSource *,
+                                  n_mask_source << 1);
+
+  priv->mask_source[n_mask_source] = mask_source;
+}
+
+/**
+ * art_render_add_image_source: Add a mask source to the render object.
+ * @render: Render object.
+ * @image_source: Image source to add.
+ *
+ * This routine adds an image source to the render object. In general,
+ * client api's for adding image sources should just take a render
+ * object, then the mask source creation function should call this
+ * function.  Clients should never have to call this function
+ * directly, unless of course they're creating custom image sources.
+ **/
+void
+art_render_add_image_source (ArtRender *render, ArtImageSource *image_source)
+{
+  ArtRenderPriv *priv = (ArtRenderPriv *)render;
+
+  if (priv->image_source != NULL)
+    {
+      art_warn ("art_render_add_image_source: image source already present.\n");
+      return;
+    }
+  priv->image_source = image_source;
+}
+
+/* Solid image source object and methods. Perhaps this should go into a
+   separate file. */
+
+typedef struct _ArtImageSourceSolid ArtImageSourceSolid;
+
+struct _ArtImageSourceSolid {
+  ArtImageSource super;
+  ArtPixMaxDepth color[ART_MAX_CHAN];
+  art_u32 *rgbtab;
+  art_boolean init;
+};
+
+static void
+art_render_image_solid_done (ArtRenderCallback *self, ArtRender *render)
+{
+  ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
+
+  if (z->rgbtab != NULL)
+    art_free (z->rgbtab);
+  art_free (self);
+}
+
+static void
+art_render_image_solid_rgb8_opaq_init (ArtImageSourceSolid *self, ArtRender *render)
+{
+  ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
+  ArtPixMaxDepth color_max;
+  int r_fg, g_fg, b_fg;
+  int r_bg, g_bg, b_bg;
+  int r, g, b;
+  int dr, dg, db;
+  int i;
+  int tmp;
+  art_u32 *rgbtab;
+
+  rgbtab = art_new (art_u32, 256);
+  z->rgbtab = rgbtab;
+
+  color_max = self->color[0];
+  r_fg = ART_PIX_8_FROM_MAX (color_max);
+  color_max = self->color[1];
+  g_fg = ART_PIX_8_FROM_MAX (color_max);
+  color_max = self->color[2];
+  b_fg = ART_PIX_8_FROM_MAX (color_max);
+
+  color_max = render->clear_color[0];
+  r_bg = ART_PIX_8_FROM_MAX (color_max);
+  color_max = render->clear_color[1];
+  g_bg = ART_PIX_8_FROM_MAX (color_max);
+  color_max = render->clear_color[2];
+  b_bg = ART_PIX_8_FROM_MAX (color_max);
+
+  r = (r_bg << 16) + 0x8000;
+  g = (g_bg << 16) + 0x8000;
+  b = (b_bg << 16) + 0x8000;
+  tmp = ((r_fg - r_bg) << 16) + 0x80;
+  dr = (tmp + (tmp >> 8)) >> 8;
+  tmp = ((g_fg - g_bg) << 16) + 0x80;
+  dg = (tmp + (tmp >> 8)) >> 8;
+  tmp = ((b_fg - b_bg) << 16) + 0x80;
+  db = (tmp + (tmp >> 8)) >> 8;
+
+  for (i = 0; i < 256; i++)
+    {
+      rgbtab[i] = (r & 0xff0000) | ((g & 0xff0000) >> 8) | (b >> 16);
+      r += dr;
+      g += dg;
+      b += db;
+    }
+}
+
+static void
+art_render_image_solid_rgb8_opaq (ArtRenderCallback *self, ArtRender *render,
+                                 art_u8 *dest, int y)
+{
+  ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
+  ArtRenderMaskRun *run = render->run;
+  int n_run = render->n_run;
+  art_u32 *rgbtab = z->rgbtab;
+  art_u32 rgb;
+  int x0 = render->x0;
+  int x1 = render->x1;
+  int run_x0, run_x1;
+  int i;
+  int ix;
+
+  if (n_run > 0)
+    {
+      run_x1 = run[0].x;
+      if (run_x1 > x0)
+       {
+         rgb = rgbtab[0];
+         art_rgb_fill_run (dest,
+                           rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+                           run_x1 - x0);
+       }
+      for (i = 0; i < n_run - 1; i++)
+       {
+         run_x0 = run_x1;
+         run_x1 = run[i + 1].x;
+         rgb = rgbtab[(run[i].alpha >> 16) & 0xff];
+         ix = (run_x0 - x0) * 3;
+#define OPTIMIZE_LEN_1
+#ifdef OPTIMIZE_LEN_1
+         if (run_x1 - run_x0 == 1)
+           {
+             dest[ix] = rgb >> 16;
+             dest[ix + 1] = (rgb >> 8) & 0xff;
+             dest[ix + 2] = rgb & 0xff;
+           }
+         else
+           {
+             art_rgb_fill_run (dest + ix,
+                               rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+                               run_x1 - run_x0);
+           }
+#else
+         art_rgb_fill_run (dest + ix,
+                           rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+                           run_x1 - run_x0);
+#endif
+       }
+    }
+  else
+    {
+      run_x1 = x0;
+    }
+  if (run_x1 < x1)
+    {
+      rgb = rgbtab[0];
+      art_rgb_fill_run (dest + (run_x1 - x0) * 3,
+                       rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+                       x1 - run_x1);
+    }
+}
+
+static void
+art_render_image_solid_rgb8 (ArtRenderCallback *self, ArtRender *render,
+                            art_u8 *dest, int y)
+{
+  ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
+  int width = render->x1 - render->x0;
+  art_u8 r, g, b;
+  ArtPixMaxDepth color_max;
+
+  /* todo: replace this simple test with real sparseness */
+  if (z->init)
+    return;
+  z->init = ART_TRUE;
+
+  color_max = z->color[0];
+  r = ART_PIX_8_FROM_MAX (color_max);
+  color_max = z->color[1];
+  g = ART_PIX_8_FROM_MAX (color_max);
+  color_max = z->color[2];
+  b = ART_PIX_8_FROM_MAX (color_max);
+
+  art_rgb_fill_run (render->image_buf, r, g, b, width);
+}
+
+static void
+art_render_image_solid_negotiate (ArtImageSource *self, ArtRender *render,
+                                 ArtImageSourceFlags *p_flags,
+                                 int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+  ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
+  ArtImageSourceFlags flags = 0;
+  static void (*render_cbk) (ArtRenderCallback *self, ArtRender *render,
+                            art_u8 *dest, int y);
+
+  render_cbk = NULL;
+
+  if (render->depth == 8 && render->n_chan == 3 &&
+      render->alpha_type == ART_ALPHA_NONE)
+    {
+      if (render->clear)
+       {
+         render_cbk = art_render_image_solid_rgb8_opaq;
+         flags |= ART_IMAGE_SOURCE_CAN_CLEAR | ART_IMAGE_SOURCE_CAN_COMPOSITE;
+         art_render_image_solid_rgb8_opaq_init (z, render);
+       }
+    }
+  if (render_cbk == NULL)
+    {
+      if (render->depth == 8)
+       {
+         render_cbk = art_render_image_solid_rgb8;
+         *p_buf_depth = 8;
+         *p_alpha = ART_ALPHA_NONE; /* todo */
+       }
+    }
+  /* todo: general case */
+  self->super.render = render_cbk;
+  *p_flags = flags;
+}
+
+/**
+ * art_render_image_solid: Add a solid color image source.
+ * @render: The render object.
+ * @color: Color.
+ *
+ * Adds an image source with the solid color given by @color. The
+ * color need not be retained in memory after this call.
+ **/
+void
+art_render_image_solid (ArtRender *render, ArtPixMaxDepth *color)
+{
+  ArtImageSourceSolid *image_source;
+  int i;
+
+  image_source = art_new (ArtImageSourceSolid, 1);
+  image_source->super.super.render = NULL;
+  image_source->super.super.done = art_render_image_solid_done;
+  image_source->super.negotiate = art_render_image_solid_negotiate;
+
+  for (i = 0; i < render->n_chan; i++)
+    image_source->color[i] = color[i];
+
+  image_source->rgbtab = NULL;
+  image_source->init = ART_FALSE;
+
+  art_render_add_image_source (render, &image_source->super);
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_render.h b/libraries/libart_lgpl-2.3.7/art_render.h
new file mode 100644 (file)
index 0000000..b06ce8b
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * art_render.h: Modular rendering architecture.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RENDER_H__
+#define __ART_RENDER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Render object */
+
+#ifndef ART_MAX_DEPTH
+#define ART_MAX_DEPTH 16
+#endif
+
+#if ART_MAX_DEPTH == 16
+typedef art_u16 ArtPixMaxDepth;
+#define ART_PIX_MAX_FROM_8(x) ((x) | ((x) << 8))
+#define ART_PIX_8_FROM_MAX(x) (((x) + 0x80 - (((x) + 0x80) >> 8)) >> 8)
+#else
+#if ART_MAX_DEPTH == 8
+typedef art_u8 ArtPixMaxDepth;
+#define ART_PIX_MAX_FROM_8(x) (x)
+#define ART_PIX_8_FROM_MAX(x) (x)
+#else
+#error ART_MAX_DEPTH must be either 8 or 16
+#endif
+#endif
+
+#define ART_MAX_CHAN 16
+
+typedef struct _ArtRender ArtRender;
+typedef struct _ArtRenderCallback ArtRenderCallback;
+typedef struct _ArtRenderMaskRun ArtRenderMaskRun;
+typedef struct _ArtImageSource ArtImageSource;
+typedef struct _ArtMaskSource ArtMaskSource;
+
+typedef enum {
+  ART_ALPHA_NONE      = 0,
+  ART_ALPHA_SEPARATE  = 1,
+  ART_ALPHA_PREMUL    = 2
+} ArtAlphaType;
+
+typedef enum {
+  ART_COMPOSITE_NORMAL,
+  ART_COMPOSITE_MULTIPLY,
+  /* todo: more */
+  ART_COMPOSITE_CUSTOM
+} ArtCompositingMode;
+
+typedef enum {
+  ART_IMAGE_SOURCE_CAN_CLEAR = 1,
+  ART_IMAGE_SOURCE_CAN_COMPOSITE = 2
+} ArtImageSourceFlags;
+
+struct _ArtRenderMaskRun {
+  int x;
+  int alpha;
+};
+
+struct _ArtRenderCallback {
+  void (*render) (ArtRenderCallback *self, ArtRender *render,
+                 art_u8 *dest, int y);
+  void (*done) (ArtRenderCallback *self, ArtRender *render);
+};
+
+struct _ArtImageSource {
+  ArtRenderCallback super;
+  void (*negotiate) (ArtImageSource *self, ArtRender *render,
+                    ArtImageSourceFlags *p_flags,
+                    int *p_buf_depth, ArtAlphaType *p_alpha_type);
+};
+
+struct _ArtMaskSource {
+  ArtRenderCallback super;
+  int (*can_drive) (ArtMaskSource *self, ArtRender *render);
+  /* For each mask source, ::prepare() is invoked if it is not
+     a driver, or ::invoke_driver() if it is. */
+  void (*invoke_driver) (ArtMaskSource *self, ArtRender *render);
+  void (*prepare) (ArtMaskSource *self, ArtRender *render, art_boolean first);
+};
+
+struct _ArtRender {
+  /* parameters of destination image */
+  int x0, y0;
+  int x1, y1;
+  art_u8 *pixels;
+  int rowstride;
+  int n_chan;
+  int depth;
+  ArtAlphaType alpha_type;
+
+  art_boolean clear;
+  ArtPixMaxDepth clear_color[ART_MAX_CHAN + 1];
+  art_u32 opacity; /* [0..0x10000] */
+
+  ArtCompositingMode compositing_mode;
+
+  ArtAlphaGamma *alphagamma;
+
+  art_u8 *alpha_buf;
+
+  /* parameters of intermediate buffer */
+  int buf_depth;
+  ArtAlphaType buf_alpha;
+  art_u8 *image_buf;
+
+  /* driving alpha scanline data */
+  /* A "run" is a contiguous sequence of x values with the same alpha value. */
+  int n_run;
+  ArtRenderMaskRun *run;
+
+  /* A "span" is a contiguous sequence of x values with non-zero alpha. */
+  int n_span;
+  int *span_x;
+
+  art_boolean need_span;
+};
+
+ArtRender *
+art_render_new (int x0, int y0, int x1, int y1,
+               art_u8 *pixels, int rowstride,
+               int n_chan, int depth, ArtAlphaType alpha_type,
+               ArtAlphaGamma *alphagamma);
+
+void
+art_render_invoke (ArtRender *render);
+
+void
+art_render_clear (ArtRender *render, const ArtPixMaxDepth *clear_color);
+
+void
+art_render_clear_rgb (ArtRender *render, art_u32 clear_rgb);
+
+void
+art_render_mask_solid (ArtRender *render, int opacity);
+
+void
+art_render_image_solid (ArtRender *render, ArtPixMaxDepth *color);
+
+/* The next two functions are for custom mask sources only. */
+void
+art_render_add_mask_source (ArtRender *render, ArtMaskSource *mask_source);
+
+void
+art_render_invoke_callbacks (ArtRender *render, art_u8 *dest, int y);
+
+/* The following function is for custom image sources only. */
+void
+art_render_add_image_source (ArtRender *render, ArtImageSource *image_source);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RENDER_H__ */
+
diff --git a/libraries/libart_lgpl-2.3.7/art_render_gradient.c b/libraries/libart_lgpl-2.3.7/art_render_gradient.c
new file mode 100644 (file)
index 0000000..d84dad8
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * art_render_gradient.c: Gradient image source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien <raph@acm.org>
+ *          Alexander Larsson <alla@lysator.liu.se>
+ */
+
+#include <math.h>
+
+#include "art_misc.h"
+#include "art_alphagamma.h"
+#include "art_filterlevel.h"
+
+#include "art_render.h"
+#include "art_render_gradient.h"
+
+typedef struct _ArtImageSourceGradLin ArtImageSourceGradLin;
+typedef struct _ArtImageSourceGradRad ArtImageSourceGradRad;
+
+struct _ArtImageSourceGradLin {
+  ArtImageSource super;
+  const ArtGradientLinear *gradient;
+};
+
+struct _ArtImageSourceGradRad {
+  ArtImageSource super;
+  const ArtGradientRadial *gradient;
+  double a;
+};
+
+#define EPSILON 1e-6
+
+/**
+ * art_render_gradient_setpix: Set a gradient pixel.
+ * @render: The render object.
+ * @dst: Pointer to destination (where to store pixel).
+ * @n_stops: Number of stops in @stops.
+ * @stops: The stops for the gradient.
+ * @offset: The offset.
+ *
+ * @n_stops must be > 0.
+ *
+ * Sets a gradient pixel, storing it at @dst.
+ **/
+static void
+art_render_gradient_setpix (ArtRender *render,
+                           art_u8 *dst,
+                           int n_stops, ArtGradientStop *stops,
+                           double offset)
+{
+  int ix;
+  int j;
+  double off0, off1;
+  int n_ch = render->n_chan + 1;
+
+  for (ix = 0; ix < n_stops; ix++)
+    if (stops[ix].offset > offset)
+      break;
+  /* stops[ix - 1].offset < offset < stops[ix].offset */
+  if (ix > 0 && ix < n_stops)
+    {
+      off0 = stops[ix - 1].offset;
+      off1 = stops[ix].offset;
+      if (fabs (off1 - off0) > EPSILON)
+       {
+         double interp;
+
+         interp = (offset - off0) / (off1 - off0);
+         for (j = 0; j < n_ch; j++)
+           {
+             int z0, z1;
+             int z;
+             z0 = stops[ix - 1].color[j];
+             z1 = stops[ix].color[j];
+             z = floor (z0 + (z1 - z0) * interp + 0.5);
+             if (render->buf_depth == 8)
+               dst[j] = ART_PIX_8_FROM_MAX (z);
+             else /* (render->buf_depth == 16) */
+               ((art_u16 *)dst)[j] = z;
+           }
+         return;
+       }
+    }
+  else if (ix == n_stops)
+    ix--;
+
+  for (j = 0; j < n_ch; j++)
+    {
+      int z;
+      z = stops[ix].color[j];
+      if (render->buf_depth == 8)
+       dst[j] = ART_PIX_8_FROM_MAX (z);
+      else /* (render->buf_depth == 16) */
+       ((art_u16 *)dst)[j] = z;
+    }
+}
+
+static void
+art_render_gradient_linear_done (ArtRenderCallback *self, ArtRender *render)
+{
+  art_free (self);
+}
+
+static void
+art_render_gradient_linear_render (ArtRenderCallback *self, ArtRender *render,
+                                  art_u8 *dest, int y)
+{
+  ArtImageSourceGradLin *z = (ArtImageSourceGradLin *)self;
+  const ArtGradientLinear *gradient = z->gradient;
+  int pixstride = (render->n_chan + 1) * (render->depth >> 3);
+  int x;
+  int width = render->x1 - render->x0;
+  double offset, d_offset;
+  double actual_offset;
+  int n_stops = gradient->n_stops;
+  ArtGradientStop *stops = gradient->stops;
+  art_u8 *bufp = render->image_buf;
+  ArtGradientSpread spread = gradient->spread;
+
+  offset = render->x0 * gradient->a + y * gradient->b + gradient->c;
+  d_offset = gradient->a;
+
+  for (x = 0; x < width; x++)
+    {
+      if (spread == ART_GRADIENT_PAD)
+       actual_offset = offset;
+      else if (spread == ART_GRADIENT_REPEAT)
+       actual_offset = offset - floor (offset);
+      else /* (spread == ART_GRADIENT_REFLECT) */
+       {
+         double tmp;
+
+         tmp = offset - 2 * floor (0.5 * offset);
+         actual_offset = tmp > 1 ? 2 - tmp : tmp;
+       }
+      art_render_gradient_setpix (render, bufp, n_stops, stops, actual_offset);
+      offset += d_offset;
+      bufp += pixstride;
+    }
+}
+
+static void
+art_render_gradient_linear_negotiate (ArtImageSource *self, ArtRender *render,
+                                     ArtImageSourceFlags *p_flags,
+                                     int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+  self->super.render = art_render_gradient_linear_render;
+  *p_flags = 0;
+  *p_buf_depth = render->depth;
+  *p_alpha = ART_ALPHA_PREMUL;
+}
+
+/**
+ * art_render_gradient_linear: Add a linear gradient image source.
+ * @render: The render object.
+ * @gradient: The linear gradient.
+ *
+ * Adds the linear gradient @gradient as the image source for rendering
+ * in the render object @render.
+ **/
+void
+art_render_gradient_linear (ArtRender *render,
+                           const ArtGradientLinear *gradient,
+                           ArtFilterLevel level)
+{
+  ArtImageSourceGradLin *image_source = art_new (ArtImageSourceGradLin, 1);
+
+  image_source->super.super.render = NULL;
+  image_source->super.super.done = art_render_gradient_linear_done;
+  image_source->super.negotiate = art_render_gradient_linear_negotiate;
+
+  image_source->gradient = gradient;
+
+  art_render_add_image_source (render, &image_source->super);
+}
+
+static void
+art_render_gradient_radial_done (ArtRenderCallback *self, ArtRender *render)
+{
+  art_free (self);
+}
+
+static void
+art_render_gradient_radial_render (ArtRenderCallback *self, ArtRender *render,
+                                  art_u8 *dest, int y)
+{
+  ArtImageSourceGradRad *z = (ArtImageSourceGradRad *)self;
+  const ArtGradientRadial *gradient = z->gradient;
+  int pixstride = (render->n_chan + 1) * (render->depth >> 3);
+  int x;
+  int x0 = render->x0;
+  int width = render->x1 - x0;
+  int n_stops = gradient->n_stops;
+  ArtGradientStop *stops = gradient->stops;
+  art_u8 *bufp = render->image_buf;
+  double fx = gradient->fx;
+  double fy = gradient->fy;
+  double dx, dy;
+  double *affine = gradient->affine;
+  double aff0 = affine[0];
+  double aff1 = affine[1];
+  const double a = z->a;
+  const double arecip = 1.0 / a;
+  double b, db;
+  double c, dc, ddc;
+  double b_a, db_a;
+  double rad, drad, ddrad;
+
+  dx = x0 * aff0 + y * affine[2] + affine[4] - fx;
+  dy = x0 * aff1 + y * affine[3] + affine[5] - fy;
+  b = dx * fx + dy * fy;
+  db = aff0 * fx + aff1 * fy;
+  c = dx * dx + dy * dy;
+  dc = 2 * aff0 * dx + aff0 * aff0 + 2 * aff1 * dy + aff1 * aff1;
+  ddc = 2 * aff0 * aff0 + 2 * aff1 * aff1;
+
+  b_a = b * arecip;
+  db_a = db * arecip;
+
+  rad = b_a * b_a + c * arecip;
+  drad = 2 * b_a * db_a + db_a * db_a + dc * arecip;
+  ddrad = 2 * db_a * db_a + ddc * arecip;
+
+  for (x = 0; x < width; x++)
+    {
+      double z;
+
+      if (rad > 0)
+       z = b_a + sqrt (rad);
+      else
+       z = b_a;
+      art_render_gradient_setpix (render, bufp, n_stops, stops, z);
+      bufp += pixstride;
+      b_a += db_a;
+      rad += drad;
+      drad += ddrad;
+    }
+}
+
+static void
+art_render_gradient_radial_negotiate (ArtImageSource *self, ArtRender *render,
+                                     ArtImageSourceFlags *p_flags,
+                                     int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+  self->super.render = art_render_gradient_radial_render;
+  *p_flags = 0;
+  *p_buf_depth = render->depth;
+  *p_alpha = ART_ALPHA_PREMUL;
+}
+
+/**
+ * art_render_gradient_radial: Add a radial gradient image source.
+ * @render: The render object.
+ * @gradient: The radial gradient.
+ *
+ * Adds the radial gradient @gradient as the image source for rendering
+ * in the render object @render.
+ **/
+void
+art_render_gradient_radial (ArtRender *render,
+                           const ArtGradientRadial *gradient,
+                           ArtFilterLevel level)
+{
+  ArtImageSourceGradRad *image_source = art_new (ArtImageSourceGradRad, 1);
+  double fx = gradient->fx;
+  double fy = gradient->fy;
+
+  image_source->super.super.render = NULL;
+  image_source->super.super.done = art_render_gradient_radial_done;
+  image_source->super.negotiate = art_render_gradient_radial_negotiate;
+
+  image_source->gradient = gradient;
+  /* todo: sanitycheck fx, fy? */
+  image_source->a = 1 - fx * fx - fy * fy;
+
+  art_render_add_image_source (render, &image_source->super);
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_render_gradient.h b/libraries/libart_lgpl-2.3.7/art_render_gradient.h
new file mode 100644 (file)
index 0000000..b76e6bd
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * art_render_gradient.h: Gradient image source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien <raph@acm.org>
+ *          Alexander Larsson <alla@lysator.liu.se>
+ */
+
+#ifndef __ART_RENDER_GRADIENT_H__
+#define __ART_RENDER_GRADIENT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtGradientLinear ArtGradientLinear;
+typedef struct _ArtGradientRadial ArtGradientRadial;
+typedef struct _ArtGradientStop ArtGradientStop;
+
+typedef enum {
+  ART_GRADIENT_PAD,
+  ART_GRADIENT_REFLECT,
+  ART_GRADIENT_REPEAT
+} ArtGradientSpread;
+
+struct _ArtGradientLinear {
+  double a;
+  double b;
+  double c;
+  ArtGradientSpread spread;
+  int n_stops;
+  ArtGradientStop *stops;
+};
+
+struct _ArtGradientRadial {
+  double affine[6]; /* transforms user coordinates to unit circle */
+  double fx, fy;    /* focal point in unit circle coords */
+  int n_stops;
+  ArtGradientStop *stops;
+};
+
+struct _ArtGradientStop {
+  double offset;
+  ArtPixMaxDepth color[ART_MAX_CHAN + 1];
+};
+
+void
+art_render_gradient_linear (ArtRender *render,
+                           const ArtGradientLinear *gradient,
+                           ArtFilterLevel level);
+
+void
+art_render_gradient_radial (ArtRender *render,
+                           const ArtGradientRadial *gradient,
+                           ArtFilterLevel level);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RENDER_GRADIENT_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_render_svp.c b/libraries/libart_lgpl-2.3.7/art_render_svp.c
new file mode 100644 (file)
index 0000000..885f66b
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * art_render_gradient.c: SVP mask source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien <raph@acm.org>
+ */
+
+#include "art_misc.h"
+#include "art_alphagamma.h"
+#include "art_svp.h"
+#include "art_svp_render_aa.h"
+
+#include "art_render.h"
+#include "art_render_svp.h"
+
+typedef struct _ArtMaskSourceSVP ArtMaskSourceSVP;
+
+struct _ArtMaskSourceSVP {
+  ArtMaskSource super;
+  ArtRender *render;
+  const ArtSVP *svp;
+  art_u8 *dest_ptr;
+};
+
+static void
+art_render_svp_done (ArtRenderCallback *self, ArtRender *render)
+{
+  art_free (self);
+}
+
+static int
+art_render_svp_can_drive (ArtMaskSource *self, ArtRender *render)
+{
+  return 10;
+}
+
+/* The basic art_render_svp_callback function is repeated four times,
+   for all combinations of non-unit opacity and generating spans. In
+   general, I'd consider this bad style, but in this case I plead
+   a measurable performance improvement. */
+
+static void
+art_render_svp_callback (void *callback_data, int y,
+                        int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+  ArtRender *render = z->render;
+  int n_run = 0;
+  int i;
+  int running_sum = start;
+  int x0 = render->x0;
+  int x1 = render->x1;
+  int run_x0, run_x1;
+  ArtRenderMaskRun *run = render->run;
+
+  if (n_steps > 0)
+    {
+      run_x1 = steps[0].x;
+      if (run_x1 > x0 && running_sum > 0x80ff)
+       {
+         run[0].x = x0;
+         run[0].alpha = running_sum;
+         n_run++;
+       }
+
+      for (i = 0; i < n_steps - 1; i++)
+       {
+          running_sum += steps[i].delta;
+          run_x0 = run_x1;
+          run_x1 = steps[i + 1].x;
+         if (run_x1 > run_x0)
+           {
+             run[n_run].x = run_x0;
+             run[n_run].alpha = running_sum;
+             n_run++;
+           }
+       }
+      if (x1 > run_x1)
+       {
+         running_sum += steps[n_steps - 1].delta;
+         run[n_run].x = run_x1;
+         run[n_run].alpha = running_sum;
+         n_run++;
+       }
+      if (running_sum > 0x80ff)
+       {
+         run[n_run].x = x1;
+         run[n_run].alpha = 0x8000;
+         n_run++;
+       }
+    }
+
+  render->n_run = n_run;
+
+  art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+  z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_callback_span (void *callback_data, int y,
+                             int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+  ArtRender *render = z->render;
+  int n_run = 0;
+  int n_span = 0;
+  int i;
+  int running_sum = start;
+  int x0 = render->x0;
+  int x1 = render->x1;
+  int run_x0, run_x1;
+  ArtRenderMaskRun *run = render->run;
+  int *span_x = render->span_x;
+
+  if (n_steps > 0)
+    {
+      run_x1 = steps[0].x;
+      if (run_x1 > x0 && running_sum > 0x80ff)
+       {
+         run[0].x = x0;
+         run[0].alpha = running_sum;
+         n_run++;
+         span_x[0] = x0;
+         n_span++;
+       }
+
+      for (i = 0; i < n_steps - 1; i++)
+       {
+          running_sum += steps[i].delta;
+          run_x0 = run_x1;
+          run_x1 = steps[i + 1].x;
+         if (run_x1 > run_x0)
+           {
+             run[n_run].x = run_x0;
+             run[n_run].alpha = running_sum;
+             n_run++;
+             if ((n_span & 1) != (running_sum > 0x80ff))
+               span_x[n_span++] = run_x0;
+           }
+       }
+      if (x1 > run_x1)
+       {
+         running_sum += steps[n_steps - 1].delta;
+         run[n_run].x = run_x1;
+         run[n_run].alpha = running_sum;
+         n_run++;
+         if ((n_span & 1) != (running_sum > 0x80ff))
+           span_x[n_span++] = run_x1;
+       }
+      if (running_sum > 0x80ff)
+       {
+         run[n_run].x = x1;
+         run[n_run].alpha = 0x8000;
+         n_run++;
+         span_x[n_span++] = x1;
+       }
+    }
+
+  render->n_run = n_run;
+  render->n_span = n_span;
+
+  art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+  z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_callback_opacity (void *callback_data, int y,
+                                int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+  ArtRender *render = z->render;
+  int n_run = 0;
+  int i;
+  art_u32 running_sum;
+  int x0 = render->x0;
+  int x1 = render->x1;
+  int run_x0, run_x1;
+  ArtRenderMaskRun *run = render->run;
+  art_u32 opacity = render->opacity;
+  art_u32 alpha;
+
+  running_sum = start - 0x7f80;
+
+  if (n_steps > 0)
+    {
+      run_x1 = steps[0].x;
+      alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
+      if (run_x1 > x0 && alpha > 0x80ff)
+       {
+         run[0].x = x0;
+         run[0].alpha = alpha;
+         n_run++;
+       }
+
+      for (i = 0; i < n_steps - 1; i++)
+       {
+          running_sum += steps[i].delta;
+          run_x0 = run_x1;
+          run_x1 = steps[i + 1].x;
+         if (run_x1 > run_x0)
+           {
+             run[n_run].x = run_x0;
+             alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
+             run[n_run].alpha = alpha;
+             n_run++;
+           }
+       }
+      if (x1 > run_x1)
+       {
+         running_sum += steps[n_steps - 1].delta;
+         run[n_run].x = run_x1;
+         alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
+         run[n_run].alpha = alpha;
+         n_run++;
+       }
+      if (alpha > 0x80ff)
+       {
+         run[n_run].x = x1;
+         run[n_run].alpha = 0x8000;
+         n_run++;
+       }
+    }
+
+  render->n_run = n_run;
+
+  art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+  z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_callback_opacity_span (void *callback_data, int y,
+                                     int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+  ArtRender *render = z->render;
+  int n_run = 0;
+  int n_span = 0;
+  int i;
+  art_u32 running_sum;
+  int x0 = render->x0;
+  int x1 = render->x1;
+  int run_x0, run_x1;
+  ArtRenderMaskRun *run = render->run;
+  int *span_x = render->span_x;
+  art_u32 opacity = render->opacity;
+  art_u32 alpha;
+
+  running_sum = start - 0x7f80;
+
+  if (n_steps > 0)
+    {
+      run_x1 = steps[0].x;
+      alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
+      if (run_x1 > x0 && alpha > 0x80ff)
+       {
+         run[0].x = x0;
+         run[0].alpha = alpha;
+         n_run++;
+         span_x[0] = x0;
+         n_span++;
+       }
+
+      for (i = 0; i < n_steps - 1; i++)
+       {
+          running_sum += steps[i].delta;
+          run_x0 = run_x1;
+          run_x1 = steps[i + 1].x;
+         if (run_x1 > run_x0)
+           {
+             run[n_run].x = run_x0;
+             alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
+             run[n_run].alpha = alpha;
+             n_run++;
+             if ((n_span & 1) != (alpha > 0x80ff))
+               span_x[n_span++] = run_x0;
+           }
+       }
+      if (x1 > run_x1)
+       {
+         running_sum += steps[n_steps - 1].delta;
+         run[n_run].x = run_x1;
+         alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
+         run[n_run].alpha = alpha;
+         n_run++;
+         if ((n_span & 1) != (alpha > 0x80ff))
+           span_x[n_span++] = run_x1;
+       }
+      if (alpha > 0x80ff)
+       {
+         run[n_run].x = x1;
+         run[n_run].alpha = 0x8000;
+         n_run++;
+         span_x[n_span++] = x1;
+       }
+    }
+
+  render->n_run = n_run;
+  render->n_span = n_span;
+
+  art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+  z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_invoke_driver (ArtMaskSource *self, ArtRender *render)
+{
+  ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)self;
+  void (*callback) (void *callback_data,
+                   int y,
+                   int start,
+                   ArtSVPRenderAAStep *steps, int n_steps);
+
+  z->dest_ptr = render->pixels;
+  if (render->opacity == 0x10000)
+    {
+      if (render->need_span)
+       callback = art_render_svp_callback_span;
+      else
+       callback = art_render_svp_callback;
+    }
+  else
+    {
+      if (render->need_span)
+       callback = art_render_svp_callback_opacity_span;
+      else
+       callback = art_render_svp_callback_opacity;
+    }
+
+  art_svp_render_aa (z->svp,
+                    render->x0, render->y0,
+                    render->x1, render->y1, callback,
+                    self);
+  art_render_svp_done (&self->super, render);
+}
+
+static void
+art_render_svp_prepare (ArtMaskSource *self, ArtRender *render,
+                       art_boolean first)
+{
+  /* todo */
+  art_die ("art_render_svp non-driver mode not yet implemented.\n");
+}
+
+/**
+ * art_render_svp: Use an SVP as a render mask source.
+ * @render: Render object.
+ * @svp: SVP.
+ *
+ * Adds @svp to the render object as a mask. Note: @svp must remain
+ * allocated until art_render_invoke() is called on @render.
+ **/
+void
+art_render_svp (ArtRender *render, const ArtSVP *svp)
+{
+  ArtMaskSourceSVP *mask_source;
+  mask_source = art_new (ArtMaskSourceSVP, 1);
+
+  mask_source->super.super.render = NULL;
+  mask_source->super.super.done = art_render_svp_done;
+  mask_source->super.can_drive = art_render_svp_can_drive;
+  mask_source->super.invoke_driver = art_render_svp_invoke_driver;
+  mask_source->super.prepare = art_render_svp_prepare;
+  mask_source->render = render;
+  mask_source->svp = svp;
+
+  art_render_add_mask_source (render, &mask_source->super);
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_render_svp.h b/libraries/libart_lgpl-2.3.7/art_render_svp.h
new file mode 100644 (file)
index 0000000..fe9eb2a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * art_render_gradient.h: SVP mask source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien <raph@acm.org>
+ */
+
+#ifndef __ART_RENDER_SVP_H__
+#define __ART_RENDER_SVP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_render_svp (ArtRender *render, const ArtSVP *svp);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RENDER_SVP_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb.c b/libraries/libart_lgpl-2.3.7/art_rgb.c
new file mode 100644 (file)
index 0000000..fab50ab
--- /dev/null
@@ -0,0 +1,176 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>    /* for memset */
+#include "art_misc.h"
+#include "art_rgb.h"
+
+#include "config.h" /* for endianness */
+
+/* Basic operators for manipulating 24-bit packed RGB buffers. */
+
+#define COLOR_RUN_COMPLEX
+
+#ifdef COLOR_RUN_SIMPLE
+/* This is really slow. Is there any way we might speed it up?
+   Two ideas:
+
+   First, maybe we should be working at 32-bit alignment. Then,
+   this can be a simple loop over word stores.
+
+   Second, we can keep working at 24-bit alignment, but have some
+   intelligence about storing. For example, we can iterate over
+   4-pixel chunks (aligned at 4 pixels), with an inner loop
+   something like:
+
+   *buf++ = v1;
+   *buf++ = v2;
+   *buf++ = v3;
+
+   One source of extra complexity is the need to make sure linebuf is
+   aligned to a 32-bit boundary.
+
+   This second alternative has some complexity to it, but is
+   appealing because it really minimizes the memory bandwidth. */
+void
+art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, gint n)
+{
+  int i;
+
+  if (r == g && g == b)
+    {
+      memset (buf, g, n + n + n);
+    }
+  else
+    {
+      for (i = 0; i < n; i++)
+       {
+         *buf++ = r;
+         *buf++ = g;
+         *buf++ = b;
+       }
+    }
+}
+#endif
+
+#ifdef COLOR_RUN_COMPLEX
+/* This implements the second of the two ideas above. The test results
+   are _very_ encouraging - it seems the speed is within 10% of
+   memset, which is quite good! */
+/**
+ * art_rgb_fill_run: fill a buffer a solid RGB color.
+ * @buf: Buffer to fill.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @n: Number of RGB triples to fill.
+ *
+ * Fills a buffer with @n copies of the (@r, @g, @b) triple. Thus,
+ * locations @buf (inclusive) through @buf + 3 * @n (exclusive) are
+ * written.
+ *
+ * The implementation of this routine is very highly optimized.
+ **/
+void
+art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
+{
+  int i;
+  unsigned int v1, v2, v3;
+
+  if (r == g && g == b)
+    {
+      memset (buf, g, n + n + n);
+    }
+  else
+    {
+      if (n < 8)
+       {
+         for (i = 0; i < n; i++)
+           {
+             *buf++ = r;
+             *buf++ = g;
+             *buf++ = b;
+           }
+       } else {
+         /* handle prefix up to byte alignment */
+         /* I'm worried about this cast on sizeof(long) != sizeof(uchar *)
+            architectures, but it _should_ work. */
+         for (i = 0; ((unsigned long)buf) & 3; i++)
+           {
+             *buf++ = r;
+             *buf++ = g;
+             *buf++ = b;
+           }
+#ifndef WORDS_BIGENDIAN
+         v1 = r | (g << 8) | (b << 16) | (r << 24);
+         v3 = (v1 << 8) | b;
+         v2 = (v3 << 8) | g;
+#else
+         v1 = (r << 24) | (g << 16) | (b << 8) | r;
+         v2 = (v1 << 8) | g;
+         v3 = (v2 << 8) | b;
+#endif
+         for (; i < n - 3; i += 4)
+           {
+             ((art_u32 *)buf)[0] = v1;
+             ((art_u32 *)buf)[1] = v2;
+             ((art_u32 *)buf)[2] = v3;
+             buf += 12;
+           }
+         /* handle postfix */
+         for (; i < n; i++)
+           {
+             *buf++ = r;
+             *buf++ = g;
+             *buf++ = b;
+           }
+       }
+    }
+}
+#endif
+
+/**
+ * art_rgb_run_alpha: Render semitransparent color over RGB buffer.
+ * @buf: Buffer for rendering.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @alpha: Alpha, range 0..256.
+ * @n: Number of RGB triples to render.
+ *
+ * Renders a sequential run of solid (@r, @g, @b) color over @buf with
+ * opacity @alpha.
+ **/
+void
+art_rgb_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
+{
+  int i;
+  int v;
+
+  for (i = 0; i < n; i++)
+    {
+      v = *buf;
+      *buf++ = v + (((r - v) * alpha + 0x80) >> 8);
+      v = *buf;
+      *buf++ = v + (((g - v) * alpha + 0x80) >> 8);
+      v = *buf;
+      *buf++ = v + (((b - v) * alpha + 0x80) >> 8);
+    }
+}
+
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb.h b/libraries/libart_lgpl-2.3.7/art_rgb.h
new file mode 100644 (file)
index 0000000..1dd7df8
--- /dev/null
@@ -0,0 +1,38 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_H__
+#define __ART_RGB_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n);
+
+void
+art_rgb_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha,
+                  int n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_a_affine.c b/libraries/libart_lgpl-2.3.7/art_rgb_a_affine.c
new file mode 100644 (file)
index 0000000..1889e9e
--- /dev/null
@@ -0,0 +1,147 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+#include "art_rgb_affine_private.h"
+#include "art_rgb_a_affine.h"
+
+/* This module handles compositing of affine-transformed alpha only images
+   over rgb pixel buffers. */
+
+/* Composite the source image over the destination image, applying the
+   affine transform. */
+
+/**
+ * art_rgb_a_affine: Affine transform source Alpha image and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image alpha buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @rgb: RGB foreground color, in 0xRRGGBB.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the solid color rgb with alpha specified by the
+ * source image stored in @src, compositing over the area of destination
+ * image @dst specified by the rectangle (@x0, @y0) - (@x1, @y1).
+ * As usual in libart, the left and top edges of this rectangle are
+ * included, and the right and bottom edges are excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be
+ * done in a gamma-corrected color space. In the current
+ * implementation, it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+art_rgb_a_affine (art_u8 *dst,
+                 int x0, int y0, int x1, int y1, int dst_rowstride,
+                 const art_u8 *src,
+                 int src_width, int src_height, int src_rowstride,
+                 art_u32 rgb,
+                 const double affine[6],
+                 ArtFilterLevel level,
+                 ArtAlphaGamma *alphagamma)
+{
+  /* Note: this is a slow implementation, and is missing all filter
+     levels other than NEAREST. It is here for clarity of presentation
+     and to establish the interface. */
+  int x, y;
+  double inv[6];
+  art_u8 *dst_p, *dst_linestart;
+  const art_u8 *src_p;
+  ArtPoint pt, src_pt;
+  int src_x, src_y;
+  int alpha;
+  art_u8 bg_r, bg_g, bg_b;
+  art_u8 fg_r, fg_g, fg_b;
+  int tmp;
+  int run_x0, run_x1;
+  art_u8 r, g, b;
+
+  r = (rgb>>16)&0xff;
+  g = (rgb>>8)&0xff;
+  b = (rgb)&0xff;
+
+  dst_linestart = dst;
+  art_affine_invert (inv, affine);
+  for (y = y0; y < y1; y++)
+    {
+      pt.y = y + 0.5;
+      run_x0 = x0;
+      run_x1 = x1;
+      art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+                         inv);
+      dst_p = dst_linestart + (run_x0 - x0) * 3;
+      for (x = run_x0; x < run_x1; x++)
+       {
+         pt.x = x + 0.5;
+         art_affine_point (&src_pt, &pt, inv);
+         src_x = floor (src_pt.x);
+         src_y = floor (src_pt.y);
+         src_p = src + (src_y * src_rowstride) + src_x;
+         if (src_x >= 0 && src_x < src_width &&
+             src_y >= 0 && src_y < src_height)
+           {
+
+         alpha = *src_p;
+         if (alpha)
+           {
+             if (alpha == 255)
+               {
+                 dst_p[0] = r;
+                 dst_p[1] = g;
+                 dst_p[2] = b;
+               }
+             else
+               {
+                 bg_r = dst_p[0];
+                 bg_g = dst_p[1];
+                 bg_b = dst_p[2];
+                 
+                 tmp = (r - bg_r) * alpha;
+                 fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
+                 tmp = (g - bg_g) * alpha;
+                 fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
+                 tmp = (b - bg_b) * alpha;
+                 fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
+                 
+                 dst_p[0] = fg_r;
+                 dst_p[1] = fg_g;
+                 dst_p[2] = fg_b;
+               }
+           }
+           } else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; }
+         dst_p += 3;
+       }
+      dst_linestart += dst_rowstride;
+    }
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_a_affine.h b/libraries/libart_lgpl-2.3.7/art_rgb_a_affine.h
new file mode 100644 (file)
index 0000000..46e1462
--- /dev/null
@@ -0,0 +1,52 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_A_AFFINE_H__
+#define __ART_RGB_A_AFFINE_H__
+
+/* This module handles compositing of affine-transformed alpha only images
+   over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#else
+#include <art_filterlevel.h>
+#include <art_alphagamma.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_a_affine (art_u8 *dst,
+                 int x0, int y0, int x1, int y1, int dst_rowstride,
+                 const art_u8 *src,
+                 int src_width, int src_height, int src_rowstride,
+                 art_u32 rgb,
+                 const double affine[6],
+                 ArtFilterLevel level,
+                 ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_affine.c b/libraries/libart_lgpl-2.3.7/art_rgb_affine.c
new file mode 100644 (file)
index 0000000..f72c5a8
--- /dev/null
@@ -0,0 +1,104 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+#include "art_rgb_affine.h"
+#include "art_rgb_affine_private.h"
+
+/* This module handles compositing of affine-transformed rgb images
+   over rgb pixel buffers. */
+
+/**
+ * art_rgb_affine: Affine transform source RGB image and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image RGB buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
+ * of this rectangle are included, and the right and bottom edges are
+ * excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be done
+ * in a gamma-corrected color space. Since the source image is opaque RGB,
+ * this argument only affects the edges. In the current implementation,
+ * it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
+               const art_u8 *src,
+               int src_width, int src_height, int src_rowstride,
+               const double affine[6],
+               ArtFilterLevel level,
+               ArtAlphaGamma *alphagamma)
+{
+  /* Note: this is a slow implementation, and is missing all filter
+     levels other than NEAREST. It is here for clarity of presentation
+     and to establish the interface. */
+  int x, y;
+  double inv[6];
+  art_u8 *dst_p, *dst_linestart;
+  const art_u8 *src_p;
+  ArtPoint pt, src_pt;
+  int src_x, src_y;
+  int run_x0, run_x1;
+
+  dst_linestart = dst;
+  art_affine_invert (inv, affine);
+  for (y = y0; y < y1; y++)
+    {
+      pt.y = y + 0.5;
+      run_x0 = x0;
+      run_x1 = x1;
+      art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+                         inv);
+      dst_p = dst_linestart + (run_x0 - x0) * 3;
+      for (x = run_x0; x < run_x1; x++)
+       {
+         pt.x = x + 0.5;
+         art_affine_point (&src_pt, &pt, inv);
+         src_x = floor (src_pt.x);
+         src_y = floor (src_pt.y);
+         src_p = src + (src_y * src_rowstride) + src_x * 3;
+         dst_p[0] = src_p[0];
+         dst_p[1] = src_p[1];
+         dst_p[2] = src_p[2];
+         dst_p += 3;
+       }
+      dst_linestart += dst_rowstride;
+    }
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_affine.h b/libraries/libart_lgpl-2.3.7/art_rgb_affine.h
new file mode 100644 (file)
index 0000000..5419598
--- /dev/null
@@ -0,0 +1,50 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_AFFINE_H__
+#define __ART_RGB_AFFINE_H__
+
+/* This module handles compositing of affine-transformed rgb images
+   over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#else
+#include <art_filterlevel.h>
+#include <art_alphagamma.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
+               const art_u8 *src,
+               int src_width, int src_height, int src_rowstride,
+               const double affine[6],
+               ArtFilterLevel level,
+               ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_affine_private.c b/libraries/libart_lgpl-2.3.7/art_rgb_affine_private.c
new file mode 100644 (file)
index 0000000..949a89a
--- /dev/null
@@ -0,0 +1,125 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+#include "art_rgb_affine_private.h"
+
+/* Private functions for the rgb affine image compositors - primarily,
+   the determination of runs, eliminating the need for source image
+   bbox calculation in the inner loop. */
+
+/* Determine a "run", such that the inverse affine of all pixels from
+   (x0, y) inclusive to (x1, y) exclusive fit within the bounds
+   of the source image.
+
+   Initial values of x0, x1, and result values stored in first two
+   pointer arguments.
+*/
+
+#define EPSILON 1e-6
+
+void
+art_rgb_affine_run (int *p_x0, int *p_x1, int y,
+                   int src_width, int src_height,
+                   const double affine[6])
+{
+  int x0, x1;
+  double z;
+  double x_intercept;
+  int xi;
+
+  x0 = *p_x0;
+  x1 = *p_x1;
+
+  /* do left and right edges */
+  if (affine[0] > EPSILON)
+    {
+      z = affine[2] * (y + 0.5) + affine[4];
+      x_intercept = -z / affine[0];
+      xi = ceil (x_intercept + EPSILON - 0.5);
+      if (xi > x0)
+       x0 = xi;
+      x_intercept = (-z + src_width) / affine[0];
+      xi = ceil (x_intercept - EPSILON - 0.5);
+      if (xi < x1)
+       x1 = xi;
+    }
+  else if (affine[0] < -EPSILON)
+    {
+      z = affine[2] * (y + 0.5) + affine[4];
+      x_intercept = (-z + src_width) / affine[0];
+      xi = ceil (x_intercept + EPSILON - 0.5);
+      if (xi > x0)
+       x0 = xi;
+      x_intercept = -z / affine[0];
+      xi = ceil (x_intercept - EPSILON - 0.5);
+      if (xi < x1)
+       x1 = xi;
+    }
+  else
+    {
+      z = affine[2] * (y + 0.5) + affine[4];
+      if (z < 0 || z >= src_width)
+       {
+         *p_x1 = *p_x0;
+         return;
+       }
+    }
+
+  /* do top and bottom edges */
+  if (affine[1] > EPSILON)
+    {
+      z = affine[3] * (y + 0.5) + affine[5];
+      x_intercept = -z / affine[1];
+      xi = ceil (x_intercept + EPSILON - 0.5);
+      if (xi > x0)
+       x0 = xi;
+      x_intercept = (-z + src_height) / affine[1];
+      xi = ceil (x_intercept - EPSILON - 0.5);
+      if (xi < x1)
+       x1 = xi;
+    }
+  else if (affine[1] < -EPSILON)
+    {
+      z = affine[3] * (y + 0.5) + affine[5];
+      x_intercept = (-z + src_height) / affine[1];
+      xi = ceil (x_intercept + EPSILON - 0.5);
+      if (xi > x0)
+       x0 = xi;
+      x_intercept = -z / affine[1];
+      xi = ceil (x_intercept - EPSILON - 0.5);
+      if (xi < x1)
+       x1 = xi;
+    }
+  else
+    {
+      z = affine[3] * (y + 0.5) + affine[5];
+      if (z < 0 || z >= src_height)
+       {
+         *p_x1 = *p_x0;
+         return;
+       }
+    }
+
+  *p_x0 = x0;
+  *p_x1 = x1;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_affine_private.h b/libraries/libart_lgpl-2.3.7/art_rgb_affine_private.h
new file mode 100644 (file)
index 0000000..edaf0e3
--- /dev/null
@@ -0,0 +1,39 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_AFFINE_PRIVATE_H__
+#define __ART_RGB_AFFINE_PRIVATE_H__
+
+/* This module handles compositing of affine-transformed rgb images
+   over rgb pixel buffers. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_affine_run (int *p_x0, int *p_x1, int y,
+                   int src_width, int src_height,
+                   const double affine[6]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_bitmap_affine.c b/libraries/libart_lgpl-2.3.7/art_rgb_bitmap_affine.c
new file mode 100644 (file)
index 0000000..57e0655
--- /dev/null
@@ -0,0 +1,196 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+#include "art_rgb_affine_private.h"
+#include "art_rgb_bitmap_affine.h"
+
+/* This module handles compositing of affine-transformed bitmap images
+   over rgb pixel buffers. */
+
+/* Composite the source image over the destination image, applying the
+   affine transform. Foreground color is given and assumed to be
+   opaque, background color is assumed to be fully transparent. */
+
+static void
+art_rgb_bitmap_affine_opaque (art_u8 *dst,
+                             int x0, int y0, int x1, int y1,
+                             int dst_rowstride,
+                             const art_u8 *src,
+                             int src_width, int src_height, int src_rowstride,
+                             art_u32 rgb,
+                             const double affine[6],
+                             ArtFilterLevel level,
+                             ArtAlphaGamma *alphagamma)
+{
+  /* Note: this is a slow implementation, and is missing all filter
+     levels other than NEAREST. It is here for clarity of presentation
+     and to establish the interface. */
+  int x, y;
+  double inv[6];
+  art_u8 *dst_p, *dst_linestart;
+  const art_u8 *src_p;
+  ArtPoint pt, src_pt;
+  int src_x, src_y;
+  art_u8 r, g, b;
+  int run_x0, run_x1;
+
+  r = rgb >> 16;
+  g = (rgb >> 8) & 0xff;
+  b = rgb & 0xff;
+  dst_linestart = dst;
+  art_affine_invert (inv, affine);
+  for (y = y0; y < y1; y++)
+    {
+      pt.y = y + 0.5;
+      run_x0 = x0;
+      run_x1 = x1;
+      art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+                         inv);
+      dst_p = dst_linestart + (run_x0 - x0) * 3;
+      for (x = run_x0; x < run_x1; x++)
+       {
+         pt.x = x + 0.5;
+         art_affine_point (&src_pt, &pt, inv);
+         src_x = floor (src_pt.x);
+         src_y = floor (src_pt.y);
+         src_p = src + (src_y * src_rowstride) + (src_x >> 3);
+         if (*src_p & (128 >> (src_x & 7)))
+           {
+             dst_p[0] = r;
+             dst_p[1] = g;
+             dst_p[2] = b;
+           }
+         dst_p += 3;
+       }
+      dst_linestart += dst_rowstride;
+    }
+}
+/* Composite the source image over the destination image, applying the
+   affine transform. Foreground color is given, background color is
+   assumed to be fully transparent. */
+
+/**
+ * art_rgb_bitmap_affine: Affine transform source bitmap image and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image bitmap buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @rgba: RGBA foreground color, in 0xRRGGBBAA.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1).
+ *
+ * The source bitmap stored with MSB as the leftmost pixel. Source 1
+ * bits correspond to the semitransparent color @rgba, while source 0
+ * bits are transparent.
+ *
+ * See art_rgb_affine() for a description of additional parameters.
+ **/
+void
+art_rgb_bitmap_affine (art_u8 *dst,
+                      int x0, int y0, int x1, int y1, int dst_rowstride,
+                      const art_u8 *src,
+                      int src_width, int src_height, int src_rowstride,
+                      art_u32 rgba,
+                      const double affine[6],
+                      ArtFilterLevel level,
+                      ArtAlphaGamma *alphagamma)
+{
+  /* Note: this is a slow implementation, and is missing all filter
+     levels other than NEAREST. It is here for clarity of presentation
+     and to establish the interface. */
+  int x, y;
+  double inv[6];
+  art_u8 *dst_p, *dst_linestart;
+  const art_u8 *src_p;
+  ArtPoint pt, src_pt;
+  int src_x, src_y;
+  int alpha;
+  art_u8 bg_r, bg_g, bg_b;
+  art_u8 fg_r, fg_g, fg_b;
+  art_u8 r, g, b;
+  int run_x0, run_x1;
+
+  alpha = rgba & 0xff;
+  if (alpha == 0xff)
+    {
+      art_rgb_bitmap_affine_opaque (dst, x0, y0, x1, y1, dst_rowstride,
+                                   src,
+                                   src_width, src_height, src_rowstride,
+                                   rgba >> 8,
+                                   affine,
+                                   level,
+                                   alphagamma);
+      return;
+    }
+  /* alpha = (65536 * alpha) / 255; */
+  alpha = (alpha << 8) + alpha + (alpha >> 7);
+  r = rgba >> 24;
+  g = (rgba >> 16) & 0xff;
+  b = (rgba >> 8) & 0xff;
+  dst_linestart = dst;
+  art_affine_invert (inv, affine);
+  for (y = y0; y < y1; y++)
+    {
+      pt.y = y + 0.5;
+      run_x0 = x0;
+      run_x1 = x1;
+      art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+                         inv);
+      dst_p = dst_linestart + (run_x0 - x0) * 3;
+      for (x = run_x0; x < run_x1; x++)
+       {
+         pt.x = x + 0.5;
+         art_affine_point (&src_pt, &pt, inv);
+         src_x = floor (src_pt.x);
+         src_y = floor (src_pt.y);
+         src_p = src + (src_y * src_rowstride) + (src_x >> 3);
+         if (*src_p & (128 >> (src_x & 7)))
+           {
+             bg_r = dst_p[0];
+             bg_g = dst_p[1];
+             bg_b = dst_p[2];
+
+             fg_r = bg_r + (((r - bg_r) * alpha + 0x8000) >> 16);
+             fg_g = bg_g + (((g - bg_g) * alpha + 0x8000) >> 16);
+             fg_b = bg_b + (((b - bg_b) * alpha + 0x8000) >> 16);
+
+             dst_p[0] = fg_r;
+             dst_p[1] = fg_g;
+             dst_p[2] = fg_b;
+           }
+         dst_p += 3;
+       }
+      dst_linestart += dst_rowstride;
+    }
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_bitmap_affine.h b/libraries/libart_lgpl-2.3.7/art_rgb_bitmap_affine.h
new file mode 100644 (file)
index 0000000..777d688
--- /dev/null
@@ -0,0 +1,52 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_BITMAP_AFFINE_H__
+#define __ART_RGB_BITMAP_AFFINE_H__
+
+/* This module handles compositing of affine-transformed bitmap images
+   over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#else
+#include <art_filterlevel.h>
+#include <art_alphagamma.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_bitmap_affine (art_u8 *dst,
+                      int x0, int y0, int x1, int y1, int dst_rowstride,
+                      const art_u8 *src,
+                      int src_width, int src_height, int src_rowstride,
+                      art_u32 rgba,
+                      const double affine[6],
+                      ArtFilterLevel level,
+                      ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_pixbuf_affine.c b/libraries/libart_lgpl-2.3.7/art_rgb_pixbuf_affine.c
new file mode 100644 (file)
index 0000000..9f08ad4
--- /dev/null
@@ -0,0 +1,102 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+#include "art_pixbuf.h"
+#include "art_rgb_affine.h"
+#include "art_rgb_affine.h"
+#include "art_rgb_rgba_affine.h"
+#include "art_rgb_pixbuf_affine.h"
+
+/* This module handles compositing of affine-transformed generic
+   pixbuf images over rgb pixel buffers. */
+
+/* Composite the source image over the destination image, applying the
+   affine transform. */
+/**
+ * art_rgb_pixbuf_affine: Affine transform source RGB pixbuf and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @pixbuf: source image pixbuf.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
+ * of this rectangle are included, and the right and bottom edges are
+ * excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be
+ * done in a gamma-corrected color space. In the current
+ * implementation, it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+art_rgb_pixbuf_affine (art_u8 *dst,
+                      int x0, int y0, int x1, int y1, int dst_rowstride,
+                      const ArtPixBuf *pixbuf,
+                      const double affine[6],
+                      ArtFilterLevel level,
+                      ArtAlphaGamma *alphagamma)
+{
+  if (pixbuf->format != ART_PIX_RGB)
+    {
+      art_warn ("art_rgb_pixbuf_affine: need RGB format image\n");
+      return;
+    }
+
+  if (pixbuf->bits_per_sample != 8)
+    {
+      art_warn ("art_rgb_pixbuf_affine: need 8-bit sample data\n");
+      return;
+    }
+
+  if (pixbuf->n_channels != 3 + (pixbuf->has_alpha != 0))
+    {
+      art_warn ("art_rgb_pixbuf_affine: need 8-bit sample data\n");
+      return;
+    }
+
+  if (pixbuf->has_alpha)
+    art_rgb_rgba_affine (dst, x0, y0, x1, y1, dst_rowstride,
+                        pixbuf->pixels,
+                        pixbuf->width, pixbuf->height, pixbuf->rowstride,
+                        affine,
+                        level,
+                        alphagamma);
+  else
+    art_rgb_affine (dst, x0, y0, x1, y1, dst_rowstride,
+                   pixbuf->pixels,
+                   pixbuf->width, pixbuf->height, pixbuf->rowstride,
+                   affine,
+                   level,
+                   alphagamma);
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_pixbuf_affine.h b/libraries/libart_lgpl-2.3.7/art_rgb_pixbuf_affine.h
new file mode 100644 (file)
index 0000000..4107659
--- /dev/null
@@ -0,0 +1,52 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_PIXBUF_AFFINE_H__
+#define __ART_RGB_PIXBUF_AFFINE_H__
+
+/* This module handles compositing of affine-transformed generic
+   pixbuf images over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#include "art_pixbuf.h"
+#else
+#include <art_filterlevel.h>
+#include <art_alphagamma.h>
+#include <art_pixbuf.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_pixbuf_affine (art_u8 *dst,
+                      int x0, int y0, int x1, int y1, int dst_rowstride,
+                      const ArtPixBuf *pixbuf,
+                      const double affine[6],
+                      ArtFilterLevel level,
+                      ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_rgba_affine.c b/libraries/libart_lgpl-2.3.7/art_rgb_rgba_affine.c
new file mode 100644 (file)
index 0000000..78c27fe
--- /dev/null
@@ -0,0 +1,140 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+#include "art_rgb_affine_private.h"
+#include "art_rgb_rgba_affine.h"
+
+/* This module handles compositing of affine-transformed rgba images
+   over rgb pixel buffers. */
+
+/* Composite the source image over the destination image, applying the
+   affine transform. */
+
+/**
+ * art_rgb_rgba_affine: Affine transform source RGBA image and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image RGBA buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
+ * of this rectangle are included, and the right and bottom edges are
+ * excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be
+ * done in a gamma-corrected color space. In the current
+ * implementation, it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+art_rgb_rgba_affine (art_u8 *dst,
+                    int x0, int y0, int x1, int y1, int dst_rowstride,
+                    const art_u8 *src,
+                    int src_width, int src_height, int src_rowstride,
+                    const double affine[6],
+                    ArtFilterLevel level,
+                    ArtAlphaGamma *alphagamma)
+{
+  /* Note: this is a slow implementation, and is missing all filter
+     levels other than NEAREST. It is here for clarity of presentation
+     and to establish the interface. */
+  int x, y;
+  double inv[6];
+  art_u8 *dst_p, *dst_linestart;
+  const art_u8 *src_p;
+  ArtPoint pt, src_pt;
+  int src_x, src_y;
+  int alpha;
+  art_u8 bg_r, bg_g, bg_b;
+  art_u8 fg_r, fg_g, fg_b;
+  int tmp;
+  int run_x0, run_x1;
+
+  dst_linestart = dst;
+  art_affine_invert (inv, affine);
+  for (y = y0; y < y1; y++)
+    {
+      pt.y = y + 0.5;
+      run_x0 = x0;
+      run_x1 = x1;
+      art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+                         inv);
+      dst_p = dst_linestart + (run_x0 - x0) * 3;
+      for (x = run_x0; x < run_x1; x++)
+       {
+         pt.x = x + 0.5;
+         art_affine_point (&src_pt, &pt, inv);
+         src_x = floor (src_pt.x);
+         src_y = floor (src_pt.y);
+         src_p = src + (src_y * src_rowstride) + src_x * 4;
+         if (src_x >= 0 && src_x < src_width &&
+             src_y >= 0 && src_y < src_height)
+           {
+
+         alpha = src_p[3];
+         if (alpha)
+           {
+             if (alpha == 255)
+               {
+                 dst_p[0] = src_p[0];
+                 dst_p[1] = src_p[1];
+                 dst_p[2] = src_p[2];
+               }
+             else
+               {
+                 bg_r = dst_p[0];
+                 bg_g = dst_p[1];
+                 bg_b = dst_p[2];
+                 
+                 tmp = (src_p[0] - bg_r) * alpha;
+                 fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
+                 tmp = (src_p[1] - bg_g) * alpha;
+                 fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
+                 tmp = (src_p[2] - bg_b) * alpha;
+                 fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
+                 
+                 dst_p[0] = fg_r;
+                 dst_p[1] = fg_g;
+                 dst_p[2] = fg_b;
+               }
+           }
+           } else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; }
+         dst_p += 3;
+       }
+      dst_linestart += dst_rowstride;
+    }
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_rgba_affine.h b/libraries/libart_lgpl-2.3.7/art_rgb_rgba_affine.h
new file mode 100644 (file)
index 0000000..d9b5c02
--- /dev/null
@@ -0,0 +1,51 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_RGBA_AFFINE_H__
+#define __ART_RGB_RGBA_AFFINE_H__
+
+/* This module handles compositing of affine-transformed rgba images
+   over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#else
+#include <art_filterlevel.h>
+#include <art_alphagamma.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_rgba_affine (art_u8 *dst,
+                    int x0, int y0, int x1, int y1, int dst_rowstride,
+                    const art_u8 *src,
+                    int src_width, int src_height, int src_rowstride,
+                    const double affine[6],
+                    ArtFilterLevel level,
+                    ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_svp.c b/libraries/libart_lgpl-2.3.7/art_rgb_svp.c
new file mode 100644 (file)
index 0000000..81cf562
--- /dev/null
@@ -0,0 +1,457 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Render a sorted vector path into an RGB buffer. */
+
+#include "art_misc.h"
+
+#include "art_svp.h"
+#include "art_svp_render_aa.h"
+#include "art_rgb.h"
+#include "art_rgb_svp.h"
+
+typedef struct _ArtRgbSVPData ArtRgbSVPData;
+typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData;
+
+struct _ArtRgbSVPData {
+  art_u32 rgbtab[256];
+  art_u8 *buf;
+  int rowstride;
+  int x0, x1;
+};
+
+struct _ArtRgbSVPAlphaData {
+  int alphatab[256];
+  art_u8 r, g, b, alpha;
+  art_u8 *buf;
+  int rowstride;
+  int x0, x1;
+};
+
+static void
+art_rgb_svp_callback (void *callback_data, int y,
+                     int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+  ArtRgbSVPData *data = (ArtRgbSVPData *)callback_data;
+  art_u8 *linebuf;
+  int run_x0, run_x1;
+  art_u32 running_sum = start;
+  art_u32 rgb;
+  int x0, x1;
+  int k;
+
+  linebuf = data->buf;
+  x0 = data->x0;
+  x1 = data->x1;
+
+  if (n_steps > 0)
+    {
+      run_x1 = steps[0].x;
+      if (run_x1 > x0)
+       {
+         rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+         art_rgb_fill_run (linebuf,
+                           rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+                           run_x1 - x0);
+       }
+
+      for (k = 0; k < n_steps - 1; k++)
+       {
+         running_sum += steps[k].delta;
+         run_x0 = run_x1;
+         run_x1 = steps[k + 1].x;
+         if (run_x1 > run_x0)
+           {
+             rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+             art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
+                               rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+                               run_x1 - run_x0);
+           }
+       }
+      running_sum += steps[k].delta;
+      if (x1 > run_x1)
+       {
+         rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+         art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
+                           rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+                           x1 - run_x1);
+       }
+    }
+  else
+    {
+      rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+      art_rgb_fill_run (linebuf,
+                       rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+                       x1 - x0);
+    }
+
+  data->buf += data->rowstride;
+}
+
+/* Render the vector path into the RGB buffer. */
+
+/**
+ * art_rgb_svp_aa: Render sorted vector path into RGB buffer.
+ * @svp: The source sorted vector path.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @fg_color: Foreground color in 0xRRGGBB format.
+ * @bg_color: Background color in 0xRRGGBB format.
+ * @buf: Destination RGB buffer.
+ * @rowstride: Rowstride of @buf buffer.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the rendering.
+ *
+ * Renders the shape specified with @svp into the @buf RGB buffer.
+ * @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
+ * of the rectangle rendered. The new pixels are stored starting at
+ * the first byte of @buf. Thus, the @x0 and @y0 parameters specify
+ * an offset within @svp, and may be tweaked as a way of doing
+ * integer-pixel translations without fiddling with @svp itself.
+ *
+ * The @fg_color and @bg_color arguments specify the opaque colors to
+ * be used for rendering. For pixels of entirely 0 winding-number,
+ * @bg_color is used. For pixels of entirely 1 winding number,
+ * @fg_color is used. In between, the color is interpolated based on
+ * the fraction of the pixel with a winding number of 1. If
+ * @alphagamma is NULL, then linear interpolation (in pixel counts) is
+ * the default. Otherwise, the interpolation is as specified by
+ * @alphagamma.
+ **/
+void
+art_rgb_svp_aa (const ArtSVP *svp,
+               int x0, int y0, int x1, int y1,
+               art_u32 fg_color, art_u32 bg_color,
+               art_u8 *buf, int rowstride,
+               ArtAlphaGamma *alphagamma)
+{
+  ArtRgbSVPData data;
+
+  int r_fg, g_fg, b_fg;
+  int r_bg, g_bg, b_bg;
+  int r, g, b;
+  int dr, dg, db;
+  int i;
+
+  if (alphagamma == NULL)
+    {
+      r_fg = fg_color >> 16;
+      g_fg = (fg_color >> 8) & 0xff;
+      b_fg = fg_color & 0xff;
+
+      r_bg = bg_color >> 16;
+      g_bg = (bg_color >> 8) & 0xff;
+      b_bg = bg_color & 0xff;
+
+      r = (r_bg << 16) + 0x8000;
+      g = (g_bg << 16) + 0x8000;
+      b = (b_bg << 16) + 0x8000;
+      dr = ((r_fg - r_bg) << 16) / 255;
+      dg = ((g_fg - g_bg) << 16) / 255;
+      db = ((b_fg - b_bg) << 16) / 255;
+
+      for (i = 0; i < 256; i++)
+       {
+         data.rgbtab[i] = (r & 0xff0000) | ((g & 0xff0000) >> 8) | (b >> 16);
+         r += dr;
+         g += dg;
+         b += db;
+       }
+    }
+  else
+    {
+      int *table;
+      art_u8 *invtab;
+
+      table = alphagamma->table;
+
+      r_fg = table[fg_color >> 16];
+      g_fg = table[(fg_color >> 8) & 0xff];
+      b_fg = table[fg_color & 0xff];
+
+      r_bg = table[bg_color >> 16];
+      g_bg = table[(bg_color >> 8) & 0xff];
+      b_bg = table[bg_color & 0xff];
+
+      r = (r_bg << 16) + 0x8000;
+      g = (g_bg << 16) + 0x8000;
+      b = (b_bg << 16) + 0x8000;
+      dr = ((r_fg - r_bg) << 16) / 255;
+      dg = ((g_fg - g_bg) << 16) / 255;
+      db = ((b_fg - b_bg) << 16) / 255;
+
+      invtab = alphagamma->invtable;
+      for (i = 0; i < 256; i++)
+       {
+         data.rgbtab[i] = (invtab[r >> 16] << 16) |
+           (invtab[g >> 16] << 8) |
+           invtab[b >> 16];
+         r += dr;
+         g += dg;
+         b += db;
+       }
+    }
+  data.buf = buf;
+  data.rowstride = rowstride;
+  data.x0 = x0;
+  data.x1 = x1;
+  art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_callback, &data);
+}
+
+static void
+art_rgb_svp_alpha_callback (void *callback_data, int y,
+                           int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+  ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
+  art_u8 *linebuf;
+  int run_x0, run_x1;
+  art_u32 running_sum = start;
+  int x0, x1;
+  int k;
+  art_u8 r, g, b;
+  int *alphatab;
+  int alpha;
+
+  linebuf = data->buf;
+  x0 = data->x0;
+  x1 = data->x1;
+
+  r = data->r;
+  g = data->g;
+  b = data->b;
+  alphatab = data->alphatab;
+
+  if (n_steps > 0)
+    {
+      run_x1 = steps[0].x;
+      if (run_x1 > x0)
+       {
+         alpha = (running_sum >> 16) & 0xff;
+         if (alpha)
+           art_rgb_run_alpha (linebuf,
+                              r, g, b, alphatab[alpha],
+                              run_x1 - x0);
+       }
+
+      for (k = 0; k < n_steps - 1; k++)
+       {
+         running_sum += steps[k].delta;
+         run_x0 = run_x1;
+         run_x1 = steps[k + 1].x;
+         if (run_x1 > run_x0)
+           {
+             alpha = (running_sum >> 16) & 0xff;
+             if (alpha)
+               art_rgb_run_alpha (linebuf + (run_x0 - x0) * 3,
+                                  r, g, b, alphatab[alpha],
+                                  run_x1 - run_x0);
+           }
+       }
+      running_sum += steps[k].delta;
+      if (x1 > run_x1)
+       {
+         alpha = (running_sum >> 16) & 0xff;
+         if (alpha)
+           art_rgb_run_alpha (linebuf + (run_x1 - x0) * 3,
+                              r, g, b, alphatab[alpha],
+                              x1 - run_x1);
+       }
+    }
+  else
+    {
+      alpha = (running_sum >> 16) & 0xff;
+      if (alpha)
+       art_rgb_run_alpha (linebuf,
+                          r, g, b, alphatab[alpha],
+                          x1 - x0);
+    }
+
+  data->buf += data->rowstride;
+}
+
+static void
+art_rgb_svp_alpha_opaque_callback (void *callback_data, int y,
+                                  int start,
+                                  ArtSVPRenderAAStep *steps, int n_steps)
+{
+  ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
+  art_u8 *linebuf;
+  int run_x0, run_x1;
+  art_u32 running_sum = start;
+  int x0, x1;
+  int k;
+  art_u8 r, g, b;
+  int *alphatab;
+  int alpha;
+
+  linebuf = data->buf;
+  x0 = data->x0;
+  x1 = data->x1;
+
+  r = data->r;
+  g = data->g;
+  b = data->b;
+  alphatab = data->alphatab;
+
+  if (n_steps > 0)
+    {
+      run_x1 = steps[0].x;
+      if (run_x1 > x0)
+       {
+         alpha = running_sum >> 16;
+         if (alpha)
+           {
+             if (alpha >= 255)
+               art_rgb_fill_run (linebuf,
+                                 r, g, b,
+                                 run_x1 - x0);
+             else
+               art_rgb_run_alpha (linebuf,
+                                  r, g, b, alphatab[alpha],
+                                  run_x1 - x0);
+           }
+       }
+
+      for (k = 0; k < n_steps - 1; k++)
+       {
+         running_sum += steps[k].delta;
+         run_x0 = run_x1;
+         run_x1 = steps[k + 1].x;
+         if (run_x1 > run_x0)
+           {
+             alpha = running_sum >> 16;
+             if (alpha)
+               {
+                 if (alpha >= 255)
+                   art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
+                                     r, g, b,
+                                     run_x1 - run_x0);
+                 else
+                   art_rgb_run_alpha (linebuf + (run_x0 - x0) * 3,
+                                      r, g, b, alphatab[alpha],
+                                      run_x1 - run_x0);
+               }
+           }
+       }
+      running_sum += steps[k].delta;
+      if (x1 > run_x1)
+       {
+         alpha = running_sum >> 16;
+         if (alpha)
+           {
+             if (alpha >= 255)
+               art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
+                                 r, g, b,
+                                 x1 - run_x1);
+             else
+               art_rgb_run_alpha (linebuf + (run_x1 - x0) * 3,
+                                  r, g, b, alphatab[alpha],
+                                  x1 - run_x1);
+           }
+       }
+    }
+  else
+    {
+      alpha = running_sum >> 16;
+      if (alpha)
+       {
+         if (alpha >= 255)
+           art_rgb_fill_run (linebuf,
+                             r, g, b,
+                             x1 - x0);
+         else
+           art_rgb_run_alpha (linebuf,
+                              r, g, b, alphatab[alpha],
+                              x1 - x0);
+       }
+    }
+
+  data->buf += data->rowstride;
+}
+
+/**
+ * art_rgb_svp_alpha: Alpha-composite sorted vector path over RGB buffer.
+ * @svp: The source sorted vector path.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @rgba: Color in 0xRRGGBBAA format.
+ * @buf: Destination RGB buffer.
+ * @rowstride: Rowstride of @buf buffer.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Renders the shape specified with @svp over the @buf RGB buffer.
+ * @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
+ * of the rectangle rendered. The new pixels are stored starting at
+ * the first byte of @buf. Thus, the @x0 and @y0 parameters specify
+ * an offset within @svp, and may be tweaked as a way of doing
+ * integer-pixel translations without fiddling with @svp itself.
+ *
+ * The @rgba argument specifies the color for the rendering. Pixels of
+ * entirely 0 winding number are left untouched. Pixels of entirely
+ * 1 winding number have the color @rgba composited over them (ie,
+ * are replaced by the red, green, blue components of @rgba if the alpha
+ * component is 0xff). Pixels of intermediate coverage are interpolated
+ * according to the rule in @alphagamma, or default to linear if
+ * @alphagamma is NULL.
+ **/
+void
+art_rgb_svp_alpha (const ArtSVP *svp,
+                  int x0, int y0, int x1, int y1,
+                  art_u32 rgba,
+                  art_u8 *buf, int rowstride,
+                  ArtAlphaGamma *alphagamma)
+{
+  ArtRgbSVPAlphaData data;
+  int r, g, b, alpha;
+  int i;
+  int a, da;
+
+  r = rgba >> 24;
+  g = (rgba >> 16) & 0xff;
+  b = (rgba >> 8) & 0xff;
+  alpha = rgba & 0xff;
+
+  data.r = r;
+  data.g = g;
+  data.b = b;
+  data.alpha = alpha;
+
+  a = 0x8000;
+  da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
+
+  for (i = 0; i < 256; i++)
+    {
+      data.alphatab[i] = a >> 16;
+      a += da;
+    }
+
+  data.buf = buf;
+  data.rowstride = rowstride;
+  data.x0 = x0;
+  data.x1 = x1;
+  if (alpha == 255)
+    art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback,
+                      &data);
+  else
+    art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback, &data);
+}
+
diff --git a/libraries/libart_lgpl-2.3.7/art_rgb_svp.h b/libraries/libart_lgpl-2.3.7/art_rgb_svp.h
new file mode 100644 (file)
index 0000000..32102ca
--- /dev/null
@@ -0,0 +1,53 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_SVP_H__
+#define __ART_RGB_SVP_H__
+
+/* Render a sorted vector path into an RGB buffer. */
+
+#ifdef LIBART_COMPILATION
+#include "art_alphagamma.h"
+#else
+#include <art_alphagamma.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_rgb_svp_aa (const ArtSVP *svp,
+               int x0, int y0, int x1, int y1,
+               art_u32 fg_color, art_u32 bg_color,
+               art_u8 *buf, int rowstride,
+               ArtAlphaGamma *alphagamma);
+
+void
+art_rgb_svp_alpha (const ArtSVP *svp,
+                  int x0, int y0, int x1, int y1,
+                  art_u32 rgba,
+                  art_u8 *buf, int rowstride,
+                  ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RGB_SVP_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_rgba.c b/libraries/libart_lgpl-2.3.7/art_rgba.c
new file mode 100644 (file)
index 0000000..6fecde6
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * art_rgba.c: Functions for manipulating RGBA pixel data.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "art_misc.h"
+#include "art_rgba.h"
+
+#define ART_OPTIMIZE_SPACE
+
+#ifndef ART_OPTIMIZE_SPACE
+#include "art_rgba_table.c"
+#endif
+
+/**
+ * art_rgba_rgba_composite: Composite RGBA image over RGBA buffer.
+ * @dst: Destination RGBA buffer.
+ * @src: Source RGBA buffer.
+ * @n: Number of RGBA pixels to composite.
+ *
+ * Composites the RGBA pixels in @dst over the @src buffer.
+ **/
+void
+art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n)
+{
+  int i;
+#ifdef WORDS_BIGENDIAN
+  art_u32 src_rgba, dst_rgba;
+#else
+  art_u32 src_abgr, dst_abgr;
+#endif
+  art_u8 src_alpha, dst_alpha;
+
+  for (i = 0; i < n; i++)
+    {
+#ifdef WORDS_BIGENDIAN
+      src_rgba = ((art_u32 *)src)[i];
+      src_alpha = src_rgba & 0xff;
+#else
+      src_abgr = ((art_u32 *)src)[i];
+      src_alpha = (src_abgr >> 24) & 0xff;
+#endif
+      if (src_alpha)
+       {
+         if (src_alpha == 0xff ||
+             (
+#ifdef WORDS_BIGENDIAN
+              dst_rgba = ((art_u32 *)dst)[i],
+              dst_alpha = dst_rgba & 0xff,
+#else
+              dst_abgr = ((art_u32 *)dst)[i],
+              dst_alpha = (dst_abgr >> 24),
+#endif
+              dst_alpha == 0))
+#ifdef WORDS_BIGENDIAN
+           ((art_u32 *)dst)[i] = src_rgba;
+#else
+           ((art_u32 *)dst)[i] = src_abgr;
+#endif
+         else
+           {
+             int r, g, b, a;
+             int src_r, src_g, src_b;
+             int dst_r, dst_g, dst_b;
+             int tmp;
+             int c;
+
+#ifdef ART_OPTIMIZE_SPACE
+             tmp = (255 - src_alpha) * (255 - dst_alpha) + 0x80;
+             a = 255 - ((tmp + (tmp >> 8)) >> 8);
+             c = ((src_alpha << 16) + (a >> 1)) / a;
+#else
+             tmp = art_rgba_composite_table[(src_alpha << 8) + dst_alpha];
+             c = tmp & 0x1ffff;
+             a = tmp >> 24;
+#endif
+#ifdef WORDS_BIGENDIAN
+             src_r = (src_rgba >> 24) & 0xff;
+             src_g = (src_rgba >> 16) & 0xff;
+             src_b = (src_rgba >> 8) & 0xff;
+             dst_r = (dst_rgba >> 24) & 0xff;
+             dst_g = (dst_rgba >> 16) & 0xff;
+             dst_b = (dst_rgba >> 8) & 0xff;
+#else
+             src_r = src_abgr & 0xff;
+             src_g = (src_abgr >> 8) & 0xff;
+             src_b = (src_abgr >> 16) & 0xff;
+             dst_r = dst_abgr & 0xff;
+             dst_g = (dst_abgr >> 8) & 0xff;
+             dst_b = (dst_abgr >> 16) & 0xff;
+#endif
+             r = dst_r + (((src_r - dst_r) * c + 0x8000) >> 16);
+             g = dst_g + (((src_g - dst_g) * c + 0x8000) >> 16);
+             b = dst_b + (((src_b - dst_b) * c + 0x8000) >> 16);
+#ifdef WORDS_BIGENDIAN
+           ((art_u32 *)dst)[i] = (r << 24) | (g << 16) | (b << 8) | a;
+#else
+           ((art_u32 *)dst)[i] = (a << 24) | (b << 16) | (g << 8) | r;
+#endif       
+           }
+       }
+#if 0
+      /* it's not clear to me this optimization really wins */
+      else
+       {
+         /* skip over run of transparent pixels */
+         for (; i < n - 1; i++)
+           {
+#ifdef WORDS_BIGENDIAN
+             src_rgba = ((art_u32 *)src)[i + 1];
+             if (src_rgba & 0xff)
+               break;
+#else
+             src_abgr = ((art_u32 *)src)[i + 1];
+             if (src_abgr & 0xff000000)
+               break;
+#endif
+           }
+       }
+#endif
+    }
+}
+
+/**
+ * art_rgba_fill_run: fill an RGBA buffer a solid RGB color.
+ * @buf: Buffer to fill.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @n: Number of RGB triples to fill.
+ *
+ * Fills a buffer with @n copies of the (@r, @g, @b) triple, solid
+ * alpha. Thus, locations @buf (inclusive) through @buf + 4 * @n
+ * (exclusive) are written.
+ **/
+void
+art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
+{
+  int i;
+#ifdef WORDS_BIGENDIAN
+  art_u32 src_rgba;
+#else
+  art_u32 src_abgr;
+#endif
+
+#ifdef WORDS_BIGENDIAN
+  src_rgba = (r << 24) | (g << 16) | (b << 8) | 255;
+#else
+  src_abgr = (255 << 24) | (b << 16) | (g << 8) | r;
+#endif
+  for (i = 0; i < n; i++)
+    {
+#ifdef WORDS_BIGENDIAN
+      ((art_u32 *)buf)[i] = src_rgba;
+#else
+      ((art_u32 *)buf)[i] = src_abgr;
+#endif
+    }    
+}
+
+/**
+ * art_rgba_run_alpha: Render semitransparent color over RGBA buffer.
+ * @buf: Buffer for rendering.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @alpha: Alpha, range 0..255.
+ * @n: Number of RGB triples to render.
+ *
+ * Renders a sequential run of solid (@r, @g, @b) color over @buf with
+ * opacity @alpha. Note that the range of @alpha is 0..255, in contrast
+ * to art_rgb_run_alpha, which has a range of 0..256.
+ **/
+void
+art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
+{
+  int i;
+#ifdef WORDS_BIGENDIAN
+  art_u32 src_rgba, dst_rgba;
+#else
+  art_u32 src_abgr, dst_abgr;
+#endif
+  art_u8 dst_alpha;
+  int a;
+  int dst_r, dst_g, dst_b;
+  int tmp;
+  int c;
+
+#ifdef WORDS_BIGENDIAN
+  src_rgba = (r << 24) | (g << 16) | (b << 8) | alpha;
+#else
+  src_abgr = (alpha << 24) | (b << 16) | (g << 8) | r;
+#endif
+  for (i = 0; i < n; i++)
+    {
+#ifdef WORDS_BIGENDIAN
+      dst_rgba = ((art_u32 *)buf)[i];
+      dst_alpha = dst_rgba & 0xff;
+#else
+      dst_abgr = ((art_u32 *)buf)[i];
+      dst_alpha = (dst_abgr >> 24) & 0xff;
+#endif
+      if (dst_alpha)
+       {
+#ifdef ART_OPTIMIZE_SPACE
+         tmp = (255 - alpha) * (255 - dst_alpha) + 0x80;
+         a = 255 - ((tmp + (tmp >> 8)) >> 8);
+         c = ((alpha << 16) + (a >> 1)) / a;
+#else
+         tmp = art_rgba_composite_table[(alpha << 8) + dst_alpha];
+         c = tmp & 0x1ffff;
+         a = tmp >> 24;
+#endif
+#ifdef WORDS_BIGENDIAN
+         dst_r = (dst_rgba >> 24) & 0xff;
+         dst_g = (dst_rgba >> 16) & 0xff;
+         dst_b = (dst_rgba >> 8) & 0xff;
+#else
+         dst_r = dst_abgr & 0xff;
+         dst_g = (dst_abgr >> 8) & 0xff;
+         dst_b = (dst_abgr >> 16) & 0xff;
+#endif
+         dst_r += (((r - dst_r) * c + 0x8000) >> 16);
+         dst_g += (((g - dst_g) * c + 0x8000) >> 16);
+         dst_b += (((b - dst_b) * c + 0x8000) >> 16);
+#ifdef WORDS_BIGENDIAN
+         ((art_u32 *)buf)[i] = (dst_r << 24) | (dst_g << 16) | (dst_b << 8) | a;
+#else
+         ((art_u32 *)buf)[i] = (a << 24) | (dst_b << 16) | (dst_g << 8) | dst_r;
+#endif
+       }
+      else
+       {
+#ifdef WORDS_BIGENDIAN
+         ((art_u32 *)buf)[i] = src_rgba;
+#else
+         ((art_u32 *)buf)[i] = src_abgr;
+#endif
+       }
+    }
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_rgba.h b/libraries/libart_lgpl-2.3.7/art_rgba.h
new file mode 100644 (file)
index 0000000..682d5ae
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * art_rgba.h: Functions for manipulating RGBA pixel data.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGBA_H__
+#define __ART_RGBA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n);
+
+void
+art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n);
+
+void
+art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/art_svp.c b/libraries/libart_lgpl-2.3.7/art_svp.c
new file mode 100644 (file)
index 0000000..3c11d7c
--- /dev/null
@@ -0,0 +1,152 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Basic constructors and operations for sorted vector paths */
+
+#include "art_misc.h"
+
+#include "art_rect.h"
+#include "art_svp.h"
+
+/* Add a new segment. The arguments can be zero and NULL if the caller
+   would rather fill them in later.
+
+   We also realloc one auxiliary array of ints of size n_segs if
+   desired.
+*/
+/**
+ * art_svp_add_segment: Add a segment to an #ArtSVP structure.
+ * @p_vp: Pointer to where the #ArtSVP structure is stored.
+ * @pn_segs_max: Pointer to the allocated size of *@p_vp.
+ * @pn_points_max: Pointer to where auxiliary array is stored.
+ * @n_points: Number of points for new segment.
+ * @dir: Direction for new segment; 0 is up, 1 is down.
+ * @points: Points for new segment.
+ * @bbox: Bounding box for new segment.
+ *
+ * Adds a new segment to an ArtSVP structure. This routine reallocates
+ * the structure if necessary, updating *@p_vp and *@pn_segs_max as
+ * necessary.
+ *
+ * The new segment is simply added after all other segments. Thus,
+ * this routine should be called in order consistent with the #ArtSVP
+ * sorting rules.
+ *
+ * If the @bbox argument is given, it is simply stored in the new
+ * segment. Otherwise (if it is NULL), the bounding box is computed
+ * from the @points given.
+ **/
+int
+art_svp_add_segment (ArtSVP **p_vp, int *pn_segs_max,
+                    int **pn_points_max,
+                    int n_points, int dir, ArtPoint *points,
+                    ArtDRect *bbox)
+{
+  int seg_num;
+  ArtSVP *svp;
+  ArtSVPSeg *seg;
+
+  svp = *p_vp;
+  seg_num = svp->n_segs++;
+  if (*pn_segs_max == seg_num)
+    {
+      *pn_segs_max <<= 1;
+      svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
+                                  (*pn_segs_max - 1) * sizeof(ArtSVPSeg));
+      *p_vp = svp;
+      if (pn_points_max != NULL)
+       *pn_points_max = art_renew (*pn_points_max, int, *pn_segs_max);
+    }
+  seg = &svp->segs[seg_num];
+  seg->n_points = n_points;
+  seg->dir = dir;
+  seg->points = points;
+  if (bbox)
+    seg->bbox = *bbox;
+  else if (points)
+    {
+      double x_min, x_max;
+      int i;
+
+      x_min = x_max = points[0].x;
+      for (i = 1; i < n_points; i++)
+       {
+         if (x_min > points[i].x)
+           x_min = points[i].x;
+         if (x_max < points[i].x)
+           x_max = points[i].x;
+       }
+      seg->bbox.x0 = x_min;
+      seg->bbox.y0 = points[0].y;
+      
+      seg->bbox.x1 = x_max;
+      seg->bbox.y1 = points[n_points - 1].y;
+    }
+  return seg_num;
+}
+
+
+/**
+ * art_svp_free: Free an #ArtSVP structure.
+ * @svp: #ArtSVP to free.
+ * 
+ * Frees an #ArtSVP structure and all the segments in it.
+ **/
+void
+art_svp_free (ArtSVP *svp)
+{
+  int n_segs = svp->n_segs;
+  int i;
+
+  for (i = 0; i < n_segs; i++)
+    art_free (svp->segs[i].points);
+  art_free (svp);
+}
+
+#ifdef ART_USE_NEW_INTERSECTOR
+#define EPSILON 0
+#else
+#define EPSILON 1e-6
+#endif
+
+/**
+ * art_svp_seg_compare: Compare two segments of an svp.
+ * @seg1: First segment to compare.
+ * @seg2: Second segment to compare.
+ * 
+ * Compares two segments of an svp. Return 1 if @seg2 is below or to the
+ * right of @seg1, -1 otherwise.
+ **/
+int
+art_svp_seg_compare (const void *s1, const void *s2)
+{
+  const ArtSVPSeg *seg1 = s1;
+  const ArtSVPSeg *seg2 = s2;
+
+  if (seg1->points[0].y - EPSILON > seg2->points[0].y) return 1;
+  else if (seg1->points[0].y + EPSILON < seg2->points[0].y) return -1;
+  else if (seg1->points[0].x - EPSILON > seg2->points[0].x) return 1;
+  else if (seg1->points[0].x + EPSILON < seg2->points[0].x) return -1;
+  else if ((seg1->points[1].x - seg1->points[0].x) *
+          (seg2->points[1].y - seg2->points[0].y) -
+          (seg1->points[1].y - seg1->points[0].y) *
+          (seg2->points[1].x - seg2->points[0].x) > 0) return 1;
+  else return -1;
+}
+
diff --git a/libraries/libart_lgpl-2.3.7/art_svp.h b/libraries/libart_lgpl-2.3.7/art_svp.h
new file mode 100644 (file)
index 0000000..ca5293b
--- /dev/null
@@ -0,0 +1,68 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_H__
+#define __ART_SVP_H__
+
+/* Basic data structures and constructors for sorted vector paths */
+
+#ifdef LIBART_COMPILATION
+#include "art_rect.h"
+#include "art_point.h"
+#else
+#include <art_rect.h>
+#include <art_point.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtSVP ArtSVP;
+typedef struct _ArtSVPSeg ArtSVPSeg;
+
+struct _ArtSVPSeg {
+  int n_points;
+  int dir; /* == 0 for "up", 1 for "down" */
+  ArtDRect bbox;
+  ArtPoint *points;
+};
+
+struct _ArtSVP {
+  int n_segs;
+  ArtSVPSeg segs[1];
+};
+
+int
+art_svp_add_segment (ArtSVP **p_vp, int *pn_segs_max,
+                    int **pn_points_max,
+                    int n_points, int dir, ArtPoint *points,
+                    ArtDRect *bbox);
+
+void
+art_svp_free (ArtSVP *svp);
+
+int
+art_svp_seg_compare (const void *s1, const void *s2);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_intersect.c b/libraries/libart_lgpl-2.3.7/art_svp_intersect.c
new file mode 100644 (file)
index 0000000..6d4abe8
--- /dev/null
@@ -0,0 +1,1682 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2001 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* This file contains a testbed implementation of the new intersection
+   code.
+*/
+
+#include <math.h> /* for sqrt */
+
+/* Sanitychecking verifies the main invariant on every priority queue
+   point. Do not use in production, as it slows things down way too
+   much. */
+#define noSANITYCHECK
+
+/* This can be used in production, to prevent hangs. Eventually, it
+   should not be necessary. */
+#define CHEAP_SANITYCHECK
+
+#define noVERBOSE
+#ifdef VERBOSE
+#include <stdio.h>
+#endif
+
+#include "art_misc.h"
+#include "art_svp.h"
+#include "art_svp_intersect.h"
+
+/* A priority queue - perhaps move to a separate file if it becomes
+   needed somewhere else */
+
+#define ART_PRIQ_USE_HEAP
+
+typedef struct _ArtPriQ ArtPriQ;
+typedef struct _ArtPriPoint ArtPriPoint;
+
+struct _ArtPriQ {
+  int n_items;
+  int n_items_max;
+  ArtPriPoint **items;
+};
+
+struct _ArtPriPoint {
+  double x;
+  double y;
+  void *user_data;
+};
+
+static ArtPriQ *
+art_pri_new (void)
+{
+  ArtPriQ *result = art_new (ArtPriQ, 1);
+
+  result->n_items = 0;
+  result->n_items_max = 16;
+  result->items = art_new (ArtPriPoint *, result->n_items_max);
+  return result;
+}
+
+static void
+art_pri_free (ArtPriQ *pq)
+{
+  art_free (pq->items);
+  art_free (pq);
+}
+
+static art_boolean
+art_pri_empty (ArtPriQ *pq)
+{
+  return pq->n_items == 0;
+}
+
+#ifdef ART_PRIQ_USE_HEAP
+
+/* This heap implementation is based on Vasek Chvatal's course notes:
+   http://www.cs.rutgers.edu/~chvatal/notes/pq.html#heap */
+
+static void
+art_pri_bubble_up (ArtPriQ *pq, int vacant, ArtPriPoint *missing)
+{
+  ArtPriPoint **items = pq->items;
+  int parent;
+
+  parent = (vacant - 1) >> 1;
+  while (vacant > 0 && (missing->y < items[parent]->y ||
+                       (missing->y == items[parent]->y &&
+                        missing->x < items[parent]->x)))
+    {
+      items[vacant] = items[parent];
+      vacant = parent;
+      parent = (vacant - 1) >> 1;
+    }
+
+  items[vacant] = missing;
+}
+
+static void
+art_pri_insert (ArtPriQ *pq, ArtPriPoint *point)
+{
+  if (pq->n_items == pq->n_items_max)
+    art_expand (pq->items, ArtPriPoint *, pq->n_items_max);
+
+  art_pri_bubble_up (pq, pq->n_items++, point);
+}
+
+static void
+art_pri_sift_down_from_root (ArtPriQ *pq, ArtPriPoint *missing)
+{
+  ArtPriPoint **items = pq->items;
+  int vacant = 0, child = 2;
+  int n = pq->n_items;
+
+  while (child < n)
+    {
+      if (items[child - 1]->y < items[child]->y ||
+         (items[child - 1]->y == items[child]->y &&
+          items[child - 1]->x < items[child]->x))
+       child--;
+      items[vacant] = items[child];
+      vacant = child;
+      child = (vacant + 1) << 1;
+    }
+  if (child == n)
+    {
+      items[vacant] = items[n - 1];
+      vacant = n - 1;
+    }
+
+  art_pri_bubble_up (pq, vacant, missing);
+}
+
+static ArtPriPoint *
+art_pri_choose (ArtPriQ *pq)
+{
+  ArtPriPoint *result = pq->items[0];
+
+  art_pri_sift_down_from_root (pq, pq->items[--pq->n_items]);
+  return result;
+}
+
+#else
+
+/* Choose least point in queue */
+static ArtPriPoint *
+art_pri_choose (ArtPriQ *pq)
+{
+  int i;
+  int best = 0;
+  double best_x, best_y;
+  double y;
+  ArtPriPoint *result;
+
+  if (pq->n_items == 0)
+    return NULL;
+
+  best_x = pq->items[best]->x;
+  best_y = pq->items[best]->y;
+
+  for (i = 1; i < pq->n_items; i++)
+    {
+      y = pq->items[i]->y;
+      if (y < best_y || (y == best_y && pq->items[i]->x < best_x))
+       {
+         best = i;
+         best_x = pq->items[best]->x;
+         best_y = y;
+       }
+    }
+  result = pq->items[best];
+  pq->items[best] = pq->items[--pq->n_items];
+  return result;
+}
+
+static void
+art_pri_insert (ArtPriQ *pq, ArtPriPoint *point)
+{
+  if (pq->n_items == pq->n_items_max)
+    art_expand (pq->items, ArtPriPoint *, pq->n_items_max);
+
+  pq->items[pq->n_items++] = point;
+}
+
+#endif
+
+#ifdef TEST_PRIQ
+
+#include <stdlib.h> /* for rand() */
+#include <stdio.h>
+
+static double
+double_rand (double lo, double hi, int quant)
+{
+  int tmp = rand () / (RAND_MAX * (1.0 / quant)) + 0.5;
+  return lo + tmp * ((hi - lo) / quant);
+}
+
+/*
+ * This custom allocator for priority queue points is here so I can
+ * test speed. It doesn't look like it will be that significant, but
+ * if I want a small improvement later, it's something.
+ */
+
+typedef ArtPriPoint *ArtPriPtPool;
+
+static ArtPriPtPool *
+art_pri_pt_pool_new (void)
+{
+  ArtPriPtPool *result = art_new (ArtPriPtPool, 1);
+  *result = NULL;
+  return result;
+}
+
+static ArtPriPoint *
+art_pri_pt_alloc (ArtPriPtPool *pool)
+{
+  ArtPriPoint *result = *pool;
+  if (result == NULL)
+    return art_new (ArtPriPoint, 1);
+  else
+    {
+      *pool = result->user_data;
+      return result;
+    }
+}
+
+static void
+art_pri_pt_free (ArtPriPtPool *pool, ArtPriPoint *pt)
+{
+  pt->user_data = *pool;
+  *pool = pt;
+}
+
+static void
+art_pri_pt_pool_free (ArtPriPtPool *pool)
+{
+  ArtPriPoint *pt = *pool;
+  while (pt != NULL)
+    {
+      ArtPriPoint *next = pt->user_data;
+      art_free (pt);
+      pt = next;
+    }
+  art_free (pool);
+}
+
+int
+main (int argc, char **argv)
+{
+  ArtPriPtPool *pool = art_pri_pt_pool_new ();
+  ArtPriQ *pq;
+  int i, j;
+  const int n_iter = 1;
+  const int pq_size = 100;
+
+  for (j = 0; j < n_iter; j++)
+    {
+      pq = art_pri_new ();
+
+      for (i = 0; i < pq_size; i++)
+       {
+         ArtPriPoint *pt = art_pri_pt_alloc (pool);
+         pt->x = double_rand (0, 1, 100);
+         pt->y = double_rand (0, 1, 100);
+         pt->user_data = (void *)i;
+         art_pri_insert (pq, pt);
+       }
+
+      while (!art_pri_empty (pq))
+       {
+         ArtPriPoint *pt = art_pri_choose (pq);
+         if (n_iter == 1)
+           printf ("(%g, %g), %d\n", pt->x, pt->y, (int)pt->user_data);
+         art_pri_pt_free (pool, pt);
+       }
+
+      art_pri_free (pq);
+    }
+  art_pri_pt_pool_free (pool);
+  return 0;
+}
+
+#else /* TEST_PRIQ */
+
+/* A virtual class for an "svp writer". A client of this object creates an
+   SVP by repeatedly calling "add segment" and "add point" methods on it.
+*/
+
+typedef struct _ArtSvpWriterRewind ArtSvpWriterRewind;
+
+/* An implementation of the svp writer virtual class that applies the
+   winding rule. */
+
+struct _ArtSvpWriterRewind {
+  ArtSvpWriter super;
+  ArtWindRule rule;
+  ArtSVP *svp;
+  int n_segs_max;
+  int *n_points_max;
+};
+
+static int
+art_svp_writer_rewind_add_segment (ArtSvpWriter *self, int wind_left,
+                                  int delta_wind, double x, double y)
+{
+  ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self;
+  ArtSVP *svp;
+  ArtSVPSeg *seg;
+  art_boolean left_filled, right_filled;
+  int wind_right = wind_left + delta_wind;
+  int seg_num;
+  const int init_n_points_max = 4;
+
+  switch (swr->rule)
+    {
+    case ART_WIND_RULE_NONZERO:
+      left_filled = (wind_left != 0);
+      right_filled = (wind_right != 0);
+      break;
+    case ART_WIND_RULE_INTERSECT:
+      left_filled = (wind_left > 1);
+      right_filled = (wind_right > 1);
+      break;
+    case ART_WIND_RULE_ODDEVEN:
+      left_filled = (wind_left & 1);
+      right_filled = (wind_right & 1);
+      break;
+    case ART_WIND_RULE_POSITIVE:
+      left_filled = (wind_left > 0);
+      right_filled = (wind_right > 0);
+      break;
+    default:
+      art_die ("Unknown wind rule %d\n", swr->rule);
+    }
+  if (left_filled == right_filled)
+    {
+      /* discard segment now */
+#ifdef VERBOSE
+      printf ("swr add_segment: %d += %d (%g, %g) --> -1\n",
+             wind_left, delta_wind, x, y);
+#endif
+      return -1;
+   }
+
+  svp = swr->svp;
+  seg_num = svp->n_segs++;
+  if (swr->n_segs_max == seg_num)
+    {
+      swr->n_segs_max <<= 1;
+      svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
+                                  (swr->n_segs_max - 1) *
+                                  sizeof(ArtSVPSeg));
+      swr->svp = svp;
+      swr->n_points_max = art_renew (swr->n_points_max, int,
+                                    swr->n_segs_max);
+    }
+  seg = &svp->segs[seg_num];
+  seg->n_points = 1;
+  seg->dir = right_filled;
+  swr->n_points_max[seg_num] = init_n_points_max;
+  seg->bbox.x0 = x;
+  seg->bbox.y0 = y;
+  seg->bbox.x1 = x;
+  seg->bbox.y1 = y;
+  seg->points = art_new (ArtPoint, init_n_points_max);
+  seg->points[0].x = x;
+  seg->points[0].y = y;
+#ifdef VERBOSE
+    printf ("swr add_segment: %d += %d (%g, %g) --> %d(%s)\n",
+           wind_left, delta_wind, x, y, seg_num,
+           seg->dir ? "v" : "^");
+#endif
+  return seg_num;
+}
+
+static void
+art_svp_writer_rewind_add_point (ArtSvpWriter *self, int seg_id,
+                                double x, double y)
+{
+  ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self;
+  ArtSVPSeg *seg;
+  int n_points;
+
+#ifdef VERBOSE
+  printf ("swr add_point: %d (%g, %g)\n", seg_id, x, y);
+#endif
+  if (seg_id < 0)
+    /* omitted segment */
+    return;
+
+  seg = &swr->svp->segs[seg_id];
+  n_points = seg->n_points++;
+  if (swr->n_points_max[seg_id] == n_points)
+    art_expand (seg->points, ArtPoint, swr->n_points_max[seg_id]);
+  seg->points[n_points].x = x;
+  seg->points[n_points].y = y;
+  if (x < seg->bbox.x0)
+    seg->bbox.x0 = x;
+  if (x > seg->bbox.x1)
+    seg->bbox.x1 = x;
+  seg->bbox.y1 = y;
+}
+
+static void
+art_svp_writer_rewind_close_segment (ArtSvpWriter *self, int seg_id)
+{
+  /* Not needed for this simple implementation. A potential future
+     optimization is to merge segments that can be merged safely. */
+#ifdef SANITYCHECK
+  ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self;
+  ArtSVPSeg *seg;
+
+  if (seg_id >= 0)
+    {
+      seg = &swr->svp->segs[seg_id];
+      if (seg->n_points < 2)
+       art_warn ("*** closing segment %d with only %d point%s\n",
+                 seg_id, seg->n_points, seg->n_points == 1 ? "" : "s");
+    }
+#endif
+
+#ifdef VERBOSE
+  printf ("swr close_segment: %d\n", seg_id);
+#endif
+}
+
+ArtSVP *
+art_svp_writer_rewind_reap (ArtSvpWriter *self)
+{
+  ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self;
+  ArtSVP *result = swr->svp;
+
+  art_free (swr->n_points_max);
+  art_free (swr);
+  return result;
+}
+
+ArtSvpWriter *
+art_svp_writer_rewind_new (ArtWindRule rule)
+{
+  ArtSvpWriterRewind *result = art_new (ArtSvpWriterRewind, 1);
+
+  result->super.add_segment = art_svp_writer_rewind_add_segment;
+  result->super.add_point = art_svp_writer_rewind_add_point;
+  result->super.close_segment = art_svp_writer_rewind_close_segment;
+
+  result->rule = rule;
+  result->n_segs_max = 16;
+  result->svp = art_alloc (sizeof(ArtSVP) + 
+                          (result->n_segs_max - 1) * sizeof(ArtSVPSeg));
+  result->svp->n_segs = 0;
+  result->n_points_max = art_new (int, result->n_segs_max);
+
+  return &result->super;
+}
+
+/* Now, data structures for the active list */
+
+typedef struct _ArtActiveSeg ArtActiveSeg;
+
+/* Note: BNEG is 1 for \ lines, and 0 for /. Thus,
+   x[(flags & BNEG) ^ 1] <= x[flags & BNEG] */
+#define ART_ACTIVE_FLAGS_BNEG 1
+
+/* This flag is set if the segment has been inserted into the active
+   list. */
+#define ART_ACTIVE_FLAGS_IN_ACTIVE 2
+
+/* This flag is set when the segment is to be deleted in the
+   horiz commit process. */
+#define ART_ACTIVE_FLAGS_DEL 4
+
+/* This flag is set if the seg_id is a valid output segment. */
+#define ART_ACTIVE_FLAGS_OUT 8
+
+/* This flag is set if the segment is in the horiz list. */
+#define ART_ACTIVE_FLAGS_IN_HORIZ 16
+
+struct _ArtActiveSeg {
+  int flags;
+  int wind_left, delta_wind;
+  ArtActiveSeg *left, *right; /* doubly linked list structure */
+
+  const ArtSVPSeg *in_seg;
+  int in_curs;
+
+  double x[2];
+  double y0, y1;
+  double a, b, c; /* line equation; ax+by+c = 0 for the line, a^2 + b^2 = 1,
+                    and a>0 */
+
+  /* bottom point and intersection point stack */
+  int n_stack;
+  int n_stack_max;
+  ArtPoint *stack;
+
+  /* horiz commit list */
+  ArtActiveSeg *horiz_left, *horiz_right;
+  double horiz_x;
+  int horiz_delta_wind;
+  int seg_id;
+};
+
+typedef struct _ArtIntersectCtx ArtIntersectCtx;
+
+struct _ArtIntersectCtx {
+  const ArtSVP *in;
+  ArtSvpWriter *out;
+
+  ArtPriQ *pq;
+
+  ArtActiveSeg *active_head;
+
+  double y;
+  ArtActiveSeg *horiz_first;
+  ArtActiveSeg *horiz_last;
+
+  /* segment index of next input segment to be added to pri q */
+  int in_curs;
+};
+
+#define EPSILON_A 1e-5 /* Threshold for breaking lines at point insertions */
+
+/**
+ * art_svp_intersect_setup_seg: Set up an active segment from input segment.
+ * @seg: Active segment.
+ * @pri_pt: Priority queue point to initialize.
+ *
+ * Sets the x[], a, b, c, flags, and stack fields according to the
+ * line from the current cursor value. Sets the priority queue point
+ * to the bottom point of this line. Also advances the input segment
+ * cursor.
+ **/
+static void
+art_svp_intersect_setup_seg (ArtActiveSeg *seg, ArtPriPoint *pri_pt)
+{
+  const ArtSVPSeg *in_seg = seg->in_seg;
+  int in_curs = seg->in_curs++;
+  double x0, y0, x1, y1;
+  double dx, dy, s;
+  double a, b, r2;
+
+  x0 = in_seg->points[in_curs].x;
+  y0 = in_seg->points[in_curs].y;
+  x1 = in_seg->points[in_curs + 1].x;
+  y1 = in_seg->points[in_curs + 1].y;
+  pri_pt->x = x1;
+  pri_pt->y = y1;
+  dx = x1 - x0;
+  dy = y1 - y0;
+  r2 = dx * dx + dy * dy;
+  s = r2 == 0 ? 1 : 1 / sqrt (r2);
+  seg->a = a = dy * s;
+  seg->b = b = -dx * s;
+  seg->c = -(a * x0 + b * y0);
+  seg->flags = (seg->flags & ~ART_ACTIVE_FLAGS_BNEG) | (dx > 0);
+  seg->x[0] = x0;
+  seg->x[1] = x1;
+  seg->y0 = y0;
+  seg->y1 = y1;
+  seg->n_stack = 1;
+  seg->stack[0].x = x1;
+  seg->stack[0].y = y1;
+}
+
+/**
+ * art_svp_intersect_add_horiz: Add point to horizontal list.
+ * @ctx: Intersector context.
+ * @seg: Segment with point to insert into horizontal list.
+ *
+ * Inserts @seg into horizontal list, keeping it in ascending horiz_x
+ * order.
+ *
+ * Note: the horiz_commit routine processes "clusters" of segs in the
+ * horiz list, all sharing the same horiz_x value. The cluster is
+ * processed in active list order, rather than horiz list order. Thus,
+ * the order of segs in the horiz list sharing the same horiz_x
+ * _should_ be irrelevant. Even so, we use b as a secondary sorting key,
+ * as a "belt and suspenders" defensive coding tactic.
+ **/
+static void
+art_svp_intersect_add_horiz (ArtIntersectCtx *ctx, ArtActiveSeg *seg)
+{
+  ArtActiveSeg **pp = &ctx->horiz_last;
+  ArtActiveSeg *place;
+  ArtActiveSeg *place_right = NULL;
+
+
+#ifdef CHEAP_SANITYCHECK
+  if (seg->flags & ART_ACTIVE_FLAGS_IN_HORIZ)
+    {
+      art_warn ("*** attempt to put segment in horiz list twice\n");
+      return;
+    }
+  seg->flags |= ART_ACTIVE_FLAGS_IN_HORIZ;
+#endif
+
+#ifdef VERBOSE
+  printf ("add_horiz %lx, x = %g\n", (unsigned long) seg, seg->horiz_x);
+#endif
+  for (place = *pp; place != NULL && (place->horiz_x > seg->horiz_x ||
+                                     (place->horiz_x == seg->horiz_x &&
+                                      place->b < seg->b));
+       place = *pp)
+    {
+      place_right = place;
+      pp = &place->horiz_left;
+    }
+  *pp = seg;
+  seg->horiz_left = place;
+  seg->horiz_right = place_right;
+  if (place == NULL)
+    ctx->horiz_first = seg;
+  else
+    place->horiz_right = seg;
+}
+
+static void
+art_svp_intersect_push_pt (ArtIntersectCtx *ctx, ArtActiveSeg *seg,
+                          double x, double y)
+{
+  ArtPriPoint *pri_pt;
+  int n_stack = seg->n_stack;
+
+  if (n_stack == seg->n_stack_max)
+    art_expand (seg->stack, ArtPoint, seg->n_stack_max);
+  seg->stack[n_stack].x = x;
+  seg->stack[n_stack].y = y;
+  seg->n_stack++;
+
+  seg->x[1] = x;
+  seg->y1 = y;
+
+  pri_pt = art_new (ArtPriPoint, 1);
+  pri_pt->x = x;
+  pri_pt->y = y;
+  pri_pt->user_data = seg;
+  art_pri_insert (ctx->pq, pri_pt);
+}
+
+/**
+ * art_svp_intersect_break: Break an active segment.
+ *
+ * Note: y must be greater than the top point's y, and less than
+ * the bottom's.
+ *
+ * Return value: x coordinate of break point.
+ */
+static double
+art_svp_intersect_break (ArtIntersectCtx *ctx, ArtActiveSeg *seg,
+                        double y)
+{
+  double x0, y0, x1, y1;
+  const ArtSVPSeg *in_seg = seg->in_seg;
+  int in_curs = seg->in_curs;
+  double x;
+
+  x0 = in_seg->points[in_curs - 1].x;
+  y0 = in_seg->points[in_curs - 1].y;
+  x1 = in_seg->points[in_curs].x;
+  y1 = in_seg->points[in_curs].y;
+  x = x0 + (x1 - x0) * ((y - y0) / (y1 - y0));
+
+  /* I think we can count on min(x0, x1) <= x <= max(x0, x1) with sane
+     arithmetic, but it might be worthwhile to check just in case. */
+
+  if (y > ctx->y)
+    art_svp_intersect_push_pt (ctx, seg, x, y);
+  else
+    {
+      seg->x[0] = x;
+      seg->y0 = y;
+      seg->horiz_x = x;
+      art_svp_intersect_add_horiz (ctx, seg);
+    }
+
+  return x;
+}
+
+/**
+ * art_svp_intersect_add_point: Add a point, breaking nearby neighbors.
+ * @ctx: Intersector context.
+ * @x: X coordinate of point to add.
+ * @y: Y coordinate of point to add.
+ * @seg: "nearby" segment, or NULL if leftmost.
+ *
+ * Return value: Segment immediately to the left of the new point, or
+ * NULL if the new point is leftmost.
+ **/
+static ArtActiveSeg *
+art_svp_intersect_add_point (ArtIntersectCtx *ctx, double x, double y,
+                            ArtActiveSeg *seg)
+{
+  ArtActiveSeg *left, *right;
+  double x_min = x, x_max = x;
+  art_boolean left_live, right_live;
+  double d;
+  double new_x;
+  ArtActiveSeg *test, *result = NULL;
+  double x_test;
+
+  left = seg;
+  if (left == NULL)
+    right = ctx->active_head;
+  else
+    right = left->right; 
+  left_live = (left != NULL);
+  right_live = (right != NULL);
+  while (left_live || right_live)
+    {
+      if (left_live)
+       {
+         if (x <= left->x[left->flags & ART_ACTIVE_FLAGS_BNEG] &&
+             /* It may be that one of these conjuncts turns out to be always
+                true. We test both anyway, to be defensive. */
+             y != left->y0 && y < left->y1)
+           {
+             d = x_min * left->a + y * left->b + left->c;
+             if (d < EPSILON_A)
+               {
+                 new_x = art_svp_intersect_break (ctx, left, y);
+                 if (new_x > x_max)
+                   {
+                     x_max = new_x;
+                     right_live = (right != NULL);
+                   }
+                 else if (new_x < x_min)
+                   x_min = new_x;
+                 left = left->left;
+                 left_live = (left != NULL);
+               }
+             else
+               left_live = ART_FALSE;
+           }
+         else
+           left_live = ART_FALSE;
+       }
+      else if (right_live)
+       {
+         if (x <= right->x[(right->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] &&
+             /* It may be that one of these conjuncts turns out to be always
+                true. We test both anyway, to be defensive. */
+             y != right->y0 && y < right->y1)
+           {
+             d = x_max * right->a + y * right->b + right->c;
+             if (d > -EPSILON_A)
+               {
+                 new_x = art_svp_intersect_break (ctx, right, y);
+                 if (new_x < x_min)
+                   {
+                     x_min = new_x;
+                     left_live = (left != NULL);
+                   }
+                 else if (new_x >= x_max)
+                   x_max = new_x;
+                 right = right->right;
+                 right_live = (right != NULL);
+               }
+             else
+               right_live = ART_FALSE;
+           }
+         else
+           right_live = ART_FALSE;
+       }
+    }
+
+  /* Now, (left, right) defines an interval of segments broken. Sort
+     into ascending x order. */
+  test = left == NULL ? ctx->active_head : left->right;
+  result = left;
+  if (test != NULL && test != right)
+    {
+      x_test = test->x[1];
+      for (;;)
+       {
+         if (x_test <= x)
+           result = test;
+         test = test->right;
+         if (test == right)
+           break;
+         new_x = test->x[1];
+         if (new_x < x_test)
+           {
+             art_warn ("art_svp_intersect_add_point: non-ascending x\n");
+           }
+         x_test = new_x;
+       }
+    }
+  return result;
+}
+
+static void
+art_svp_intersect_swap_active (ArtIntersectCtx *ctx,
+                              ArtActiveSeg *left_seg, ArtActiveSeg *right_seg)
+{
+  right_seg->left = left_seg->left;
+  if (right_seg->left != NULL)
+    right_seg->left->right = right_seg;
+  else
+    ctx->active_head = right_seg;
+  left_seg->right = right_seg->right;
+  if (left_seg->right != NULL)
+    left_seg->right->left = left_seg;
+  left_seg->left = right_seg;
+  right_seg->right = left_seg;
+}
+
+typedef enum {
+  ART_BREAK_LEFT = 1,
+  ART_BREAK_RIGHT = 2
+} ArtBreakFlags;
+
+/**
+ * art_svp_intersect_test_cross: Test crossing of a pair of active segments.
+ * @ctx: Intersector context.
+ * @left_seg: Left segment of the pair.
+ * @right_seg: Right segment of the pair.
+ * @break_flags: Flags indicating whether to break neighbors.
+ *
+ * Tests crossing of @left_seg and @right_seg. If there is a crossing,
+ * inserts the intersection point into both segments.
+ *
+ * Return value: True if the intersection took place at the current
+ * scan line, indicating further iteration is needed.
+ **/
+static art_boolean
+art_svp_intersect_test_cross (ArtIntersectCtx *ctx,
+                             ArtActiveSeg *left_seg, ArtActiveSeg *right_seg,
+                             ArtBreakFlags break_flags)
+{
+  double left_x0, left_y0, left_x1;
+  double left_y1 = left_seg->y1;
+  double right_y1 = right_seg->y1;
+  double d;
+
+  const ArtSVPSeg *in_seg;
+  int in_curs;
+  double d0, d1, t;
+  double x, y; /* intersection point */
+
+#ifdef VERBOSE 
+  static int count = 0;
+
+  printf ("art_svp_intersect_test_cross %lx <-> %lx: count=%d\n",
+         (unsigned long)left_seg, (unsigned long)right_seg, count++);
+#endif
+
+  if (left_seg->y0 == right_seg->y0 && left_seg->x[0] == right_seg->x[0])
+    {
+      if (left_seg->b < right_seg->b)
+       {
+         art_svp_intersect_swap_active (ctx, left_seg, right_seg);
+         return ART_TRUE;
+       }
+      else
+       return ART_FALSE;
+    }
+
+  if (left_y1 < right_y1)
+    {
+      /* Test left (x1, y1) against right segment */
+      double left_x1 = left_seg->x[1];
+
+      if (left_x1 <
+         right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] ||
+         left_y1 == right_seg->y0)
+       return ART_FALSE;
+      d = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c;
+      if (d < -EPSILON_A)
+       return ART_FALSE;
+      else if (d < EPSILON_A)
+       {
+         double right_x1 = art_svp_intersect_break (ctx, right_seg, left_y1);
+         if (left_x1 <= right_x1)
+           return ART_FALSE;
+       }
+    }
+  else if (left_y1 > right_y1)
+    {
+      /* Test right (x1, y1) against left segment */
+      double right_x1 = right_seg->x[1];
+
+      if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] ||
+         right_y1 == left_seg->y0)
+       return ART_FALSE;
+      d = right_x1 * left_seg->a + right_y1 * left_seg->b + left_seg->c;
+      if (d > EPSILON_A)
+       return ART_FALSE;
+      else if (d > -EPSILON_A)
+       {
+         double left_x1 = art_svp_intersect_break (ctx, left_seg, right_y1);
+         if (left_x1 <= right_x1)
+           return ART_FALSE;
+       }
+    }
+  else /* left_y1 == right_y1 */
+    { 
+      double left_x1 = left_seg->x[1];
+      double right_x1 = right_seg->x[1];
+
+      if (left_x1 <= right_x1)
+       return ART_FALSE;
+    }
+
+  /* The segments cross. Find the intersection point. */
+
+  in_seg = left_seg->in_seg;
+  in_curs = left_seg->in_curs;
+  left_x0 = in_seg->points[in_curs - 1].x;
+  left_y0 = in_seg->points[in_curs - 1].y;
+  left_x1 = in_seg->points[in_curs].x;
+  left_y1 = in_seg->points[in_curs].y;
+  d0 = left_x0 * right_seg->a + left_y0 * right_seg->b + right_seg->c;
+  d1 = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c;
+  if (d0 == d1)
+    {
+      x = left_x0;
+      y = left_y0;
+    }
+  else
+    {
+      /* Is this division always safe? It could possibly overflow. */
+      t = d0 / (d0 - d1);
+      if (t <= 0)
+       {
+         x = left_x0;
+         y = left_y0;
+       }
+      else if (t >= 1)
+       {
+         x = left_x1;
+         y = left_y1;
+       }
+      else
+       {
+         x = left_x0 + t * (left_x1 - left_x0);
+         y = left_y0 + t * (left_y1 - left_y0);
+       }
+    }
+
+  /* Make sure intersection point is within bounds of right seg. */
+  if (y < right_seg->y0)
+    {
+      x = right_seg->x[0];
+      y = right_seg->y0;
+    }
+  else if (y > right_seg->y1)
+    {
+      x = right_seg->x[1];
+      y = right_seg->y1;
+    }
+  else if (x < right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1])
+    x = right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1];
+  else if (x > right_seg->x[right_seg->flags & ART_ACTIVE_FLAGS_BNEG])
+    x = right_seg->x[right_seg->flags & ART_ACTIVE_FLAGS_BNEG];
+
+  if (y == left_seg->y0)
+    {
+      if (y != right_seg->y0)
+       {
+#ifdef VERBOSE
+         printf ("art_svp_intersect_test_cross: intersection (%g, %g) matches former y0 of %lx, %lx\n",
+                   x, y, (unsigned long)left_seg, (unsigned long)right_seg);
+#endif
+         art_svp_intersect_push_pt (ctx, right_seg, x, y);
+         if ((break_flags & ART_BREAK_RIGHT) && right_seg->right != NULL)
+           art_svp_intersect_add_point (ctx, x, y, right_seg->right);
+       }
+      else
+       {
+         /* Intersection takes place at current scan line; process
+            immediately rather than queueing intersection point into
+            priq. */
+
+         /* Choose "most vertical" segement */
+         if (left_seg->a > right_seg->a)
+           x = left_seg->x[0];
+         else
+           x = right_seg->x[0];
+         /* todo: fudge x */
+
+         art_svp_intersect_swap_active (ctx, left_seg, right_seg);
+         return ART_TRUE;
+       }
+    }
+  else if (y == right_seg->y0)
+    {
+#ifdef VERBOSE
+      printf ("*** art_svp_intersect_test_cross: intersection (%g, %g) matches latter y0 of %lx, %lx\n",
+             x, y, (unsigned long)left_seg, (unsigned long)right_seg);
+#endif
+      art_svp_intersect_push_pt (ctx, left_seg, x, y);
+      if ((break_flags & ART_BREAK_LEFT) && left_seg->left != NULL)
+       art_svp_intersect_add_point (ctx, x, y, left_seg->left);
+    }
+  else
+    {
+#ifdef VERBOSE
+      printf ("Inserting (%g, %g) into %lx, %lx\n",
+             x, y, (unsigned long)left_seg, (unsigned long)right_seg);
+#endif
+      /* Insert the intersection point into both segments. */
+      art_svp_intersect_push_pt (ctx, left_seg, x, y);
+      art_svp_intersect_push_pt (ctx, right_seg, x, y);
+      if ((break_flags & ART_BREAK_LEFT) && left_seg->left != NULL)
+       art_svp_intersect_add_point (ctx, x, y, left_seg->left);
+      if ((break_flags & ART_BREAK_RIGHT) && right_seg->right != NULL)
+       art_svp_intersect_add_point (ctx, x, y, right_seg->right);
+    }
+  return ART_FALSE;
+}
+
+/**
+ * art_svp_intersect_active_delete: Delete segment from active list.
+ * @ctx: Intersection context.
+ * @seg: Segment to delete.
+ *
+ * Deletes @seg from the active list.
+ **/
+static /* todo inline */ void
+art_svp_intersect_active_delete (ArtIntersectCtx *ctx, ArtActiveSeg *seg)
+{
+  ArtActiveSeg *left = seg->left, *right = seg->right;
+
+  if (left != NULL)
+    left->right = right;
+  else
+    ctx->active_head = right;
+  if (right != NULL)
+    right->left = left;
+}
+
+/**
+ * art_svp_intersect_active_free: Free an active segment.
+ * @seg: Segment to delete.
+ *
+ * Frees @seg.
+ **/
+static /* todo inline */ void
+art_svp_intersect_active_free (ArtActiveSeg *seg)
+{
+  art_free (seg->stack);
+#ifdef VERBOSE
+  printf ("Freeing %lx\n", (unsigned long) seg);
+#endif
+  art_free (seg);
+}
+
+/**
+ * art_svp_intersect_insert_cross: Test crossings of newly inserted line.
+ *
+ * Tests @seg against its left and right neighbors for intersections.
+ * Precondition: the line in @seg is not purely horizontal.
+ **/
+static void
+art_svp_intersect_insert_cross (ArtIntersectCtx *ctx,
+                               ArtActiveSeg *seg)
+{
+  ArtActiveSeg *left = seg, *right = seg;
+
+  for (;;)
+    {
+      if (left != NULL && left->left != NULL)
+       {
+         if (art_svp_intersect_test_cross (ctx, left->left, left,
+                                           ART_BREAK_LEFT))
+           {
+             if (left == right || right == NULL)
+               right = left->right;
+           }
+         else
+           {
+             left = NULL;
+           }
+       }
+      else if (right != NULL && right->right != NULL)
+       {
+         if (art_svp_intersect_test_cross (ctx, right, right->right,
+                                           ART_BREAK_RIGHT))
+           {
+             if (left == right || left == NULL)
+               left = right->left;
+           }
+         else
+           {
+             right = NULL;
+           }
+       }
+      else
+       break;
+    }
+}
+
+/**
+ * art_svp_intersect_horiz: Add horizontal line segment.
+ * @ctx: Intersector context.
+ * @seg: Segment on which to add horizontal line.
+ * @x0: Old x position.
+ * @x1: New x position.
+ *
+ * Adds a horizontal line from @x0 to @x1, and updates the current
+ * location of @seg to @x1.
+ **/
+static void
+art_svp_intersect_horiz (ArtIntersectCtx *ctx, ArtActiveSeg *seg,
+                        double x0, double x1)
+{
+  ArtActiveSeg *hs;
+
+  if (x0 == x1)
+    return;
+
+  hs = art_new (ArtActiveSeg, 1);
+
+  hs->flags = ART_ACTIVE_FLAGS_DEL | (seg->flags & ART_ACTIVE_FLAGS_OUT);
+  if (seg->flags & ART_ACTIVE_FLAGS_OUT)
+    {
+      ArtSvpWriter *swr = ctx->out;
+
+      swr->add_point (swr, seg->seg_id, x0, ctx->y);
+    }
+  hs->seg_id = seg->seg_id;
+  hs->horiz_x = x0;
+  hs->horiz_delta_wind += seg->delta_wind;
+  hs->stack = NULL;
+  hs->horiz_delta_wind = 0;
+  seg->horiz_delta_wind -= seg->delta_wind;
+
+  art_svp_intersect_add_horiz (ctx, hs);
+
+  if (x0 > x1)
+    {
+      ArtActiveSeg *left;
+
+      for (left = seg->left; left != NULL; left = seg->left)
+       {
+         int left_bneg = left->flags & ART_ACTIVE_FLAGS_BNEG;
+
+         if (left->x[left_bneg] <= x1)
+           break;
+         if (left->x[left_bneg ^ 1] <= x1 &&
+             x1 * left->a + ctx->y * left->b + left->c >= 0)
+           break;
+         if (left->y0 != ctx->y && left->y1 != ctx->y)
+           {
+             art_svp_intersect_break (ctx, left, ctx->y);
+           }
+#ifdef VERBOSE
+         printf ("x0=%g > x1=%g, swapping %lx, %lx\n",
+                 x0, x1, (unsigned long)left, (unsigned long)seg);
+#endif
+         art_svp_intersect_swap_active (ctx, left, seg);
+       }
+    }
+  else
+    {
+      ArtActiveSeg *right;
+
+      for (right = seg->right; right != NULL; right = seg->right)
+       {
+         int right_bneg = right->flags & ART_ACTIVE_FLAGS_BNEG;
+
+         if (right->x[right_bneg ^ 1] >= x1)
+           break;
+         if (right->x[right_bneg] >= x1 &&
+             x1 * right->a + ctx->y * right->b + right->c <= 0)
+           break;
+         if (right->y0 != ctx->y && right->y1 != ctx->y)
+           {
+             art_svp_intersect_break (ctx, right, ctx->y);
+           }
+#ifdef VERBOSE
+         printf ("x0=%g < x1=%g, swapping %lx, %lx\n",
+                 x0, x1, (unsigned long)seg, (unsigned long)right);
+#endif
+         art_svp_intersect_swap_active (ctx, seg, right);
+       }
+    }
+
+  seg->x[0] = x1;
+  seg->x[1] = x1;
+  seg->horiz_x = x1;
+  seg->flags &= ~ART_ACTIVE_FLAGS_OUT;
+}
+
+/**
+ * art_svp_intersect_insert_line: Insert a line into the active list.
+ * @ctx: Intersector context.
+ * @seg: Segment containing line to insert.
+ *
+ * Inserts the line into the intersector context, taking care of any
+ * intersections, and adding the appropriate horizontal points to the
+ * active list.
+ **/
+static void
+art_svp_intersect_insert_line (ArtIntersectCtx *ctx, ArtActiveSeg *seg)
+{
+  if (seg->y1 == seg->y0)
+    {
+#ifdef VERBOSE
+      printf ("art_svp_intersect_insert_line: %lx is horizontal\n",
+             (unsigned long)seg);
+#endif
+      art_svp_intersect_horiz (ctx, seg, seg->x[0], seg->x[1]);
+    }
+  else
+    {
+      art_svp_intersect_insert_cross (ctx, seg);
+      art_svp_intersect_add_horiz (ctx, seg);
+    }
+}
+
+static void
+art_svp_intersect_process_intersection (ArtIntersectCtx *ctx,
+                                       ArtActiveSeg *seg)
+{
+  int n_stack = --seg->n_stack;
+  seg->x[1] = seg->stack[n_stack - 1].x;
+  seg->y1 = seg->stack[n_stack - 1].y;
+  seg->x[0] = seg->stack[n_stack].x;
+  seg->y0 = seg->stack[n_stack].y;
+  seg->horiz_x = seg->x[0];
+  art_svp_intersect_insert_line (ctx, seg);
+}
+
+static void
+art_svp_intersect_advance_cursor (ArtIntersectCtx *ctx, ArtActiveSeg *seg,
+                                 ArtPriPoint *pri_pt)
+{
+  const ArtSVPSeg *in_seg = seg->in_seg;
+  int in_curs = seg->in_curs;
+  ArtSvpWriter *swr = seg->flags & ART_ACTIVE_FLAGS_OUT ? ctx->out : NULL;
+
+  if (swr != NULL)
+    swr->add_point (swr, seg->seg_id, seg->x[1], seg->y1);
+  if (in_curs + 1 == in_seg->n_points)
+    {
+      ArtActiveSeg *left = seg->left, *right = seg->right;
+
+#if 0
+      if (swr != NULL)
+       swr->close_segment (swr, seg->seg_id);
+      seg->flags &= ~ART_ACTIVE_FLAGS_OUT;
+#endif
+      seg->flags |= ART_ACTIVE_FLAGS_DEL;
+      art_svp_intersect_add_horiz (ctx, seg);
+      art_svp_intersect_active_delete (ctx, seg);
+      if (left != NULL && right != NULL)
+       art_svp_intersect_test_cross (ctx, left, right,
+                                     ART_BREAK_LEFT | ART_BREAK_RIGHT);
+      art_free (pri_pt);
+    }
+  else
+    {
+      seg->horiz_x = seg->x[1];
+
+      art_svp_intersect_setup_seg (seg, pri_pt);
+      art_pri_insert (ctx->pq, pri_pt);
+      art_svp_intersect_insert_line (ctx, seg);
+    }
+}
+
+static void
+art_svp_intersect_add_seg (ArtIntersectCtx *ctx, const ArtSVPSeg *in_seg)
+{
+  ArtActiveSeg *seg = art_new (ArtActiveSeg, 1);
+  ArtActiveSeg *test;
+  double x0, y0;
+  ArtActiveSeg *beg_range;
+  ArtActiveSeg *last = NULL;
+  ArtActiveSeg *left, *right;
+  ArtPriPoint *pri_pt = art_new (ArtPriPoint, 1);
+
+  seg->flags = 0;
+  seg->in_seg = in_seg;
+  seg->in_curs = 0;
+
+  seg->n_stack_max = 4;
+  seg->stack = art_new (ArtPoint, seg->n_stack_max);
+
+  seg->horiz_delta_wind = 0;
+
+  pri_pt->user_data = seg;
+  art_svp_intersect_setup_seg (seg, pri_pt);
+  art_pri_insert (ctx->pq, pri_pt);
+
+  /* Find insertion place for new segment */
+  /* This is currently a left-to-right scan, but should be replaced
+     with a binary search as soon as it's validated. */
+
+  x0 = in_seg->points[0].x;
+  y0 = in_seg->points[0].y;
+  beg_range = NULL;
+  for (test = ctx->active_head; test != NULL; test = test->right)
+    {
+      double d;
+      int test_bneg = test->flags & ART_ACTIVE_FLAGS_BNEG;
+
+      if (x0 < test->x[test_bneg])
+       {
+         if (x0 < test->x[test_bneg ^ 1])
+           break;
+         d = x0 * test->a + y0 * test->b + test->c;
+         if (d < 0)
+           break;
+       }
+      last = test;
+    }
+
+  left = art_svp_intersect_add_point (ctx, x0, y0, last);
+  seg->left = left;
+  if (left == NULL)
+    {
+      right = ctx->active_head;
+      ctx->active_head = seg;
+    }
+  else
+    {
+      right = left->right;
+      left->right = seg;
+    }
+  seg->right = right;
+  if (right != NULL)
+    right->left = seg;
+
+  seg->delta_wind = in_seg->dir ? 1 : -1;
+  seg->horiz_x = x0;
+
+  art_svp_intersect_insert_line (ctx, seg);
+}
+
+#ifdef SANITYCHECK
+static void
+art_svp_intersect_sanitycheck_winding (ArtIntersectCtx *ctx)
+{
+#if 0
+  /* At this point, we seem to be getting false positives, so it's
+     turned off for now. */
+
+  ArtActiveSeg *seg;
+  int winding_number = 0;
+
+  for (seg = ctx->active_head; seg != NULL; seg = seg->right)
+    {
+      /* Check winding number consistency. */
+      if (seg->flags & ART_ACTIVE_FLAGS_OUT)
+       {
+         if (winding_number != seg->wind_left)
+           art_warn ("*** art_svp_intersect_sanitycheck_winding: seg %lx has wind_left of %d, expected %d\n",
+                 (unsigned long) seg, seg->wind_left, winding_number);
+         winding_number = seg->wind_left + seg->delta_wind;
+       }
+    }
+  if (winding_number != 0)
+    art_warn ("*** art_svp_intersect_sanitycheck_winding: non-balanced winding number %d\n",
+             winding_number);
+#endif
+}
+#endif
+
+/**
+ * art_svp_intersect_horiz_commit: Commit points in horiz list to output.
+ * @ctx: Intersection context.
+ *
+ * The main function of the horizontal commit is to output new
+ * points to the output writer.
+ *
+ * This "commit" pass is also where winding numbers are assigned,
+ * because doing it here provides much greater tolerance for inputs
+ * which are not in strict SVP order.
+ *
+ * Each cluster in the horiz_list contains both segments that are in
+ * the active list (ART_ACTIVE_FLAGS_DEL is false) and that are not,
+ * and are scheduled to be deleted (ART_ACTIVE_FLAGS_DEL is true). We
+ * need to deal with both.
+ **/
+static void
+art_svp_intersect_horiz_commit (ArtIntersectCtx *ctx)
+{
+  ArtActiveSeg *seg;
+  int winding_number = 0; /* initialization just to avoid warning */
+  int horiz_wind = 0;
+  double last_x = 0; /* initialization just to avoid warning */
+
+#ifdef VERBOSE
+  printf ("art_svp_intersect_horiz_commit: y=%g\n", ctx->y);
+  for (seg = ctx->horiz_first; seg != NULL; seg = seg->horiz_right)
+    printf (" %lx: %g %+d\n",
+           (unsigned long)seg, seg->horiz_x, seg->horiz_delta_wind);
+#endif
+
+  /* Output points to svp writer. */
+  for (seg = ctx->horiz_first; seg != NULL;)
+    {
+      /* Find a cluster with common horiz_x, */
+      ArtActiveSeg *curs;
+      double x = seg->horiz_x;
+
+      /* Generate any horizontal segments. */
+      if (horiz_wind != 0)
+       {
+         ArtSvpWriter *swr = ctx->out;
+         int seg_id;
+
+         seg_id = swr->add_segment (swr, winding_number, horiz_wind,
+                                    last_x, ctx->y);
+         swr->add_point (swr, seg_id, x, ctx->y);
+         swr->close_segment (swr, seg_id);
+       }
+
+      /* Find first active segment in cluster. */
+
+      for (curs = seg; curs != NULL && curs->horiz_x == x;
+          curs = curs->horiz_right)
+       if (!(curs->flags & ART_ACTIVE_FLAGS_DEL))
+         break;
+
+      if (curs != NULL && curs->horiz_x == x)
+       {
+         /* There exists at least one active segment in this cluster. */
+
+         /* Find beginning of cluster. */
+         for (; curs->left != NULL; curs = curs->left)
+           if (curs->left->horiz_x != x)
+             break;
+
+         if (curs->left != NULL)
+           winding_number = curs->left->wind_left + curs->left->delta_wind;
+         else
+           winding_number = 0;
+
+         do
+           {
+#ifdef VERBOSE
+             printf (" winding_number = %d += %d\n",
+                     winding_number, curs->delta_wind);
+#endif
+             if (!(curs->flags & ART_ACTIVE_FLAGS_OUT) ||
+                 curs->wind_left != winding_number)
+               {
+                 ArtSvpWriter *swr = ctx->out;
+
+                 if (curs->flags & ART_ACTIVE_FLAGS_OUT)
+                   {
+                     swr->add_point (swr, curs->seg_id,
+                                     curs->horiz_x, ctx->y);
+                     swr->close_segment (swr, curs->seg_id);
+                   }
+
+                 curs->seg_id = swr->add_segment (swr, winding_number,
+                                                  curs->delta_wind,
+                                                  x, ctx->y);
+                 curs->flags |= ART_ACTIVE_FLAGS_OUT;
+               }
+             curs->wind_left = winding_number;
+             winding_number += curs->delta_wind;
+             curs = curs->right;
+           }
+         while (curs != NULL && curs->horiz_x == x);
+       }
+
+      /* Skip past cluster. */
+      do
+       {
+         ArtActiveSeg *next = seg->horiz_right;
+
+         seg->flags &= ~ART_ACTIVE_FLAGS_IN_HORIZ;
+         horiz_wind += seg->horiz_delta_wind;
+         seg->horiz_delta_wind = 0;
+         if (seg->flags & ART_ACTIVE_FLAGS_DEL)
+           {
+             if (seg->flags & ART_ACTIVE_FLAGS_OUT)
+               {
+                 ArtSvpWriter *swr = ctx->out;
+                 swr->close_segment (swr, seg->seg_id);
+               }
+             art_svp_intersect_active_free (seg);
+           }
+         seg = next;
+       }
+      while (seg != NULL && seg->horiz_x == x);
+
+      last_x = x;
+    }
+  ctx->horiz_first = NULL;
+  ctx->horiz_last = NULL;
+#ifdef SANITYCHECK
+  art_svp_intersect_sanitycheck_winding (ctx);
+#endif
+}
+
+#ifdef VERBOSE
+static void
+art_svp_intersect_print_active (ArtIntersectCtx *ctx)
+{
+  ArtActiveSeg *seg;
+
+  printf ("Active list (y = %g):\n", ctx->y);
+  for (seg = ctx->active_head; seg != NULL; seg = seg->right)
+    {
+      printf (" %lx: (%g, %g)-(%g, %g), (a, b, c) = (%g, %g, %g)\n",
+             (unsigned long)seg,
+             seg->x[0], seg->y0, seg->x[1], seg->y1,
+             seg->a, seg->b, seg->c);
+    }
+}
+#endif
+
+#ifdef SANITYCHECK
+static void
+art_svp_intersect_sanitycheck (ArtIntersectCtx *ctx)
+{
+  ArtActiveSeg *seg;
+  ArtActiveSeg *last = NULL;
+  double d;
+
+  for (seg = ctx->active_head; seg != NULL; seg = seg->right)
+    {
+      if (seg->left != last)
+       {
+         art_warn ("*** art_svp_intersect_sanitycheck: last=%lx, seg->left=%lx\n",
+                   (unsigned long)last, (unsigned long)seg->left);
+       }
+      if (last != NULL)
+       {
+         /* pairwise compare with previous seg */
+
+         /* First the top. */
+         if (last->y0 < seg->y0)
+           {
+           }
+         else
+           {
+           }
+
+         /* Then the bottom. */
+         if (last->y1 < seg->y1)
+           {
+             if (!((last->x[1] <
+                    seg->x[(seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1]) ||
+                   last->y1 == seg->y0))
+               {
+                 d = last->x[1] * seg->a + last->y1 * seg->b + seg->c;
+                 if (d >= -EPSILON_A)
+                   art_warn ("*** bottom (%g, %g) of %lx is not clear of %lx to right (d = %g)\n",
+                             last->x[1], last->y1, (unsigned long) last,
+                             (unsigned long) seg, d);
+               }
+           }
+         else if (last->y1 > seg->y1)
+
+           {
+             if (!((seg->x[1] >
+                    last->x[last->flags & ART_ACTIVE_FLAGS_BNEG]) ||
+                   seg->y1 == last->y0))
+             {
+               d = seg->x[1] * last->a + seg->y1 * last->b + last->c;
+               if (d <= EPSILON_A)
+                 art_warn ("*** bottom (%g, %g) of %lx is not clear of %lx to left (d = %g)\n",
+                             seg->x[1], seg->y1, (unsigned long) seg,
+                             (unsigned long) last, d);
+             }
+           }
+         else
+           {
+             if (last->x[1] > seg->x[1])
+               art_warn ("*** bottoms (%g, %g) of %lx and (%g, %g) of %lx out of order\n",
+                         last->x[1], last->y1, (unsigned long)last,
+                         seg->x[1], seg->y1, (unsigned long)seg);
+           }
+       }
+      last = seg;
+    }
+}
+#endif
+
+void
+art_svp_intersector (const ArtSVP *in, ArtSvpWriter *out)
+{
+  ArtIntersectCtx *ctx;
+  ArtPriQ *pq;
+  ArtPriPoint *first_point;
+#ifdef VERBOSE
+  int count = 0;
+#endif
+
+  if (in->n_segs == 0)
+    return;
+
+  ctx = art_new (ArtIntersectCtx, 1);
+  ctx->in = in;
+  ctx->out = out;
+  pq = art_pri_new ();
+  ctx->pq = pq;
+
+  ctx->active_head = NULL;
+
+  ctx->horiz_first = NULL;
+  ctx->horiz_last = NULL;
+
+  ctx->in_curs = 0;
+  first_point = art_new (ArtPriPoint, 1);
+  first_point->x = in->segs[0].points[0].x;
+  first_point->y = in->segs[0].points[0].y;
+  first_point->user_data = NULL;
+  ctx->y = first_point->y;
+  art_pri_insert (pq, first_point);
+
+  while (!art_pri_empty (pq))
+    {
+      ArtPriPoint *pri_point = art_pri_choose (pq);
+      ArtActiveSeg *seg = (ArtActiveSeg *)pri_point->user_data;
+
+#ifdef VERBOSE
+      printf ("\nIntersector step %d\n", count++);
+      art_svp_intersect_print_active (ctx);
+      printf ("priq choose (%g, %g) %lx\n", pri_point->x, pri_point->y,
+             (unsigned long)pri_point->user_data);
+#endif
+#ifdef SANITYCHECK
+      art_svp_intersect_sanitycheck(ctx);
+#endif
+
+      if (ctx->y != pri_point->y)
+       {
+         art_svp_intersect_horiz_commit (ctx);
+         ctx->y = pri_point->y;
+       }
+
+      if (seg == NULL)
+       {
+         /* Insert new segment from input */
+         const ArtSVPSeg *in_seg = &in->segs[ctx->in_curs++];
+         art_svp_intersect_add_seg (ctx, in_seg);
+         if (ctx->in_curs < in->n_segs)
+           {
+             const ArtSVPSeg *next_seg = &in->segs[ctx->in_curs];
+             pri_point->x = next_seg->points[0].x;
+             pri_point->y = next_seg->points[0].y;
+             /* user_data is already NULL */
+             art_pri_insert (pq, pri_point);
+           }
+         else
+           art_free (pri_point);
+       }
+      else
+       {
+         int n_stack = seg->n_stack;
+
+         if (n_stack > 1)
+           {
+             art_svp_intersect_process_intersection (ctx, seg);
+             art_free (pri_point);
+           }
+         else
+           {
+             art_svp_intersect_advance_cursor (ctx, seg, pri_point);
+           }
+       }
+    }
+
+  art_svp_intersect_horiz_commit (ctx);
+
+  art_pri_free (pq);
+  art_free (ctx);
+}
+
+#endif /* not TEST_PRIQ */
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_intersect.h b/libraries/libart_lgpl-2.3.7/art_svp_intersect.h
new file mode 100644 (file)
index 0000000..351cdba
--- /dev/null
@@ -0,0 +1,64 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2001 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_INTERSECT_H__
+#define __ART_SVP_INTERSECT_H__
+
+/* The funky new SVP intersector. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef ART_WIND_RULE_DEFINED
+#define ART_WIND_RULE_DEFINED
+typedef enum {
+  ART_WIND_RULE_NONZERO,
+  ART_WIND_RULE_INTERSECT,
+  ART_WIND_RULE_ODDEVEN,
+  ART_WIND_RULE_POSITIVE
+} ArtWindRule;
+#endif
+
+typedef struct _ArtSvpWriter ArtSvpWriter;
+
+struct _ArtSvpWriter {
+  int (*add_segment) (ArtSvpWriter *self, int wind_left, int delta_wind,
+                     double x, double y);
+  void (*add_point) (ArtSvpWriter *self, int seg_id, double x, double y);
+  void (*close_segment) (ArtSvpWriter *self, int seg_id);
+};
+
+ArtSvpWriter *
+art_svp_writer_rewind_new (ArtWindRule rule);
+
+ArtSVP *
+art_svp_writer_rewind_reap (ArtSvpWriter *self);
+
+int
+art_svp_seg_compare (const void *s1, const void *s2);
+
+void
+art_svp_intersector (const ArtSVP *in, ArtSvpWriter *out);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_INTERSECT_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_ops.c b/libraries/libart_lgpl-2.3.7/art_svp_ops.c
new file mode 100644 (file)
index 0000000..a383806
--- /dev/null
@@ -0,0 +1,371 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#define noVERBOSE
+
+/* Vector path set operations, over sorted vpaths. */
+
+#include "art_misc.h"
+
+#include "art_svp.h"
+#include "art_vpath.h"
+#include "art_svp_vpath.h"
+#include "art_svp.h"
+#ifdef ART_USE_NEW_INTERSECTOR
+#include "art_svp_intersect.h"
+#else
+#include "art_svp_wind.h"
+#endif
+#include "art_svp_ops.h"
+#include "art_vpath_svp.h"
+
+/* Merge the segments of the two svp's. The resulting svp will share
+   segments with args passed in, so be super-careful with the
+   allocation.  */
+/**
+ * art_svp_merge: Merge the segments of two svp's.
+ * @svp1: One svp to merge.
+ * @svp2: The other svp to merge.
+ *
+ * Merges the segments of two SVP's into a new one. The resulting
+ * #ArtSVP data structure will share the segments of the argument
+ * svp's, so it is probably a good idea to free it shallowly,
+ * especially if the arguments will be freed with art_svp_free().
+ *
+ * Return value: The merged #ArtSVP.
+ **/
+static ArtSVP *
+art_svp_merge (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+  ArtSVP *svp_new;
+  int ix;
+  int ix1, ix2;
+
+  svp_new = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
+                                (svp1->n_segs + svp2->n_segs - 1) *
+                                sizeof(ArtSVPSeg));
+  ix1 = 0;
+  ix2 = 0;
+  for (ix = 0; ix < svp1->n_segs + svp2->n_segs; ix++)
+    {
+      if (ix1 < svp1->n_segs &&
+         (ix2 == svp2->n_segs ||
+          art_svp_seg_compare (&svp1->segs[ix1], &svp2->segs[ix2]) < 1))
+       svp_new->segs[ix] = svp1->segs[ix1++];
+      else
+       svp_new->segs[ix] = svp2->segs[ix2++];
+    }
+
+  svp_new->n_segs = ix;
+  return svp_new;
+}
+
+#ifdef VERBOSE
+
+#define XOFF 50
+#define YOFF 700
+
+static void
+print_ps_vpath (ArtVpath *vpath)
+{
+  int i;
+
+  for (i = 0; vpath[i].code != ART_END; i++)
+    {
+      switch (vpath[i].code)
+       {
+       case ART_MOVETO:
+         printf ("%g %g moveto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
+         break;
+       case ART_LINETO:
+         printf ("%g %g lineto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
+         break;
+       default:
+         break;
+       }
+    }
+  printf ("stroke showpage\n");
+}
+
+#define DELT 4
+
+static void
+print_ps_svp (ArtSVP *vpath)
+{
+  int i, j;
+
+  printf ("%% begin\n");
+  for (i = 0; i < vpath->n_segs; i++)
+    {
+      printf ("%g setgray\n", vpath->segs[i].dir ? 0.7 : 0);
+      for (j = 0; j < vpath->segs[i].n_points; j++)
+       {
+         printf ("%g %g %s\n",
+                 XOFF + vpath->segs[i].points[j].x,
+                 YOFF - vpath->segs[i].points[j].y,
+                 j ? "lineto" : "moveto");
+       }
+      printf ("%g %g moveto %g %g lineto %g %g lineto %g %g lineto stroke\n",
+             XOFF + vpath->segs[i].points[0].x - DELT,
+             YOFF - DELT - vpath->segs[i].points[0].y,
+             XOFF + vpath->segs[i].points[0].x - DELT,
+             YOFF - vpath->segs[i].points[0].y,
+             XOFF + vpath->segs[i].points[0].x + DELT,
+             YOFF - vpath->segs[i].points[0].y,
+             XOFF + vpath->segs[i].points[0].x + DELT,
+             YOFF - DELT - vpath->segs[i].points[0].y);
+      printf ("%g %g moveto %g %g lineto %g %g lineto %g %g lineto stroke\n",
+             XOFF + vpath->segs[i].points[j - 1].x - DELT,
+             YOFF + DELT - vpath->segs[i].points[j - 1].y,
+             XOFF + vpath->segs[i].points[j - 1].x - DELT,
+             YOFF - vpath->segs[i].points[j - 1].y,
+             XOFF + vpath->segs[i].points[j - 1].x + DELT,
+             YOFF - vpath->segs[i].points[j - 1].y,
+             XOFF + vpath->segs[i].points[j - 1].x + DELT,
+             YOFF + DELT - vpath->segs[i].points[j - 1].y);
+      printf ("stroke\n");
+    }
+
+  printf ("showpage\n");
+}
+#endif
+
+#ifndef ART_USE_NEW_INTERSECTOR
+static ArtSVP *
+art_svp_merge_perturbed (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+  ArtVpath *vpath1, *vpath2;
+  ArtVpath *vpath1_p, *vpath2_p;
+  ArtSVP *svp1_p, *svp2_p;
+  ArtSVP *svp_new;
+
+  vpath1 = art_vpath_from_svp (svp1);
+  vpath1_p = art_vpath_perturb (vpath1);
+  art_free (vpath1);
+  svp1_p = art_svp_from_vpath (vpath1_p);
+  art_free (vpath1_p);
+
+  vpath2 = art_vpath_from_svp (svp2);
+  vpath2_p = art_vpath_perturb (vpath2);
+  art_free (vpath2);
+  svp2_p = art_svp_from_vpath (vpath2_p);
+  art_free (vpath2_p);
+
+  svp_new = art_svp_merge (svp1_p, svp2_p);
+#ifdef VERBOSE
+  print_ps_svp (svp1_p);
+  print_ps_svp (svp2_p);
+  print_ps_svp (svp_new);
+#endif
+  art_free (svp1_p);
+  art_free (svp2_p);
+
+  return svp_new;
+}
+#endif
+
+/* Compute the union of two vector paths.
+
+   Status of this routine:
+
+   Basic correctness: Seems to work.
+
+   Numerical stability: We cheat (adding random perturbation). Thus,
+   it seems very likely that no numerical stability problems will be
+   seen in practice.
+
+   Speed: Would be better if we didn't go to unsorted vector path
+   and back to add the perturbation.
+
+   Precision: The perturbation fuzzes the coordinates slightly. In
+   cases of butting segments, razor thin long holes may appear.
+
+*/
+/**
+ * art_svp_union: Compute the union of two sorted vector paths.
+ * @svp1: One sorted vector path.
+ * @svp2: The other sorted vector path.
+ *
+ * Computes the union of the two argument svp's. Given two svp's with
+ * winding numbers of 0 and 1 everywhere, the resulting winding number
+ * will be 1 where either (or both) of the argument svp's has a
+ * winding number 1, 0 otherwise. The result is newly allocated.
+ *
+ * Currently, this routine has accuracy problems pending the
+ * implementation of the new intersector.
+ *
+ * Return value: The union of @svp1 and @svp2.
+ **/
+ArtSVP *
+art_svp_union (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+#ifdef ART_USE_NEW_INTERSECTOR 
+  ArtSVP *svp3, *svp_new;
+  ArtSvpWriter *swr;
+
+  svp3 = art_svp_merge (svp1, svp2);
+  swr = art_svp_writer_rewind_new (ART_WIND_RULE_POSITIVE);
+  art_svp_intersector (svp3, swr);
+  svp_new = art_svp_writer_rewind_reap (swr);
+  art_free (svp3); /* shallow free because svp3 contains shared segments */
+
+  return svp_new;
+#else
+  ArtSVP *svp3, *svp4, *svp_new;
+
+  svp3 = art_svp_merge_perturbed (svp1, svp2);
+  svp4 = art_svp_uncross (svp3);
+  art_svp_free (svp3);
+
+  svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_POSITIVE);
+#ifdef VERBOSE
+  print_ps_svp (svp4);
+  print_ps_svp (svp_new);
+#endif
+  art_svp_free (svp4);
+  return svp_new;
+#endif
+}
+
+/* Compute the intersection of two vector paths.
+
+   Status of this routine:
+
+   Basic correctness: Seems to work.
+
+   Numerical stability: We cheat (adding random perturbation). Thus,
+   it seems very likely that no numerical stability problems will be
+   seen in practice.
+
+   Speed: Would be better if we didn't go to unsorted vector path
+   and back to add the perturbation.
+
+   Precision: The perturbation fuzzes the coordinates slightly. In
+   cases of butting segments, razor thin long isolated segments may
+   appear.
+
+*/
+
+/**
+ * art_svp_intersect: Compute the intersection of two sorted vector paths.
+ * @svp1: One sorted vector path.
+ * @svp2: The other sorted vector path.
+ *
+ * Computes the intersection of the two argument svp's. Given two
+ * svp's with winding numbers of 0 and 1 everywhere, the resulting
+ * winding number will be 1 where both of the argument svp's has a
+ * winding number 1, 0 otherwise. The result is newly allocated.
+ *
+ * Currently, this routine has accuracy problems pending the
+ * implementation of the new intersector.
+ *
+ * Return value: The intersection of @svp1 and @svp2.
+ **/
+ArtSVP *
+art_svp_intersect (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+#ifdef ART_USE_NEW_INTERSECTOR 
+  ArtSVP *svp3, *svp_new;
+  ArtSvpWriter *swr;
+
+  svp3 = art_svp_merge (svp1, svp2);
+  swr = art_svp_writer_rewind_new (ART_WIND_RULE_INTERSECT);
+  art_svp_intersector (svp3, swr);
+  svp_new = art_svp_writer_rewind_reap (swr);
+  art_free (svp3); /* shallow free because svp3 contains shared segments */
+
+  return svp_new;
+#else
+  ArtSVP *svp3, *svp4, *svp_new;
+
+  svp3 = art_svp_merge_perturbed (svp1, svp2);
+  svp4 = art_svp_uncross (svp3);
+  art_svp_free (svp3);
+
+  svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_INTERSECT);
+  art_svp_free (svp4);
+  return svp_new;
+#endif
+}
+
+/* Compute the symmetric difference of two vector paths.
+
+   Status of this routine:
+
+   Basic correctness: Seems to work.
+
+   Numerical stability: We cheat (adding random perturbation). Thus,
+   it seems very likely that no numerical stability problems will be
+   seen in practice.
+
+   Speed: We could do a lot better by scanning through the svp
+   representations and culling out any segments that are exactly
+   identical. It would also be better if we didn't go to unsorted
+   vector path and back to add the perturbation.
+
+   Precision: Awful. In the case of inputs which are similar (the
+   common case for canvas display), the entire outline is "hairy." In
+   addition, the perturbation fuzzes the coordinates slightly. It can
+   be used as a conservative approximation.
+
+*/
+
+/**
+ * art_svp_diff: Compute the symmetric difference of two sorted vector paths.
+ * @svp1: One sorted vector path.
+ * @svp2: The other sorted vector path.
+ *
+ * Computes the symmetric of the two argument svp's. Given two svp's
+ * with winding numbers of 0 and 1 everywhere, the resulting winding
+ * number will be 1 where either, but not both, of the argument svp's
+ * has a winding number 1, 0 otherwise. The result is newly allocated.
+ *
+ * Currently, this routine has accuracy problems pending the
+ * implementation of the new intersector.
+ *
+ * Return value: The symmetric difference of @svp1 and @svp2.
+ **/
+ArtSVP *
+art_svp_diff (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+#ifdef ART_USE_NEW_INTERSECTOR 
+  ArtSVP *svp3, *svp_new;
+  ArtSvpWriter *swr;
+
+  svp3 = art_svp_merge (svp1, svp2);
+  swr = art_svp_writer_rewind_new (ART_WIND_RULE_ODDEVEN);
+  art_svp_intersector (svp3, swr);
+  svp_new = art_svp_writer_rewind_reap (swr);
+  art_free (svp3); /* shallow free because svp3 contains shared segments */
+
+  return svp_new;
+#else
+  ArtSVP *svp3, *svp4, *svp_new;
+
+  svp3 = art_svp_merge_perturbed (svp1, svp2);
+  svp4 = art_svp_uncross (svp3);
+  art_svp_free (svp3);
+
+  svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_ODDEVEN);
+  art_svp_free (svp4);
+  return svp_new;
+#endif
+}
+
+/* todo: implement minus */
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_ops.h b/libraries/libart_lgpl-2.3.7/art_svp_ops.h
new file mode 100644 (file)
index 0000000..4e0cb7f
--- /dev/null
@@ -0,0 +1,38 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_OPS_H__
+#define __ART_SVP_OPS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Vector path set operations, over sorted vpaths. */
+
+ArtSVP *art_svp_union (const ArtSVP *svp1, const ArtSVP *svp2);
+ArtSVP *art_svp_intersect (const ArtSVP *svp1, const ArtSVP *svp2);
+ArtSVP *art_svp_diff (const ArtSVP *svp1, const ArtSVP *svp2);
+ArtSVP *art_svp_minus (const ArtSVP *svp1, const ArtSVP *svp2);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_OPS_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_point.c b/libraries/libart_lgpl-2.3.7/art_svp_point.c
new file mode 100644 (file)
index 0000000..365d3d9
--- /dev/null
@@ -0,0 +1,142 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1999 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <math.h>
+#include "art_misc.h"
+
+#include "art_svp.h"
+#include "art_svp_point.h"
+
+/* Determine whether a point is inside, or near, an svp. */
+
+/* return winding number of point wrt svp */
+/**
+ * art_svp_point_wind: Determine winding number of a point with respect to svp.
+ * @svp: The svp.
+ * @x: The X coordinate of the point.
+ * @y: The Y coordinate of the point.
+ *
+ * Determine the winding number of the point @x, @y with respect to @svp.
+ *
+ * Return value: the winding number.
+ **/
+int
+art_svp_point_wind (ArtSVP *svp, double x, double y)
+{
+  int i, j;
+  int wind = 0;
+
+  for (i = 0; i < svp->n_segs; i++)
+    {
+      ArtSVPSeg *seg = &svp->segs[i];
+
+      if (seg->bbox.y0 > y)
+       break;
+
+      if (seg->bbox.y1 > y)
+       {
+         if (seg->bbox.x1 < x)
+           wind += seg->dir ? 1 : -1;
+         else if (seg->bbox.x0 <= x)
+           {
+             double x0, y0, x1, y1, dx, dy;
+
+             for (j = 0; j < seg->n_points - 1; j++)
+               {
+                 if (seg->points[j + 1].y > y)
+                   break;
+               }
+             x0 = seg->points[j].x;
+             y0 = seg->points[j].y;
+             x1 = seg->points[j + 1].x;
+             y1 = seg->points[j + 1].y;
+
+             dx = x1 - x0;
+             dy = y1 - y0;
+             if ((x - x0) * dy > (y - y0) * dx)
+               wind += seg->dir ? 1 : -1;
+           }
+       }
+    }
+
+  return wind;
+}
+
+/**
+ * art_svp_point_dist: Determine distance between point and svp.
+ * @svp: The svp.
+ * @x: The X coordinate of the point.
+ * @y: The Y coordinate of the point.
+ *
+ * Determines the distance of the point @x, @y to the closest edge in
+ * @svp. A large number is returned if @svp is empty.
+ *
+ * Return value: the distance.
+ **/
+double
+art_svp_point_dist (ArtSVP *svp, double x, double y)
+{
+  int i, j;
+  double dist_sq;
+  double best_sq = -1;
+
+  for (i = 0; i < svp->n_segs; i++)
+    {
+      ArtSVPSeg *seg = &svp->segs[i];
+      for (j = 0; j < seg->n_points - 1; j++)
+       {
+         double x0 = seg->points[j].x;
+         double y0 = seg->points[j].y;
+         double x1 = seg->points[j + 1].x;
+         double y1 = seg->points[j + 1].y;
+
+         double dx = x1 - x0;
+         double dy = y1 - y0;
+
+         double dxx0 = x - x0;
+         double dyy0 = y - y0;
+
+         double dot = dxx0 * dx + dyy0 * dy;
+
+         if (dot < 0)
+           dist_sq = dxx0 * dxx0 + dyy0 * dyy0;
+         else
+           {
+             double rr = dx * dx + dy * dy;
+
+             if (dot > rr)
+               dist_sq = (x - x1) * (x - x1) + (y - y1) * (y - y1);
+             else
+               {
+                 double perp = (y - y0) * dx - (x - x0) * dy;
+
+                 dist_sq = perp * perp / rr;
+               }
+           }
+         if (best_sq < 0 || dist_sq < best_sq)
+           best_sq = dist_sq;
+       }
+    }
+
+  if (best_sq >= 0)
+    return sqrt (best_sq);
+  else
+    return 1e12;
+}
+
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_point.h b/libraries/libart_lgpl-2.3.7/art_svp_point.h
new file mode 100644 (file)
index 0000000..1be84ad
--- /dev/null
@@ -0,0 +1,43 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1999 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_POINT_H__
+#define __ART_SVP_POINT_H__
+
+/* Determine whether a point is inside, or near, an svp. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int
+art_svp_point_wind (ArtSVP *svp, double x, double y);
+
+double
+art_svp_point_dist (ArtSVP *svp, double x, double y);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_H__ */
+
+
+
+
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_render_aa.c b/libraries/libart_lgpl-2.3.7/art_svp_render_aa.c
new file mode 100644 (file)
index 0000000..35092c6
--- /dev/null
@@ -0,0 +1,461 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* The spiffy antialiased renderer for sorted vector paths. */
+
+#include <math.h>
+#include <string.h> /* for memmove */
+#include "art_misc.h"
+
+#include "art_rect.h"
+#include "art_svp.h"
+
+#include "art_svp_render_aa.h"
+#include "stdio.h"
+
+typedef double artfloat;
+
+struct _ArtSVPRenderAAIter {
+  const ArtSVP *svp;
+  int x0, x1;
+  int y;
+  int seg_ix;
+
+  int *active_segs;
+  int n_active_segs;
+  int *cursor;
+  artfloat *seg_x;
+  artfloat *seg_dx;
+
+  ArtSVPRenderAAStep *steps;
+};
+
+static void
+art_svp_render_insert_active (int i, int *active_segs, int n_active_segs,
+                             artfloat *seg_x, artfloat *seg_dx)
+{
+  int j;
+  artfloat x;
+  int tmp1, tmp2;
+
+  /* this is a cheap hack to get ^'s sorted correctly */
+  x = seg_x[i] + 0.001 * seg_dx[i];
+  for (j = 0; j < n_active_segs && seg_x[active_segs[j]] < x; j++);
+
+  tmp1 = i;
+  while (j < n_active_segs)
+    {
+      tmp2 = active_segs[j];
+      active_segs[j] = tmp1;
+      tmp1 = tmp2;
+      j++;
+    }
+  active_segs[j] = tmp1;
+}
+
+static void
+art_svp_render_delete_active (int *active_segs, int j, int n_active_segs)
+{
+  int k;
+
+  for (k = j; k < n_active_segs; k++)
+    active_segs[k] = active_segs[k + 1];
+}
+
+#define EPSILON 1e-6
+
+/* Render the sorted vector path in the given rectangle, antialiased.
+
+   This interface uses a callback for the actual pixel rendering. The
+   callback is called y1 - y0 times (once for each scan line). The y
+   coordinate is given as an argument for convenience (it could be
+   stored in the callback's private data and incremented on each
+   call).
+
+   The rendered polygon is represented in a semi-runlength format: a
+   start value and a sequence of "steps". Each step has an x
+   coordinate and a value delta. The resulting value at position x is
+   equal to the sum of the start value and all step delta values for
+   which the step x coordinate is less than or equal to x. An
+   efficient algorithm will traverse the steps left to right, keeping
+   a running sum.
+
+   All x coordinates in the steps are guaranteed to be x0 <= x < x1.
+   (This guarantee is a change from the gfonted vpaar renderer, and is
+   designed to simplify the callback).
+
+   There is now a further guarantee that no two steps will have the
+   same x value. This may allow for further speedup and simplification
+   of renderers.
+
+   The value 0x8000 represents 0% coverage by the polygon, while
+   0xff8000 represents 100% coverage. This format is designed so that
+   >> 16 results in a standard 0x00..0xff value range, with nice
+   rounding.
+
+   Status of this routine:
+
+   Basic correctness: OK
+
+   Numerical stability: pretty good, although probably not
+   bulletproof.
+
+   Speed: Needs more aggressive culling of bounding boxes.  Can
+   probably speed up the [x0,x1) clipping of step values.  Can do more
+   of the step calculation in fixed point.
+
+   Precision: No known problems, although it should be tested
+   thoroughly, especially for symmetry.
+
+*/
+
+ArtSVPRenderAAIter *
+art_svp_render_aa_iter (const ArtSVP *svp,
+                       int x0, int y0, int x1, int y1)
+{
+  ArtSVPRenderAAIter *iter = art_new (ArtSVPRenderAAIter, 1);
+
+  iter->svp = svp;
+  iter->y = y0;
+  iter->x0 = x0;
+  iter->x1 = x1;
+  iter->seg_ix = 0;
+
+  iter->active_segs = art_new (int, svp->n_segs);
+  iter->cursor = art_new (int, svp->n_segs);
+  iter->seg_x = art_new (artfloat, svp->n_segs);
+  iter->seg_dx = art_new (artfloat, svp->n_segs);
+  iter->steps = art_new (ArtSVPRenderAAStep, x1 - x0);
+  iter->n_active_segs = 0;
+
+  return iter;
+}
+
+#define ADD_STEP(xpos, xdelta)                          \
+  /* stereotype code fragment for adding a step */      \
+  if (n_steps == 0 || steps[n_steps - 1].x < xpos)      \
+    {                                                   \
+      sx = n_steps;                                     \
+      steps[sx].x = xpos;                               \
+      steps[sx].delta = xdelta;                         \
+      n_steps++;                                        \
+    }                                                   \
+  else                                                  \
+    {                                                   \
+      for (sx = n_steps; sx > 0; sx--)                  \
+       {                                               \
+         if (steps[sx - 1].x == xpos)                  \
+           {                                           \
+             steps[sx - 1].delta += xdelta;            \
+             sx = n_steps;                             \
+             break;                                    \
+           }                                           \
+         else if (steps[sx - 1].x < xpos)              \
+           {                                           \
+             break;                                    \
+           }                                           \
+       }                                               \
+      if (sx < n_steps)                                 \
+       {                                               \
+         memmove (&steps[sx + 1], &steps[sx],          \
+                  (n_steps - sx) * sizeof(steps[0]));  \
+         steps[sx].x = xpos;                           \
+         steps[sx].delta = xdelta;                     \
+         n_steps++;                                    \
+       }                                               \
+    }
+
+void
+art_svp_render_aa_iter_step (ArtSVPRenderAAIter *iter, int *p_start,
+                            ArtSVPRenderAAStep **p_steps, int *p_n_steps)
+{
+  const ArtSVP *svp = iter->svp;
+  int *active_segs = iter->active_segs;
+  int n_active_segs = iter->n_active_segs;
+  int *cursor = iter->cursor;
+  artfloat *seg_x = iter->seg_x;
+  artfloat *seg_dx = iter->seg_dx;
+  int i = iter->seg_ix;
+  int j;
+  int x0 = iter->x0;
+  int x1 = iter->x1;
+  int y = iter->y;
+  int seg_index;
+
+  int x;
+  ArtSVPRenderAAStep *steps = iter->steps;
+  int n_steps;
+  artfloat y_top, y_bot;
+  artfloat x_top, x_bot;
+  artfloat x_min, x_max;
+  int ix_min, ix_max;
+  artfloat delta; /* delta should be int too? */
+  int last, this;
+  int xdelta;
+  artfloat rslope, drslope;
+  int start;
+  const ArtSVPSeg *seg;
+  int curs;
+  artfloat dy;
+
+  int sx;
+  
+  /* insert new active segments */
+  for (; i < svp->n_segs && svp->segs[i].bbox.y0 < y + 1; i++)
+    {
+      if (svp->segs[i].bbox.y1 > y &&
+         svp->segs[i].bbox.x0 < x1)
+       {
+         seg = &svp->segs[i];
+         /* move cursor to topmost vector which overlaps [y,y+1) */
+         for (curs = 0; seg->points[curs + 1].y < y; curs++);
+         cursor[i] = curs;
+         dy = seg->points[curs + 1].y - seg->points[curs].y;
+         if (fabs (dy) >= EPSILON)
+           seg_dx[i] = (seg->points[curs + 1].x - seg->points[curs].x) /
+             dy;
+         else
+           seg_dx[i] = 1e12;
+         seg_x[i] = seg->points[curs].x +
+           (y - seg->points[curs].y) * seg_dx[i];
+         art_svp_render_insert_active (i, active_segs, n_active_segs++,
+                                       seg_x, seg_dx);
+       }
+    }
+
+  n_steps = 0;
+
+  /* render the runlengths, advancing and deleting as we go */
+  start = 0x8000;
+
+  for (j = 0; j < n_active_segs; j++)
+    {
+      seg_index = active_segs[j];
+      seg = &svp->segs[seg_index];
+      curs = cursor[seg_index];
+      while (curs != seg->n_points - 1 &&
+            seg->points[curs].y < y + 1)
+       {
+         y_top = y;
+         if (y_top < seg->points[curs].y)
+           y_top = seg->points[curs].y;
+         y_bot = y + 1;
+         if (y_bot > seg->points[curs + 1].y)
+           y_bot = seg->points[curs + 1].y;
+         if (y_top != y_bot) {
+           delta = (seg->dir ? 16711680.0 : -16711680.0) *
+             (y_bot - y_top);
+           x_top = seg_x[seg_index] + (y_top - y) * seg_dx[seg_index];
+           x_bot = seg_x[seg_index] + (y_bot - y) * seg_dx[seg_index];
+           if (x_top < x_bot)
+             {
+               x_min = x_top;
+               x_max = x_bot;
+             }
+           else
+             {
+               x_min = x_bot;
+               x_max = x_top;
+             }
+           ix_min = floor (x_min);
+           ix_max = floor (x_max);
+           if (ix_min >= x1)
+             {
+               /* skip; it starts to the right of the render region */
+             }
+           else if (ix_max < x0)
+             /* it ends to the left of the render region */
+             start += delta;
+           else if (ix_min == ix_max)
+             {
+               /* case 1, antialias a single pixel */
+               xdelta = (ix_min + 1 - (x_min + x_max) * 0.5) * delta;
+
+               ADD_STEP(ix_min, xdelta)
+
+               if (ix_min + 1 < x1)
+                 {
+                   xdelta = delta - xdelta;
+
+                   ADD_STEP(ix_min + 1, xdelta)
+                 }
+             }
+           else
+             {
+               /* case 2, antialias a run */
+               rslope = 1.0 / fabs (seg_dx[seg_index]);
+               drslope = delta * rslope;
+               last =
+                 drslope * 0.5 *
+                 (ix_min + 1 - x_min) * (ix_min + 1 - x_min);
+               xdelta = last;
+               if (ix_min >= x0)
+                 {
+                   ADD_STEP(ix_min, xdelta)
+                   
+                   x = ix_min + 1;
+                 }
+               else
+                 {
+                   start += last;
+                   x = x0;
+                 }
+               if (ix_max > x1)
+                 ix_max = x1;
+               for (; x < ix_max; x++)
+                 {
+                   this = (seg->dir ? 16711680.0 : -16711680.0) * rslope *
+                     (x + 0.5 - x_min);
+                   xdelta = this - last;
+                   last = this;
+
+                   ADD_STEP(x, xdelta)
+                 }
+               if (x < x1)
+                 {
+                   this =
+                     delta * (1 - 0.5 *
+                              (x_max - ix_max) * (x_max - ix_max) *
+                              rslope);
+                   xdelta = this - last;
+                   last = this;
+
+                   ADD_STEP(x, xdelta)
+                   
+                   if (x + 1 < x1)
+                     {
+                       xdelta = delta - last;
+
+                       ADD_STEP(x + 1, xdelta)
+                     }
+                 }
+             }
+         }
+         curs++;
+         if (curs != seg->n_points - 1 &&
+             seg->points[curs].y < y + 1)
+           {
+             dy = seg->points[curs + 1].y - seg->points[curs].y;
+             if (fabs (dy) >= EPSILON)
+               seg_dx[seg_index] = (seg->points[curs + 1].x -
+                                    seg->points[curs].x) / dy;
+             else
+               seg_dx[seg_index] = 1e12;
+             seg_x[seg_index] = seg->points[curs].x +
+               (y - seg->points[curs].y) * seg_dx[seg_index];
+           }
+         /* break here, instead of duplicating predicate in while? */
+       }
+      if (seg->points[curs].y >= y + 1)
+       {
+         curs--;
+         cursor[seg_index] = curs;
+         seg_x[seg_index] += seg_dx[seg_index];
+       }
+      else
+       {
+         art_svp_render_delete_active (active_segs, j--,
+                                       --n_active_segs);
+       }
+    }
+
+  *p_start = start;
+  *p_steps = steps;
+  *p_n_steps = n_steps;
+
+  iter->seg_ix = i;
+  iter->n_active_segs = n_active_segs;
+  iter->y++;
+}
+
+void
+art_svp_render_aa_iter_done (ArtSVPRenderAAIter *iter)
+{
+  art_free (iter->steps);
+
+  art_free (iter->seg_dx);
+  art_free (iter->seg_x);
+  art_free (iter->cursor);
+  art_free (iter->active_segs);
+  art_free (iter);
+}
+
+/**
+ * art_svp_render_aa: Render SVP antialiased.
+ * @svp: The #ArtSVP to render.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @callback: The callback which actually paints the pixels.
+ * @callback_data: Private data for @callback.
+ *
+ * Renders the sorted vector path in the given rectangle, antialiased.
+ *
+ * This interface uses a callback for the actual pixel rendering. The
+ * callback is called @y1 - @y0 times (once for each scan line). The y
+ * coordinate is given as an argument for convenience (it could be
+ * stored in the callback's private data and incremented on each
+ * call).
+ *
+ * The rendered polygon is represented in a semi-runlength format: a
+ * start value and a sequence of "steps". Each step has an x
+ * coordinate and a value delta. The resulting value at position x is
+ * equal to the sum of the start value and all step delta values for
+ * which the step x coordinate is less than or equal to x. An
+ * efficient algorithm will traverse the steps left to right, keeping
+ * a running sum.
+ *
+ * All x coordinates in the steps are guaranteed to be @x0 <= x < @x1.
+ * (This guarantee is a change from the gfonted vpaar renderer from
+ * which this routine is derived, and is designed to simplify the
+ * callback).
+ *
+ * The value 0x8000 represents 0% coverage by the polygon, while
+ * 0xff8000 represents 100% coverage. This format is designed so that
+ * >> 16 results in a standard 0x00..0xff value range, with nice
+ * rounding.
+ * 
+ **/
+void
+art_svp_render_aa (const ArtSVP *svp,
+                  int x0, int y0, int x1, int y1,
+                  void (*callback) (void *callback_data,
+                                    int y,
+                                    int start,
+                                    ArtSVPRenderAAStep *steps, int n_steps),
+                  void *callback_data)
+{
+  ArtSVPRenderAAIter *iter;
+  int y;
+  int start;
+  ArtSVPRenderAAStep *steps;
+  int n_steps;
+
+  iter = art_svp_render_aa_iter (svp, x0, y0, x1, y1);
+
+
+  for (y = y0; y < y1; y++)
+    {
+      art_svp_render_aa_iter_step (iter, &start, &steps, &n_steps);
+      (*callback) (callback_data, y, start, steps, n_steps);
+    }
+
+  art_svp_render_aa_iter_done (iter);
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_render_aa.h b/libraries/libart_lgpl-2.3.7/art_svp_render_aa.h
new file mode 100644 (file)
index 0000000..28e4407
--- /dev/null
@@ -0,0 +1,61 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_RENDER_AA_H__
+#define __ART_SVP_RENDER_AA_H__
+
+/* The spiffy antialiased renderer for sorted vector paths. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtSVPRenderAAStep ArtSVPRenderAAStep;
+typedef struct _ArtSVPRenderAAIter ArtSVPRenderAAIter;
+
+struct _ArtSVPRenderAAStep {
+  int x;
+  int delta; /* stored with 16 fractional bits */
+};
+
+ArtSVPRenderAAIter *
+art_svp_render_aa_iter (const ArtSVP *svp,
+                       int x0, int y0, int x1, int y1);
+
+void
+art_svp_render_aa_iter_step (ArtSVPRenderAAIter *iter, int *p_start,
+                            ArtSVPRenderAAStep **p_steps, int *p_n_steps);
+
+void
+art_svp_render_aa_iter_done (ArtSVPRenderAAIter *iter);
+
+void
+art_svp_render_aa (const ArtSVP *svp,
+                  int x0, int y0, int x1, int y1,
+                  void (*callback) (void *callback_data,
+                                    int y,
+                                    int start,
+                                    ArtSVPRenderAAStep *steps, int n_steps),
+                  void *callback_data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_RENDER_AA_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_vpath.c b/libraries/libart_lgpl-2.3.7/art_svp_vpath.c
new file mode 100644 (file)
index 0000000..cfde90f
--- /dev/null
@@ -0,0 +1,213 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Sort vector paths into sorted vector paths */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "art_misc.h"
+
+#include "art_vpath.h"
+#include "art_svp.h"
+#include "art_svp_vpath.h"
+
+
+/* reverse a list of points in place */
+static void
+reverse_points (ArtPoint *points, int n_points)
+{
+  int i;
+  ArtPoint tmp_p;
+
+  for (i = 0; i < (n_points >> 1); i++)
+    {
+      tmp_p = points[i];
+      points[i] = points[n_points - (i + 1)];
+      points[n_points - (i + 1)] = tmp_p;
+    }
+}
+
+/**
+ * art_svp_from_vpath: Convert a vpath to a sorted vector path.
+ * @vpath: #ArtVPath to convert.
+ *
+ * Converts a vector path into sorted vector path form. The svp form is
+ * more efficient for rendering and other vector operations.
+ *
+ * Basically, the implementation is to traverse the vector path,
+ * generating a new segment for each "run" of points in the vector
+ * path with monotonically increasing Y values. All the resulting
+ * values are then sorted.
+ *
+ * Note: I'm not sure that the sorting rule is correct with respect
+ * to numerical stability issues.
+ *
+ * Return value: Resulting sorted vector path.
+ **/
+ArtSVP *
+art_svp_from_vpath (ArtVpath *vpath)
+{
+  int n_segs, n_segs_max;
+  ArtSVP *svp;
+  int dir;
+  int new_dir;
+  int i;
+  ArtPoint *points;
+  int n_points, n_points_max;
+  double x, y;
+  double x_min, x_max;
+
+  n_segs = 0;
+  n_segs_max = 16;
+  svp = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
+                            (n_segs_max - 1) * sizeof(ArtSVPSeg));
+
+  dir = 0;
+  n_points = 0;
+  n_points_max = 0;
+  points = NULL;
+  i = 0;
+
+  x = y = 0; /* unnecessary, given "first code must not be LINETO" invariant,
+               but it makes gcc -Wall -ansi -pedantic happier */
+  x_min = x_max = 0; /* same */
+
+  while (vpath[i].code != ART_END) {
+    if (vpath[i].code == ART_MOVETO || vpath[i].code == ART_MOVETO_OPEN)
+      {
+       if (points != NULL && n_points >= 2)
+         {
+           if (n_segs == n_segs_max)
+             {
+               n_segs_max <<= 1;
+               svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
+                                            (n_segs_max - 1) *
+                                            sizeof(ArtSVPSeg));
+             }
+           svp->segs[n_segs].n_points = n_points;
+           svp->segs[n_segs].dir = (dir > 0);
+           if (dir < 0)
+             reverse_points (points, n_points);
+           svp->segs[n_segs].points = points;
+           svp->segs[n_segs].bbox.x0 = x_min;
+           svp->segs[n_segs].bbox.x1 = x_max;
+           svp->segs[n_segs].bbox.y0 = points[0].y;
+           svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
+           n_segs++;
+           points = NULL;
+         }
+
+       if (points == NULL)
+         {
+           n_points_max = 4;
+           points = art_new (ArtPoint, n_points_max);
+         }
+
+       n_points = 1;
+       points[0].x = x = vpath[i].x;
+       points[0].y = y = vpath[i].y;
+       x_min = x;
+       x_max = x;
+       dir = 0;
+      }
+    else /* must be LINETO */
+      {
+       new_dir = (vpath[i].y > y ||
+                  (vpath[i].y == y && vpath[i].x > x)) ? 1 : -1;
+       if (dir && dir != new_dir)
+         {
+           /* new segment */
+           x = points[n_points - 1].x;
+           y = points[n_points - 1].y;
+           if (n_segs == n_segs_max)
+             {
+               n_segs_max <<= 1;
+               svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
+                                            (n_segs_max - 1) *
+                                            sizeof(ArtSVPSeg));
+             }
+           svp->segs[n_segs].n_points = n_points;
+           svp->segs[n_segs].dir = (dir > 0);
+           if (dir < 0)
+             reverse_points (points, n_points);
+           svp->segs[n_segs].points = points;
+           svp->segs[n_segs].bbox.x0 = x_min;
+           svp->segs[n_segs].bbox.x1 = x_max;
+           svp->segs[n_segs].bbox.y0 = points[0].y;
+           svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
+           n_segs++;
+
+           n_points = 1;
+           n_points_max = 4;
+           points = art_new (ArtPoint, n_points_max);
+           points[0].x = x;
+           points[0].y = y;
+           x_min = x;
+           x_max = x;
+         }
+
+       if (points != NULL)
+         {
+           if (n_points == n_points_max)
+             art_expand (points, ArtPoint, n_points_max);
+           points[n_points].x = x = vpath[i].x;
+           points[n_points].y = y = vpath[i].y;
+           if (x < x_min) x_min = x;
+           else if (x > x_max) x_max = x;
+           n_points++;
+         }
+       dir = new_dir;
+      }
+    i++;
+  }
+
+  if (points != NULL)
+    {
+      if (n_points >= 2)
+       {
+         if (n_segs == n_segs_max)
+           {
+             n_segs_max <<= 1;
+             svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
+                                          (n_segs_max - 1) *
+                                          sizeof(ArtSVPSeg));
+           }
+         svp->segs[n_segs].n_points = n_points;
+         svp->segs[n_segs].dir = (dir > 0);
+         if (dir < 0)
+           reverse_points (points, n_points);
+         svp->segs[n_segs].points = points;
+         svp->segs[n_segs].bbox.x0 = x_min;
+         svp->segs[n_segs].bbox.x1 = x_max;
+         svp->segs[n_segs].bbox.y0 = points[0].y;
+         svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
+         n_segs++;
+       }
+      else
+       art_free (points);
+    }
+
+  svp->n_segs = n_segs;
+
+  qsort (&svp->segs, n_segs, sizeof (ArtSVPSeg), art_svp_seg_compare);
+
+  return svp;
+}
+
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_vpath.h b/libraries/libart_lgpl-2.3.7/art_svp_vpath.h
new file mode 100644 (file)
index 0000000..4ff2f2d
--- /dev/null
@@ -0,0 +1,42 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_VPATH_H__
+#define __ART_SVP_VPATH_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_vpath.h"
+#else
+#include <art_vpath.h>
+#endif
+
+/* Sort vector paths into sorted vector paths. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtSVP *
+art_svp_from_vpath (ArtVpath *vpath);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_VPATH_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_vpath_stroke.c b/libraries/libart_lgpl-2.3.7/art_svp_vpath_stroke.c
new file mode 100644 (file)
index 0000000..ee556a6
--- /dev/null
@@ -0,0 +1,729 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "art_misc.h"
+
+#include "art_vpath.h"
+#include "art_svp.h"
+#ifdef ART_USE_NEW_INTERSECTOR
+#include "art_svp_intersect.h"
+#else
+#include "art_svp_wind.h"
+#endif
+#include "art_svp_vpath.h"
+#include "art_svp_vpath_stroke.h"
+
+#define EPSILON 1e-6
+#define EPSILON_2 1e-12
+
+#define yes_OPTIMIZE_INNER
+
+/* Render an arc segment starting at (xc + x0, yc + y0) to (xc + x1,
+   yc + y1), centered at (xc, yc), and with given radius. Both x0^2 +
+   y0^2 and x1^2 + y1^2 should be equal to radius^2.
+
+   A positive value of radius means curve to the left, negative means
+   curve to the right.
+*/
+static void
+art_svp_vpath_stroke_arc (ArtVpath **p_vpath, int *pn, int *pn_max,
+                         double xc, double yc,
+                         double x0, double y0,
+                         double x1, double y1,
+                         double radius,
+                         double flatness)
+{
+  double theta;
+  double th_0, th_1;
+  int n_pts;
+  int i;
+  double aradius;
+
+  aradius = fabs (radius);
+  theta = 2 * M_SQRT2 * sqrt (flatness / aradius);
+  th_0 = atan2 (y0, x0);
+  th_1 = atan2 (y1, x1);
+  if (radius > 0)
+    {
+      /* curve to the left */
+      if (th_0 < th_1) th_0 += M_PI * 2;
+      n_pts = ceil ((th_0 - th_1) / theta);
+    }
+  else
+    {
+      /* curve to the right */
+      if (th_1 < th_0) th_1 += M_PI * 2;
+      n_pts = ceil ((th_1 - th_0) / theta);
+    }
+#ifdef VERBOSE
+  printf ("start %f %f; th_0 = %f, th_1 = %f, r = %f, theta = %f\n", x0, y0, th_0, th_1, radius, theta);
+#endif
+  art_vpath_add_point (p_vpath, pn, pn_max,
+                      ART_LINETO, xc + x0, yc + y0);
+  for (i = 1; i < n_pts; i++)
+    {
+      theta = th_0 + (th_1 - th_0) * i / n_pts;
+      art_vpath_add_point (p_vpath, pn, pn_max,
+                          ART_LINETO, xc + cos (theta) * aradius,
+                          yc + sin (theta) * aradius);
+#ifdef VERBOSE
+      printf ("mid %f %f\n", cos (theta) * radius, sin (theta) * radius);
+#endif
+    }
+  art_vpath_add_point (p_vpath, pn, pn_max,
+                      ART_LINETO, xc + x1, yc + y1);
+#ifdef VERBOSE
+  printf ("end %f %f\n", x1, y1);
+#endif
+}
+
+/* Assume that forw and rev are at point i0. Bring them to i1,
+   joining with the vector i1 - i2.
+
+   This used to be true, but isn't now that the stroke_raw code is
+   filtering out (near)zero length vectors: {It so happens that all
+   invocations of this function maintain the precondition i1 = i0 + 1,
+   so we could decrease the number of arguments by one. We haven't
+   done that here, though.}
+
+   forw is to the line's right and rev is to its left.
+
+   Precondition: no zero-length vectors, otherwise a divide by
+   zero will happen.  */
+static void
+render_seg (ArtVpath **p_forw, int *pn_forw, int *pn_forw_max,
+           ArtVpath **p_rev, int *pn_rev, int *pn_rev_max,
+           ArtVpath *vpath, int i0, int i1, int i2,
+           ArtPathStrokeJoinType join,
+           double line_width, double miter_limit, double flatness)
+{
+  double dx0, dy0;
+  double dx1, dy1;
+  double dlx0, dly0;
+  double dlx1, dly1;
+  double dmx, dmy;
+  double dmr2;
+  double scale;
+  double cross;
+
+#ifdef VERBOSE
+  printf ("join style = %d\n", join);
+#endif
+
+  /* The vectors of the lines from i0 to i1 and i1 to i2. */
+  dx0 = vpath[i1].x - vpath[i0].x;
+  dy0 = vpath[i1].y - vpath[i0].y;
+
+  dx1 = vpath[i2].x - vpath[i1].x;
+  dy1 = vpath[i2].y - vpath[i1].y;
+
+  /* Set dl[xy]0 to the vector from i0 to i1, rotated counterclockwise
+     90 degrees, and scaled to the length of line_width. */
+  scale = line_width / sqrt (dx0 * dx0 + dy0 * dy0);
+  dlx0 = dy0 * scale;
+  dly0 = -dx0 * scale;
+
+  /* Set dl[xy]1 to the vector from i1 to i2, rotated counterclockwise
+     90 degrees, and scaled to the length of line_width. */
+  scale = line_width / sqrt (dx1 * dx1 + dy1 * dy1);
+  dlx1 = dy1 * scale;
+  dly1 = -dx1 * scale;
+
+#ifdef VERBOSE
+  printf ("%% render_seg: (%g, %g) - (%g, %g) - (%g, %g)\n",
+         vpath[i0].x, vpath[i0].y,
+         vpath[i1].x, vpath[i1].y,
+         vpath[i2].x, vpath[i2].y);
+
+  printf ("%% render_seg: d[xy]0 = (%g, %g), dl[xy]0 = (%g, %g)\n",
+         dx0, dy0, dlx0, dly0);
+
+  printf ("%% render_seg: d[xy]1 = (%g, %g), dl[xy]1 = (%g, %g)\n",
+         dx1, dy1, dlx1, dly1);
+#endif
+
+  /* now, forw's last point is expected to be colinear along d[xy]0
+     to point i0 - dl[xy]0, and rev with i0 + dl[xy]0. */
+
+  /* positive for positive area (i.e. left turn) */
+  cross = dx1 * dy0 - dx0 * dy1;
+
+  dmx = (dlx0 + dlx1) * 0.5;
+  dmy = (dly0 + dly1) * 0.5;
+  dmr2 = dmx * dmx + dmy * dmy;
+
+  if (join == ART_PATH_STROKE_JOIN_MITER &&
+      dmr2 * miter_limit * miter_limit < line_width * line_width)
+    join = ART_PATH_STROKE_JOIN_BEVEL;
+
+  /* the case when dmr2 is zero or very small bothers me
+     (i.e. near a 180 degree angle) */
+  scale = line_width * line_width / dmr2;
+  dmx *= scale;
+  dmy *= scale;
+
+  if (cross * cross < EPSILON_2 && dx0 * dx1 + dy0 * dy1 >= 0)
+    {
+      /* going straight */
+#ifdef VERBOSE
+      printf ("%% render_seg: straight\n");
+#endif
+      art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+                      ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
+      art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+                      ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
+    }
+  else if (cross > 0)
+    {
+      /* left turn, forw is outside and rev is inside */
+
+#ifdef VERBOSE
+      printf ("%% render_seg: left\n");
+#endif
+      if (
+#ifdef NO_OPTIMIZE_INNER
+         0 &&
+#endif
+         /* check that i1 + dm[xy] is inside i0-i1 rectangle */
+         (dx0 + dmx) * dx0 + (dy0 + dmy) * dy0 > 0 &&
+         /* and that i1 + dm[xy] is inside i1-i2 rectangle */
+         ((dx1 - dmx) * dx1 + (dy1 - dmy) * dy1 > 0)
+#ifdef PEDANTIC_INNER
+         &&
+         /* check that i1 + dl[xy]1 is inside i0-i1 rectangle */
+         (dx0 + dlx1) * dx0 + (dy0 + dly1) * dy0 > 0 &&
+         /* and that i1 + dl[xy]0 is inside i1-i2 rectangle */
+         ((dx1 - dlx0) * dx1 + (dy1 - dly0) * dy1 > 0)
+#endif
+         )
+       {
+         /* can safely add single intersection point */
+         art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+                          ART_LINETO, vpath[i1].x + dmx, vpath[i1].y + dmy);
+       }
+      else
+       {
+         /* need to loop-de-loop the inside */
+         art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+                          ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
+         art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+                          ART_LINETO, vpath[i1].x, vpath[i1].y);
+         art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+                          ART_LINETO, vpath[i1].x + dlx1, vpath[i1].y + dly1);
+       }
+
+      if (join == ART_PATH_STROKE_JOIN_BEVEL)
+       {
+         /* bevel */
+         art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+                          ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
+         art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+                          ART_LINETO, vpath[i1].x - dlx1, vpath[i1].y - dly1);
+       }
+      else if (join == ART_PATH_STROKE_JOIN_MITER)
+       {
+         art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+                          ART_LINETO, vpath[i1].x - dmx, vpath[i1].y - dmy);
+       }
+      else if (join == ART_PATH_STROKE_JOIN_ROUND)
+       art_svp_vpath_stroke_arc (p_forw, pn_forw, pn_forw_max,
+                                 vpath[i1].x, vpath[i1].y,
+                                 -dlx0, -dly0,
+                                 -dlx1, -dly1,
+                                 line_width,
+                                 flatness);
+    }
+  else
+    {
+      /* right turn, rev is outside and forw is inside */
+#ifdef VERBOSE
+      printf ("%% render_seg: right\n");
+#endif
+
+      if (
+#ifdef NO_OPTIMIZE_INNER
+         0 &&
+#endif
+         /* check that i1 - dm[xy] is inside i0-i1 rectangle */
+         (dx0 - dmx) * dx0 + (dy0 - dmy) * dy0 > 0 &&
+         /* and that i1 - dm[xy] is inside i1-i2 rectangle */
+         ((dx1 + dmx) * dx1 + (dy1 + dmy) * dy1 > 0)
+#ifdef PEDANTIC_INNER
+         &&
+         /* check that i1 - dl[xy]1 is inside i0-i1 rectangle */
+         (dx0 - dlx1) * dx0 + (dy0 - dly1) * dy0 > 0 &&
+         /* and that i1 - dl[xy]0 is inside i1-i2 rectangle */
+         ((dx1 + dlx0) * dx1 + (dy1 + dly0) * dy1 > 0)
+#endif
+         )
+       {
+         /* can safely add single intersection point */
+         art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+                          ART_LINETO, vpath[i1].x - dmx, vpath[i1].y - dmy);
+       }
+      else
+       {
+         /* need to loop-de-loop the inside */
+         art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+                          ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
+         art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+                          ART_LINETO, vpath[i1].x, vpath[i1].y);
+         art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+                          ART_LINETO, vpath[i1].x - dlx1, vpath[i1].y - dly1);
+       }
+
+      if (join == ART_PATH_STROKE_JOIN_BEVEL)
+       {
+         /* bevel */
+         art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+                          ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
+         art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+                          ART_LINETO, vpath[i1].x + dlx1, vpath[i1].y + dly1);
+       }
+      else if (join == ART_PATH_STROKE_JOIN_MITER)
+       {
+         art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+                          ART_LINETO, vpath[i1].x + dmx, vpath[i1].y + dmy);
+       }
+      else if (join == ART_PATH_STROKE_JOIN_ROUND)
+       art_svp_vpath_stroke_arc (p_rev, pn_rev, pn_rev_max,
+                                 vpath[i1].x, vpath[i1].y,
+                                 dlx0, dly0,
+                                 dlx1, dly1,
+                                 -line_width,
+                                 flatness);
+
+    }
+}
+
+/* caps i1, under the assumption of a vector from i0 */
+static void
+render_cap (ArtVpath **p_result, int *pn_result, int *pn_result_max,
+           ArtVpath *vpath, int i0, int i1,
+           ArtPathStrokeCapType cap, double line_width, double flatness)
+{
+  double dx0, dy0;
+  double dlx0, dly0;
+  double scale;
+  int n_pts;
+  int i;
+
+  dx0 = vpath[i1].x - vpath[i0].x;
+  dy0 = vpath[i1].y - vpath[i0].y;
+
+  /* Set dl[xy]0 to the vector from i0 to i1, rotated counterclockwise
+     90 degrees, and scaled to the length of line_width. */
+  scale = line_width / sqrt (dx0 * dx0 + dy0 * dy0);
+  dlx0 = dy0 * scale;
+  dly0 = -dx0 * scale;
+
+#ifdef VERBOSE
+  printf ("cap style = %d\n", cap);
+#endif
+
+  switch (cap)
+    {
+    case ART_PATH_STROKE_CAP_BUTT:
+      art_vpath_add_point (p_result, pn_result, pn_result_max,
+                          ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
+      art_vpath_add_point (p_result, pn_result, pn_result_max,
+                          ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
+      break;
+    case ART_PATH_STROKE_CAP_ROUND:
+      n_pts = ceil (M_PI / (2.0 * M_SQRT2 * sqrt (flatness / line_width)));
+      art_vpath_add_point (p_result, pn_result, pn_result_max,
+                          ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
+      for (i = 1; i < n_pts; i++)
+       {
+         double theta, c_th, s_th;
+
+         theta = M_PI * i / n_pts;
+         c_th = cos (theta);
+         s_th = sin (theta);
+         art_vpath_add_point (p_result, pn_result, pn_result_max,
+                              ART_LINETO,
+                              vpath[i1].x - dlx0 * c_th - dly0 * s_th,
+                              vpath[i1].y - dly0 * c_th + dlx0 * s_th);
+       }
+      art_vpath_add_point (p_result, pn_result, pn_result_max,
+                          ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
+      break;
+    case ART_PATH_STROKE_CAP_SQUARE:
+      art_vpath_add_point (p_result, pn_result, pn_result_max,
+                          ART_LINETO,
+                          vpath[i1].x - dlx0 - dly0,
+                          vpath[i1].y - dly0 + dlx0);
+      art_vpath_add_point (p_result, pn_result, pn_result_max,
+                          ART_LINETO,
+                          vpath[i1].x + dlx0 - dly0,
+                          vpath[i1].y + dly0 + dlx0);
+      break;
+    }
+}
+
+/**
+ * art_svp_from_vpath_raw: Stroke a vector path, raw version
+ * @vpath: #ArtVPath to stroke.
+ * @join: Join style.
+ * @cap: Cap style.
+ * @line_width: Width of stroke.
+ * @miter_limit: Miter limit.
+ * @flatness: Flatness.
+ *
+ * Exactly the same as art_svp_vpath_stroke(), except that the resulting
+ * stroke outline may self-intersect and have regions of winding number
+ * greater than 1.
+ *
+ * Return value: Resulting raw stroked outline in svp format.
+ **/
+ArtVpath *
+art_svp_vpath_stroke_raw (ArtVpath *vpath,
+                         ArtPathStrokeJoinType join,
+                         ArtPathStrokeCapType cap,
+                         double line_width,
+                         double miter_limit,
+                         double flatness)
+{
+  int begin_idx, end_idx;
+  int i;
+  ArtVpath *forw, *rev;
+  int n_forw, n_rev;
+  int n_forw_max, n_rev_max;
+  ArtVpath *result;
+  int n_result, n_result_max;
+  double half_lw = 0.5 * line_width;
+  int closed;
+  int last, this, next, second;
+  double dx, dy;
+
+  n_forw_max = 16;
+  forw = art_new (ArtVpath, n_forw_max);
+
+  n_rev_max = 16;
+  rev = art_new (ArtVpath, n_rev_max);
+
+  n_result = 0;
+  n_result_max = 16;
+  result = art_new (ArtVpath, n_result_max);
+
+  for (begin_idx = 0; vpath[begin_idx].code != ART_END; begin_idx = end_idx)
+    {
+      n_forw = 0;
+      n_rev = 0;
+
+      closed = (vpath[begin_idx].code == ART_MOVETO);
+
+      /* we don't know what the first point joins with until we get to the
+        last point and see if it's closed. So we start with the second
+        line in the path.
+
+        Note: this is not strictly true (we now know it's closed from
+        the opening pathcode), but why fix code that isn't broken?
+      */
+
+      this = begin_idx;
+      /* skip over identical points at the beginning of the subpath */
+      for (i = this + 1; vpath[i].code == ART_LINETO; i++)
+       {
+         dx = vpath[i].x - vpath[this].x;
+         dy = vpath[i].y - vpath[this].y;
+         if (dx * dx + dy * dy > EPSILON_2)
+           break;
+       }
+      next = i;
+      second = next;
+
+      /* invariant: this doesn't coincide with next */
+      while (vpath[next].code == ART_LINETO)
+       {
+         last = this;
+         this = next;
+         /* skip over identical points after the beginning of the subpath */
+         for (i = this + 1; vpath[i].code == ART_LINETO; i++)
+           {
+             dx = vpath[i].x - vpath[this].x;
+             dy = vpath[i].y - vpath[this].y;
+             if (dx * dx + dy * dy > EPSILON_2)
+               break;
+           }
+         next = i;
+         if (vpath[next].code != ART_LINETO)
+           {
+             /* reached end of path */
+             /* make "closed" detection conform to PostScript
+                semantics (i.e. explicit closepath code rather than
+                just the fact that end of the path is the beginning) */
+             if (closed &&
+                 vpath[this].x == vpath[begin_idx].x &&
+                 vpath[this].y == vpath[begin_idx].y)
+               {
+                 int j;
+
+                 /* path is closed, render join to beginning */
+                 render_seg (&forw, &n_forw, &n_forw_max,
+                             &rev, &n_rev, &n_rev_max,
+                             vpath, last, this, second,
+                             join, half_lw, miter_limit, flatness);
+
+#ifdef VERBOSE
+                 printf ("%% forw %d, rev %d\n", n_forw, n_rev);
+#endif
+                 /* do forward path */
+                 art_vpath_add_point (&result, &n_result, &n_result_max,
+                                  ART_MOVETO, forw[n_forw - 1].x,
+                                  forw[n_forw - 1].y);
+                 for (j = 0; j < n_forw; j++)
+                   art_vpath_add_point (&result, &n_result, &n_result_max,
+                                    ART_LINETO, forw[j].x,
+                                    forw[j].y);
+
+                 /* do reverse path, reversed */
+                 art_vpath_add_point (&result, &n_result, &n_result_max,
+                                  ART_MOVETO, rev[0].x,
+                                  rev[0].y);
+                 for (j = n_rev - 1; j >= 0; j--)
+                   art_vpath_add_point (&result, &n_result, &n_result_max,
+                                    ART_LINETO, rev[j].x,
+                                    rev[j].y);
+               }
+             else
+               {
+                 /* path is open */
+                 int j;
+
+                 /* add to forw rather than result to ensure that
+                    forw has at least one point. */
+                 render_cap (&forw, &n_forw, &n_forw_max,
+                             vpath, last, this,
+                             cap, half_lw, flatness);
+                 art_vpath_add_point (&result, &n_result, &n_result_max,
+                                  ART_MOVETO, forw[0].x,
+                                  forw[0].y);
+                 for (j = 1; j < n_forw; j++)
+                   art_vpath_add_point (&result, &n_result, &n_result_max,
+                                    ART_LINETO, forw[j].x,
+                                    forw[j].y);
+                 for (j = n_rev - 1; j >= 0; j--)
+                   art_vpath_add_point (&result, &n_result, &n_result_max,
+                                    ART_LINETO, rev[j].x,
+                                    rev[j].y);
+                 render_cap (&result, &n_result, &n_result_max,
+                             vpath, second, begin_idx,
+                             cap, half_lw, flatness);
+                 art_vpath_add_point (&result, &n_result, &n_result_max,
+                                  ART_LINETO, forw[0].x,
+                                  forw[0].y);
+               }
+           }
+         else
+           render_seg (&forw, &n_forw, &n_forw_max,
+                       &rev, &n_rev, &n_rev_max,
+                       vpath, last, this, next,
+                       join, half_lw, miter_limit, flatness);
+       }
+      end_idx = next;
+    }
+
+  art_free (forw);
+  art_free (rev);
+#ifdef VERBOSE
+  printf ("%% n_result = %d\n", n_result);
+#endif
+  art_vpath_add_point (&result, &n_result, &n_result_max, ART_END, 0, 0);
+  return result;
+}
+
+#define noVERBOSE
+
+#ifdef VERBOSE
+
+#define XOFF 50
+#define YOFF 700
+
+static void
+print_ps_vpath (ArtVpath *vpath)
+{
+  int i;
+
+  for (i = 0; vpath[i].code != ART_END; i++)
+    {
+      switch (vpath[i].code)
+       {
+       case ART_MOVETO:
+         printf ("%g %g moveto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
+         break;
+       case ART_LINETO:
+         printf ("%g %g lineto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
+         break;
+       default:
+         break;
+       }
+    }
+  printf ("stroke showpage\n");
+}
+
+static void
+print_ps_svp (ArtSVP *vpath)
+{
+  int i, j;
+
+  printf ("%% begin\n");
+  for (i = 0; i < vpath->n_segs; i++)
+    {
+      printf ("%g setgray\n", vpath->segs[i].dir ? 0.7 : 0);
+      for (j = 0; j < vpath->segs[i].n_points; j++)
+       {
+         printf ("%g %g %s\n",
+                 XOFF + vpath->segs[i].points[j].x,
+                 YOFF - vpath->segs[i].points[j].y,
+                 j ? "lineto" : "moveto");
+       }
+      printf ("stroke\n");
+    }
+
+  printf ("showpage\n");
+}
+#endif
+
+/* Render a vector path into a stroked outline.
+
+   Status of this routine:
+
+   Basic correctness: Only miter and bevel line joins are implemented,
+   and only butt line caps. Otherwise, seems to be fine.
+
+   Numerical stability: We cheat (adding random perturbation). Thus,
+   it seems very likely that no numerical stability problems will be
+   seen in practice.
+
+   Speed: Should be pretty good.
+
+   Precision: The perturbation fuzzes the coordinates slightly,
+   but not enough to be visible.  */
+/**
+ * art_svp_vpath_stroke: Stroke a vector path.
+ * @vpath: #ArtVPath to stroke.
+ * @join: Join style.
+ * @cap: Cap style.
+ * @line_width: Width of stroke.
+ * @miter_limit: Miter limit.
+ * @flatness: Flatness.
+ *
+ * Computes an svp representing the stroked outline of @vpath. The
+ * width of the stroked line is @line_width.
+ *
+ * Lines are joined according to the @join rule. Possible values are
+ * ART_PATH_STROKE_JOIN_MITER (for mitered joins),
+ * ART_PATH_STROKE_JOIN_ROUND (for round joins), and
+ * ART_PATH_STROKE_JOIN_BEVEL (for bevelled joins). The mitered join
+ * is converted to a bevelled join if the miter would extend to a
+ * distance of more than @miter_limit * @line_width from the actual
+ * join point.
+ *
+ * If there are open subpaths, the ends of these subpaths are capped
+ * according to the @cap rule. Possible values are
+ * ART_PATH_STROKE_CAP_BUTT (squared cap, extends exactly to end
+ * point), ART_PATH_STROKE_CAP_ROUND (rounded half-circle centered at
+ * the end point), and ART_PATH_STROKE_CAP_SQUARE (squared cap,
+ * extending half @line_width past the end point).
+ *
+ * The @flatness parameter controls the accuracy of the rendering. It
+ * is most important for determining the number of points to use to
+ * approximate circular arcs for round lines and joins. In general, the
+ * resulting vector path will be within @flatness pixels of the "ideal"
+ * path containing actual circular arcs. I reserve the right to use
+ * the @flatness parameter to convert bevelled joins to miters for very
+ * small turn angles, as this would reduce the number of points in the
+ * resulting outline path.
+ *
+ * The resulting path is "clean" with respect to self-intersections, i.e.
+ * the winding number is 0 or 1 at each point.
+ *
+ * Return value: Resulting stroked outline in svp format.
+ **/
+ArtSVP *
+art_svp_vpath_stroke (ArtVpath *vpath,
+                     ArtPathStrokeJoinType join,
+                     ArtPathStrokeCapType cap,
+                     double line_width,
+                     double miter_limit,
+                     double flatness)
+{
+#ifdef ART_USE_NEW_INTERSECTOR
+  ArtVpath *vpath_stroke;
+  ArtSVP *svp, *svp2;
+  ArtSvpWriter *swr;
+
+  vpath_stroke = art_svp_vpath_stroke_raw (vpath, join, cap,
+                                          line_width, miter_limit, flatness);
+#ifdef VERBOSE
+  print_ps_vpath (vpath_stroke);
+#endif
+  svp = art_svp_from_vpath (vpath_stroke);
+#ifdef VERBOSE
+  print_ps_svp (svp);
+#endif
+  art_free (vpath_stroke);
+
+  swr = art_svp_writer_rewind_new (ART_WIND_RULE_NONZERO);
+  art_svp_intersector (svp, swr);
+
+  svp2 = art_svp_writer_rewind_reap (swr);
+#ifdef VERBOSE
+  print_ps_svp (svp2);
+#endif
+  art_svp_free (svp);
+  return svp2;
+#else
+  ArtVpath *vpath_stroke, *vpath2;
+  ArtSVP *svp, *svp2, *svp3;
+
+  vpath_stroke = art_svp_vpath_stroke_raw (vpath, join, cap,
+                                          line_width, miter_limit, flatness);
+#ifdef VERBOSE
+  print_ps_vpath (vpath_stroke);
+#endif
+  vpath2 = art_vpath_perturb (vpath_stroke);
+#ifdef VERBOSE
+  print_ps_vpath (vpath2);
+#endif
+  art_free (vpath_stroke);
+  svp = art_svp_from_vpath (vpath2);
+#ifdef VERBOSE
+  print_ps_svp (svp);
+#endif
+  art_free (vpath2);
+  svp2 = art_svp_uncross (svp);
+#ifdef VERBOSE
+  print_ps_svp (svp2);
+#endif
+  art_svp_free (svp);
+  svp3 = art_svp_rewind_uncrossed (svp2, ART_WIND_RULE_NONZERO);
+#ifdef VERBOSE
+  print_ps_svp (svp3);
+#endif
+  art_svp_free (svp2);
+
+  return svp3;
+#endif
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_vpath_stroke.h b/libraries/libart_lgpl-2.3.7/art_svp_vpath_stroke.h
new file mode 100644 (file)
index 0000000..dec3cb1
--- /dev/null
@@ -0,0 +1,62 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_VPATH_STROKE_H__
+#define __ART_SVP_VPATH_STROKE_H__
+
+/* Sort vector paths into sorted vector paths. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+  ART_PATH_STROKE_JOIN_MITER,
+  ART_PATH_STROKE_JOIN_ROUND,
+  ART_PATH_STROKE_JOIN_BEVEL
+} ArtPathStrokeJoinType;
+
+typedef enum {
+  ART_PATH_STROKE_CAP_BUTT,
+  ART_PATH_STROKE_CAP_ROUND,
+  ART_PATH_STROKE_CAP_SQUARE
+} ArtPathStrokeCapType;
+
+ArtSVP *
+art_svp_vpath_stroke (ArtVpath *vpath,
+                     ArtPathStrokeJoinType join,
+                     ArtPathStrokeCapType cap,
+                     double line_width,
+                     double miter_limit,
+                     double flatness);
+
+/* This version may have winding numbers exceeding 1. */
+ArtVpath *
+art_svp_vpath_stroke_raw (ArtVpath *vpath,
+                         ArtPathStrokeJoinType join,
+                         ArtPathStrokeCapType cap,
+                         double line_width,
+                         double miter_limit,
+                         double flatness);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_VPATH_STROKE_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_wind.c b/libraries/libart_lgpl-2.3.7/art_svp_wind.c
new file mode 100644 (file)
index 0000000..ac30e6f
--- /dev/null
@@ -0,0 +1,1538 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Primitive intersection and winding number operations on sorted
+   vector paths.
+
+   These routines are internal to libart, used to construct operations
+   like intersection, union, and difference. */
+
+
+#include <stdio.h> /* for printf of debugging info */
+#include <string.h> /* for memcpy */
+#include <math.h>
+#include "art_misc.h"
+
+#include "art_rect.h"
+#include "art_svp.h"
+#include "art_svp_wind.h"
+
+#define noVERBOSE
+
+#define PT_EQ(p1,p2) ((p1).x == (p2).x && (p1).y == (p2).y)
+
+#define PT_CLOSE(p1,p2) (fabs ((p1).x - (p2).x) < 1e-6 && fabs ((p1).y - (p2).y) < 1e-6)
+
+/* return nonzero and set *p to the intersection point if the lines
+   z0-z1 and z2-z3 intersect each other. */
+static int
+intersect_lines (ArtPoint z0, ArtPoint z1, ArtPoint z2, ArtPoint z3,
+                ArtPoint *p)
+{
+  double a01, b01, c01;
+  double a23, b23, c23;
+  double d0, d1, d2, d3;
+  double det;
+
+  /* if the vectors share an endpoint, they don't intersect */
+  if (PT_EQ (z0, z2) || PT_EQ (z0, z3) || PT_EQ (z1, z2) || PT_EQ (z1, z3))
+    return 0;
+
+#if 0
+  if (PT_CLOSE (z0, z2) || PT_CLOSE (z0, z3) || PT_CLOSE (z1, z2) || PT_CLOSE (z1, z3))
+    return 0;
+#endif
+
+  /* find line equations ax + by + c = 0 */
+  a01 = z0.y - z1.y;
+  b01 = z1.x - z0.x;
+  c01 = -(z0.x * a01 + z0.y * b01);
+  /* = -((z0.y - z1.y) * z0.x + (z1.x - z0.x) * z0.y) 
+     = (z1.x * z0.y - z1.y * z0.x) */
+
+  d2 = a01 * z2.x + b01 * z2.y + c01;
+  d3 = a01 * z3.x + b01 * z3.y + c01;
+  if ((d2 > 0) == (d3 > 0))
+    return 0;
+
+  a23 = z2.y - z3.y;
+  b23 = z3.x - z2.x;
+  c23 = -(z2.x * a23 + z2.y * b23);
+
+  d0 = a23 * z0.x + b23 * z0.y + c23;
+  d1 = a23 * z1.x + b23 * z1.y + c23;
+  if ((d0 > 0) == (d1 > 0))
+    return 0;
+
+  /* now we definitely know that the lines intersect */
+  /* solve the two linear equations ax + by + c = 0 */
+  det = 1.0 / (a01 * b23 - a23 * b01);
+  p->x = det * (c23 * b01 - c01 * b23);
+  p->y = det * (c01 * a23 - c23 * a01);
+
+  return 1;
+}
+
+#define EPSILON 1e-6
+
+static double
+trap_epsilon (double v)
+{
+  const double epsilon = EPSILON;
+
+  if (v < epsilon && v > -epsilon) return 0;
+  else return v;
+}
+
+/* Determine the order of line segments z0-z1 and z2-z3.
+   Return +1 if z2-z3 lies entirely to the right of z0-z1,
+   -1 if entirely to the left,
+   or 0 if overlap.
+
+   The case analysis in this function is quite ugly. The fact that it's
+   almost 200 lines long is ridiculous.
+
+   Ok, so here's the plan to cut it down:
+
+   First, do a bounding line comparison on the x coordinates. This is pretty
+   much the common case, and should go quickly. It also takes care of the
+   case where both lines are horizontal.
+
+   Then, do d0 and d1 computation, but only if a23 is nonzero.
+
+   Finally, do d2 and d3 computation, but only if a01 is nonzero.
+
+   Fall through to returning 0 (this will happen when both lines are
+   horizontal and they overlap).
+   */
+static int
+x_order (ArtPoint z0, ArtPoint z1, ArtPoint z2, ArtPoint z3)
+{
+  double a01, b01, c01;
+  double a23, b23, c23;
+  double d0, d1, d2, d3;
+
+  if (z0.y == z1.y)
+    {
+      if (z2.y == z3.y)
+       {
+         double x01min, x01max;
+         double x23min, x23max;
+
+         if (z0.x > z1.x)
+           {
+             x01min = z1.x;
+             x01max = z0.x;
+           }
+         else
+           {
+             x01min = z0.x;
+             x01max = z1.x;
+           }
+
+         if (z2.x > z3.x)
+           {
+             x23min = z3.x;
+             x23max = z2.x;
+           }
+         else
+           {
+             x23min = z2.x;
+             x23max = z3.x;
+           }
+
+         if (x23min >= x01max) return 1;
+         else if (x01min >= x23max) return -1;
+         else return 0;
+       }
+      else
+       {
+         /* z0-z1 is horizontal, z2-z3 isn't */
+         a23 = z2.y - z3.y;
+         b23 = z3.x - z2.x;
+         c23 = -(z2.x * a23 + z2.y * b23);
+
+         if (z3.y < z2.y)
+           {
+             a23 = -a23;
+             b23 = -b23;
+             c23 = -c23;
+           }
+         
+         d0 = trap_epsilon (a23 * z0.x + b23 * z0.y + c23);
+         d1 = trap_epsilon (a23 * z1.x + b23 * z1.y + c23);
+
+         if (d0 > 0)
+           {
+             if (d1 >= 0) return 1;
+             else return 0;
+           }
+         else if (d0 == 0)
+           {
+             if (d1 > 0) return 1;
+             else if (d1 < 0) return -1;
+             else printf ("case 1 degenerate\n");
+             return 0;
+           }
+         else /* d0 < 0 */
+           {
+             if (d1 <= 0) return -1;
+             else return 0;
+           }
+       }
+    }
+  else if (z2.y == z3.y)
+    {
+      /* z2-z3 is horizontal, z0-z1 isn't */
+      a01 = z0.y - z1.y;
+      b01 = z1.x - z0.x;
+      c01 = -(z0.x * a01 + z0.y * b01);
+      /* = -((z0.y - z1.y) * z0.x + (z1.x - z0.x) * z0.y) 
+        = (z1.x * z0.y - z1.y * z0.x) */
+
+      if (z1.y < z0.y)
+       {
+         a01 = -a01;
+         b01 = -b01;
+         c01 = -c01;
+       }
+
+      d2 = trap_epsilon (a01 * z2.x + b01 * z2.y + c01);
+      d3 = trap_epsilon (a01 * z3.x + b01 * z3.y + c01);
+
+      if (d2 > 0)
+       {
+         if (d3 >= 0) return -1;
+         else return 0;
+       }
+      else if (d2 == 0)
+       {
+         if (d3 > 0) return -1;
+         else if (d3 < 0) return 1;
+         else printf ("case 2 degenerate\n");
+         return 0;
+       }
+      else /* d2 < 0 */
+       {
+         if (d3 <= 0) return 1;
+         else return 0;
+       }
+    }
+
+  /* find line equations ax + by + c = 0 */
+  a01 = z0.y - z1.y;
+  b01 = z1.x - z0.x;
+  c01 = -(z0.x * a01 + z0.y * b01);
+  /* = -((z0.y - z1.y) * z0.x + (z1.x - z0.x) * z0.y) 
+     = -(z1.x * z0.y - z1.y * z0.x) */
+
+  if (a01 > 0)
+    {
+      a01 = -a01;
+      b01 = -b01;
+      c01 = -c01;
+    }
+  /* so now, (a01, b01) points to the left, thus a01 * x + b01 * y + c01
+     is negative if the point lies to the right of the line */
+
+  d2 = trap_epsilon (a01 * z2.x + b01 * z2.y + c01);
+  d3 = trap_epsilon (a01 * z3.x + b01 * z3.y + c01);
+  if (d2 > 0)
+    {
+      if (d3 >= 0) return -1;
+    }
+  else if (d2 == 0)
+    {
+      if (d3 > 0) return -1;
+      else if (d3 < 0) return 1;
+      else
+       fprintf (stderr, "colinear!\n");
+    }
+  else /* d2 < 0 */
+    {
+      if (d3 <= 0) return 1;
+    }
+
+  a23 = z2.y - z3.y;
+  b23 = z3.x - z2.x;
+  c23 = -(z2.x * a23 + z2.y * b23);
+
+  if (a23 > 0)
+    {
+      a23 = -a23;
+      b23 = -b23;
+      c23 = -c23;
+    }
+  d0 = trap_epsilon (a23 * z0.x + b23 * z0.y + c23);
+  d1 = trap_epsilon (a23 * z1.x + b23 * z1.y + c23);
+  if (d0 > 0)
+    {
+      if (d1 >= 0) return 1;
+    }
+  else if (d0 == 0)
+    {
+      if (d1 > 0) return 1;
+      else if (d1 < 0) return -1;
+      else
+       fprintf (stderr, "colinear!\n");
+    }
+  else /* d0 < 0 */
+    {
+      if (d1 <= 0) return -1;
+    }
+
+  return 0;
+}
+
+/* similar to x_order, but to determine whether point z0 + epsilon lies to
+   the left of the line z2-z3 or to the right */
+static int
+x_order_2 (ArtPoint z0, ArtPoint z1, ArtPoint z2, ArtPoint z3)
+{
+  double a23, b23, c23;
+  double d0, d1;
+
+  a23 = z2.y - z3.y;
+  b23 = z3.x - z2.x;
+  c23 = -(z2.x * a23 + z2.y * b23);
+
+  if (a23 > 0)
+    {
+      a23 = -a23;
+      b23 = -b23;
+      c23 = -c23;
+    }
+
+  d0 = a23 * z0.x + b23 * z0.y + c23;
+
+  if (d0 > EPSILON)
+    return -1;
+  else if (d0 < -EPSILON)
+    return 1;
+
+  d1 = a23 * z1.x + b23 * z1.y + c23;
+  if (d1 > EPSILON)
+    return -1;
+  else if (d1 < -EPSILON)
+    return 1;
+
+  if (z0.x <= z2.x && z1.x <= z2.x && z0.x <= z3.x && z1.x <= z3.x)
+    return -1;
+  if (z0.x >= z2.x && z1.x >= z2.x && z0.x >= z3.x && z1.x >= z3.x)
+    return 1;
+  
+  fprintf (stderr, "x_order_2: colinear!\n");
+  return 0;
+}
+
+#ifdef DEAD_CODE
+/* Traverse the vector path, keeping it in x-sorted order.
+
+   This routine doesn't actually do anything - it's just here for
+   explanatory purposes. */
+void
+traverse (ArtSVP *vp)
+{
+  int *active_segs;
+  int n_active_segs;
+  int *cursor;
+  int seg_idx;
+  double y;
+  int tmp1, tmp2;
+  int asi;
+  int i, j;
+
+  active_segs = art_new (int, vp->n_segs);
+  cursor = art_new (int, vp->n_segs);
+
+  n_active_segs = 0;
+  seg_idx = 0;
+  y = vp->segs[0].points[0].y;
+  while (seg_idx < vp->n_segs || n_active_segs > 0)
+    {
+      printf ("y = %g\n", y);
+      /* delete segments ending at y from active list */
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         if (vp->segs[asi].n_points - 1 == cursor[asi] &&
+             vp->segs[asi].points[cursor[asi]].y == y)
+           {
+             printf ("deleting %d\n", asi);
+             n_active_segs--;
+             for (j = i; j < n_active_segs; j++)
+               active_segs[j] = active_segs[j + 1];
+             i--;
+           }
+       }
+
+      /* insert new segments into the active list */
+      while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y)
+       {
+         cursor[seg_idx] = 0;
+         printf ("inserting %d\n", seg_idx);
+         for (i = 0; i < n_active_segs; i++)
+           {
+             asi = active_segs[i];
+             if (x_order (vp->segs[asi].points[cursor[asi]],
+                          vp->segs[asi].points[cursor[asi] + 1],
+                          vp->segs[seg_idx].points[0],
+                          vp->segs[seg_idx].points[1]) == -1)
+             break;
+           }
+         tmp1 = seg_idx;
+         for (j = i; j < n_active_segs; j++)
+           {
+             tmp2 = active_segs[j];
+             active_segs[j] = tmp1;
+             tmp1 = tmp2;
+           }
+         active_segs[n_active_segs] = tmp1;
+         n_active_segs++;
+         seg_idx++;
+       }
+
+      /* all active segs cross the y scanline (considering segs to be
+       closed on top and open on bottom) */
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         printf ("%d (%g, %g) - (%g, %g) %s\n", asi,
+                 vp->segs[asi].points[cursor[asi]].x,
+                 vp->segs[asi].points[cursor[asi]].y,
+                 vp->segs[asi].points[cursor[asi] + 1].x,
+                 vp->segs[asi].points[cursor[asi] + 1].y,
+                 vp->segs[asi].dir ? "v" : "^");
+       }
+
+      /* advance y to the next event */
+      if (n_active_segs == 0)
+       {
+         if (seg_idx < vp->n_segs)
+           y = vp->segs[seg_idx].points[0].y;
+         /* else we're done */
+       }
+      else
+       {
+         asi = active_segs[0];
+         y = vp->segs[asi].points[cursor[asi] + 1].y;
+         for (i = 1; i < n_active_segs; i++)
+           {
+             asi = active_segs[i];
+             if (y > vp->segs[asi].points[cursor[asi] + 1].y)
+               y = vp->segs[asi].points[cursor[asi] + 1].y;
+           }
+         if (seg_idx < vp->n_segs && y > vp->segs[seg_idx].points[0].y)
+           y = vp->segs[seg_idx].points[0].y;
+       }
+
+      /* advance cursors to reach new y */
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         while (cursor[asi] < vp->segs[asi].n_points - 1 &&
+                y >= vp->segs[asi].points[cursor[asi] + 1].y)
+           cursor[asi]++;
+       }
+      printf ("\n");
+    }
+  art_free (cursor);
+  art_free (active_segs);
+}
+#endif
+
+/* I believe that the loop will always break with i=1.
+
+   I think I'll want to change this from a simple sorted list to a
+   modified stack. ips[*][0] will get its own data structure, and
+   ips[*] will in general only be allocated if there is an intersection.
+   Finally, the segment can be traced through the initial point
+   (formerly ips[*][0]), backwards through the stack, and finally
+   to cursor + 1.
+
+   This change should cut down on allocation bandwidth, and also
+   eliminate the iteration through n_ipl below.
+
+*/
+static void
+insert_ip (int seg_i, int *n_ips, int *n_ips_max, ArtPoint **ips, ArtPoint ip)
+{
+  int i;
+  ArtPoint tmp1, tmp2;
+  int n_ipl;
+  ArtPoint *ipl;
+
+  n_ipl = n_ips[seg_i]++;
+  if (n_ipl == n_ips_max[seg_i])
+      art_expand (ips[seg_i], ArtPoint, n_ips_max[seg_i]);
+  ipl = ips[seg_i];
+  for (i = 1; i < n_ipl; i++)
+    if (ipl[i].y > ip.y)
+      break;
+  tmp1 = ip;
+  for (; i <= n_ipl; i++)
+    {
+      tmp2 = ipl[i];
+      ipl[i] = tmp1;
+      tmp1 = tmp2;
+    }
+}
+
+/* test active segment (i - 1) against i for intersection, if
+   so, add intersection point to both ips lists. */
+static void
+intersect_neighbors (int i, int *active_segs,
+                    int *n_ips, int *n_ips_max, ArtPoint **ips,
+                    int *cursor, ArtSVP *vp)
+{
+  ArtPoint z0, z1, z2, z3;
+  int asi01, asi23;
+  ArtPoint ip;
+
+  asi01 = active_segs[i - 1];
+
+  z0 = ips[asi01][0];
+  if (n_ips[asi01] == 1)
+    z1 = vp->segs[asi01].points[cursor[asi01] + 1];
+  else
+    z1 = ips[asi01][1];
+
+  asi23 = active_segs[i];
+
+  z2 = ips[asi23][0];
+  if (n_ips[asi23] == 1)
+    z3 = vp->segs[asi23].points[cursor[asi23] + 1];
+  else
+    z3 = ips[asi23][1];
+
+  if (intersect_lines (z0, z1, z2, z3, &ip))
+    {
+#ifdef VERBOSE
+      printf ("new intersection point: (%g, %g)\n", ip.x, ip.y);
+#endif
+      insert_ip (asi01, n_ips, n_ips_max, ips, ip);
+      insert_ip (asi23, n_ips, n_ips_max, ips, ip);
+    }
+}
+
+/* Add a new point to a segment in the svp.
+
+   Here, we also check to make sure that the segments satisfy nocross.
+   However, this is only valuable for debugging, and could possibly be
+   removed.
+*/
+static void
+svp_add_point (ArtSVP *svp, int *n_points_max,
+              ArtPoint p, int *seg_map, int *active_segs, int n_active_segs,
+              int i)
+{
+  int asi, asi_left, asi_right;
+  int n_points, n_points_left, n_points_right;
+  ArtSVPSeg *seg;
+
+  asi = seg_map[active_segs[i]];
+  seg = &svp->segs[asi];
+  n_points = seg->n_points;
+  /* find out whether neighboring segments share a point */
+  if (i > 0)
+    {
+      asi_left = seg_map[active_segs[i - 1]];
+      n_points_left = svp->segs[asi_left].n_points;
+      if (n_points_left > 1 && 
+         PT_EQ (svp->segs[asi_left].points[n_points_left - 2],
+                svp->segs[asi].points[n_points - 1]))
+       {
+         /* ok, new vector shares a top point with segment to the left -
+            now, check that it satisfies ordering invariant */
+         if (x_order (svp->segs[asi_left].points[n_points_left - 2],
+                      svp->segs[asi_left].points[n_points_left - 1],
+                      svp->segs[asi].points[n_points - 1],
+                      p) < 1)
+
+           {
+#ifdef VERBOSE
+             printf ("svp_add_point: cross on left!\n");
+#endif
+           }
+       }
+    }
+
+  if (i + 1 < n_active_segs)
+    {
+      asi_right = seg_map[active_segs[i + 1]];
+      n_points_right = svp->segs[asi_right].n_points;
+      if (n_points_right > 1 && 
+         PT_EQ (svp->segs[asi_right].points[n_points_right - 2],
+                svp->segs[asi].points[n_points - 1]))
+       {
+         /* ok, new vector shares a top point with segment to the right -
+            now, check that it satisfies ordering invariant */
+         if (x_order (svp->segs[asi_right].points[n_points_right - 2],
+                      svp->segs[asi_right].points[n_points_right - 1],
+                      svp->segs[asi].points[n_points - 1],
+                      p) > -1)
+           {
+#ifdef VERBOSE
+             printf ("svp_add_point: cross on right!\n");
+#endif
+           }
+       }
+    }
+  if (n_points_max[asi] == n_points)
+    art_expand (seg->points, ArtPoint, n_points_max[asi]);
+  seg->points[n_points] = p;
+  if (p.x < seg->bbox.x0)
+    seg->bbox.x0 = p.x;
+  else if (p.x > seg->bbox.x1)
+    seg->bbox.x1 = p.x;
+  seg->bbox.y1 = p.y;
+  seg->n_points++;
+}
+
+#if 0
+/* find where the segment (currently at i) is supposed to go, and return
+   the target index - if equal to i, then there is no crossing problem.
+
+   "Where it is supposed to go" is defined as following:
+
+   Delete element i, re-insert at position target (bumping everything
+   target and greater to the right).
+   */
+static int
+find_crossing (int i, int *active_segs, int n_active_segs,
+              int *cursor, ArtPoint **ips, int *n_ips, ArtSVP *vp)
+{
+  int asi, asi_left, asi_right;
+  ArtPoint p0, p1;
+  ArtPoint p0l, p1l;
+  ArtPoint p0r, p1r;
+  int target;
+
+  asi = active_segs[i];
+  p0 = ips[asi][0];
+  if (n_ips[asi] == 1)
+    p1 = vp->segs[asi].points[cursor[asi] + 1];
+  else
+    p1 = ips[asi][1];
+
+  for (target = i; target > 0; target--)
+    {
+      asi_left = active_segs[target - 1];
+      p0l = ips[asi_left][0];
+      if (n_ips[asi_left] == 1)
+       p1l = vp->segs[asi_left].points[cursor[asi_left] + 1];
+      else
+       p1l = ips[asi_left][1];
+      if (!PT_EQ (p0, p0l))
+       break;
+
+#ifdef VERBOSE
+      printf ("point matches on left (%g, %g) - (%g, %g) x (%g, %g) - (%g, %g)!\n",
+             p0l.x, p0l.y, p1l.x, p1l.y, p0.x, p0.y, p1.x, p1.y);
+#endif
+      if (x_order (p0l, p1l, p0, p1) == 1)
+       break;
+
+#ifdef VERBOSE
+      printf ("scanning to the left (i=%d, target=%d)\n", i, target);
+#endif
+    }
+
+  if (target < i) return target;
+
+  for (; target < n_active_segs - 1; target++)
+    {
+      asi_right = active_segs[target + 1];
+      p0r = ips[asi_right][0];
+      if (n_ips[asi_right] == 1)
+       p1r = vp->segs[asi_right].points[cursor[asi_right] + 1];
+      else
+       p1r = ips[asi_right][1];
+      if (!PT_EQ (p0, p0r))
+       break;
+
+#ifdef VERBOSE
+      printf ("point matches on left (%g, %g) - (%g, %g) x (%g, %g) - (%g, %g)!\n",
+             p0.x, p0.y, p1.x, p1.y, p0r.x, p0r.y, p1r.x, p1r.y);
+#endif
+      if (x_order (p0r, p1r, p0, p1) == 1)
+       break;
+
+#ifdef VERBOSE
+      printf ("scanning to the right (i=%d, target=%d)\n", i, target);
+#endif
+    }
+
+  return target;
+}
+#endif
+
+/* This routine handles the case where the segment changes its position
+   in the active segment list. Generally, this will happen when the
+   segment (defined by i and cursor) shares a top point with a neighbor,
+   but breaks the ordering invariant.
+
+   Essentially, this routine sorts the lines [start..end), all of which
+   share a top point. This is implemented as your basic insertion sort.
+
+   This routine takes care of intersecting the appropriate neighbors,
+   as well.
+
+   A first argument of -1 immediately returns, which helps reduce special
+   casing in the main unwind routine.
+*/
+static void
+fix_crossing (int start, int end, int *active_segs, int n_active_segs,
+             int *cursor, ArtPoint **ips, int *n_ips, int *n_ips_max,
+             ArtSVP *vp, int *seg_map,
+             ArtSVP **p_new_vp, int *pn_segs_max,
+             int **pn_points_max)
+{
+  int i, j;
+  int target;
+  int asi, asj;
+  ArtPoint p0i, p1i;
+  ArtPoint p0j, p1j;
+  int swap = 0;
+#ifdef VERBOSE
+  int k;
+#endif
+  ArtPoint *pts;
+
+#ifdef VERBOSE
+  printf ("fix_crossing: [%d..%d)", start, end);
+  for (k = 0; k < n_active_segs; k++)
+    printf (" %d", active_segs[k]);
+  printf ("\n");
+#endif
+
+  if (start == -1)
+    return;
+
+  for (i = start + 1; i < end; i++)
+    {
+
+      asi = active_segs[i];
+      if (cursor[asi] < vp->segs[asi].n_points - 1) {
+       p0i = ips[asi][0];
+       if (n_ips[asi] == 1)
+         p1i = vp->segs[asi].points[cursor[asi] + 1];
+       else
+         p1i = ips[asi][1];
+
+       for (j = i - 1; j >= start; j--)
+         {
+           asj = active_segs[j];
+           if (cursor[asj] < vp->segs[asj].n_points - 1)
+             {
+               p0j = ips[asj][0];
+               if (n_ips[asj] == 1)
+                 p1j = vp->segs[asj].points[cursor[asj] + 1];
+               else
+                 p1j = ips[asj][1];
+
+               /* we _hope_ p0i = p0j */
+               if (x_order_2 (p0j, p1j, p0i, p1i) == -1)
+                 break;
+             }
+         }
+
+       target = j + 1;
+       /* target is where active_seg[i] _should_ be in active_segs */
+      
+       if (target != i)
+         {
+           swap = 1;
+
+#ifdef VERBOSE
+           printf ("fix_crossing: at %i should be %i\n", i, target);
+#endif
+
+           /* let's close off all relevant segments */
+           for (j = i; j >= target; j--)
+             {
+               asi = active_segs[j];
+               /* First conjunct: this isn't the last point in the original
+                  segment.
+
+                  Second conjunct: this isn't the first point in the new
+                  segment (i.e. already broken).
+               */
+               if (cursor[asi] < vp->segs[asi].n_points - 1 &&
+                   (*p_new_vp)->segs[seg_map[asi]].n_points != 1)
+                 {
+                   int seg_num;
+                   /* so break here */
+#ifdef VERBOSE
+                   printf ("closing off %d\n", j);
+#endif
+
+                   pts = art_new (ArtPoint, 16);
+                   pts[0] = ips[asi][0];
+                   seg_num = art_svp_add_segment (p_new_vp, pn_segs_max,
+                                                  pn_points_max,
+                                                  1, vp->segs[asi].dir,
+                                                  pts,
+                                                  NULL);
+                   (*pn_points_max)[seg_num] = 16;
+                   seg_map[asi] = seg_num;
+                 }
+             }
+
+           /* now fix the ordering in active_segs */
+           asi = active_segs[i];
+           for (j = i; j > target; j--)
+             active_segs[j] = active_segs[j - 1];
+           active_segs[j] = asi;
+         }
+      }
+    }
+  if (swap && start > 0)
+    {
+      int as_start;
+
+      as_start = active_segs[start];
+      if (cursor[as_start] < vp->segs[as_start].n_points)
+       {
+#ifdef VERBOSE
+         printf ("checking intersection of %d, %d\n", start - 1, start);
+#endif
+         intersect_neighbors (start, active_segs,
+                              n_ips, n_ips_max, ips,
+                              cursor, vp);
+       }
+    }
+
+  if (swap && end < n_active_segs)
+    {
+      int as_end;
+
+      as_end = active_segs[end - 1];
+      if (cursor[as_end] < vp->segs[as_end].n_points)
+       {
+#ifdef VERBOSE
+         printf ("checking intersection of %d, %d\n", end - 1, end);
+#endif
+         intersect_neighbors (end, active_segs,
+                              n_ips, n_ips_max, ips,
+                              cursor, vp);
+       }
+    }
+  if (swap)
+    {
+#ifdef VERBOSE
+      printf ("fix_crossing return: [%d..%d)", start, end);
+      for (k = 0; k < n_active_segs; k++)
+       printf (" %d", active_segs[k]);
+      printf ("\n");
+#endif
+    }
+}
+
+/* Return a new sorted vector that covers the same area as the
+   argument, but which satisfies the nocross invariant.
+
+   Basically, this routine works by finding the intersection points,
+   and cutting the segments at those points.
+
+   Status of this routine:
+
+   Basic correctness: Seems ok.
+
+   Numerical stability: known problems in the case of points falling
+   on lines, and colinear lines. For actual use, randomly perturbing
+   the vertices is currently recommended.
+
+   Speed: pretty good, although a more efficient priority queue, as
+   well as bbox culling of potential intersections, are two
+   optimizations that could help.
+
+   Precision: pretty good, although the numerical stability problems
+   make this routine unsuitable for precise calculations of
+   differences.
+
+*/
+
+/* Here is a more detailed description of the algorithm. It follows
+   roughly the structure of traverse (above), but is obviously quite
+   a bit more complex.
+
+   Here are a few important data structures:
+
+   A new sorted vector path (new_svp).
+
+   For each (active) segment in the original, a list of intersection
+   points.
+
+   Of course, the original being traversed.
+
+   The following invariants hold (in addition to the invariants
+   of the traverse procedure).
+
+   The new sorted vector path lies entirely above the y scan line.
+
+   The new sorted vector path keeps the nocross invariant.
+
+   For each active segment, the y scan line crosses the line from the
+   first to the second of the intersection points (where the second
+   point is cursor + 1 if there is only one intersection point).
+
+   The list of intersection points + the (cursor + 1) point is kept
+   in nondecreasing y order.
+
+   Of the active segments, none of the lines from first to second
+   intersection point cross the 1st ip..2nd ip line of the left or
+   right neighbor. (However, such a line may cross further
+   intersection points of the neighbors, or segments past the
+   immediate neighbors).
+
+   Of the active segments, all lines from 1st ip..2nd ip are in
+   strictly increasing x_order (this is very similar to the invariant
+   of the traverse procedure, but is explicitly stated here in terms
+   of ips). (this basically says that nocross holds on the active
+   segments)
+
+   The combination of the new sorted vector path, the path through all
+   the intersection points to cursor + 1, and [cursor + 1, n_points)
+   covers the same area as the argument.
+
+   Another important data structure is mapping from original segment
+   number to new segment number.
+
+   The algorithm is perhaps best understood as advancing the cursors
+   while maintaining these invariants. Here's roughly how it's done.
+
+   When deleting segments from the active list, those segments are added
+   to the new sorted vector path. In addition, the neighbors may intersect
+   each other, so they are intersection tested (see below).
+
+   When inserting new segments, they are intersection tested against
+   their neighbors. The top point of the segment becomes the first
+   intersection point.
+
+   Advancing the cursor is just a bit different from the traverse
+   routine, as the cursor may advance through the intersection points
+   as well. Only when there is a single intersection point in the list
+   does the cursor advance in the original segment. In either case,
+   the new vector is intersection tested against both neighbors. It
+   also causes the vector over which the cursor is advancing to be
+   added to the new svp.
+
+   Two steps need further clarification:
+
+   Intersection testing: the 1st ip..2nd ip lines of the neighbors
+   are tested to see if they cross (using intersect_lines). If so,
+   then the intersection point is added to the ip list of both
+   segments, maintaining the invariant that the list of intersection
+   points is nondecreasing in y).
+
+   Adding vector to new svp: if the new vector shares a top x
+   coordinate with another vector, then it is checked to see whether
+   it is in order. If not, then both segments are "broken," and then
+   restarted. Note: in the case when both segments are in the same
+   order, they may simply be swapped without breaking.
+
+   For the time being, I'm going to put some of these operations into
+   subroutines. If it turns out to be a performance problem, I could
+   try to reorganize the traverse procedure so that each is only
+   called once, and inline them. But if it's not a performance
+   problem, I'll just keep it this way, because it will probably help
+   to make the code clearer, and I believe this code could use all the
+   clarity it can get. */
+/**
+ * art_svp_uncross: Resolve self-intersections of an svp.
+ * @vp: The original svp.
+ *
+ * Finds all the intersections within @vp, and constructs a new svp
+ * with new points added at these intersections.
+ *
+ * This routine needs to be redone from scratch with numerical robustness
+ * in mind. I'm working on it.
+ *
+ * Return value: The new svp.
+ **/
+ArtSVP *
+art_svp_uncross (ArtSVP *vp)
+{
+  int *active_segs;
+  int n_active_segs;
+  int *cursor;
+  int seg_idx;
+  double y;
+  int tmp1, tmp2;
+  int asi;
+  int i, j;
+  /* new data structures */
+  /* intersection points; invariant: *ips[i] is only allocated if
+     i is active */
+  int *n_ips, *n_ips_max;
+  ArtPoint **ips;
+  /* new sorted vector path */
+  int n_segs_max, seg_num;
+  ArtSVP *new_vp;
+  int *n_points_max;
+  /* mapping from argument to new segment numbers - again, only valid
+   if active */
+  int *seg_map;
+  double y_curs;
+  ArtPoint p_curs;
+  int first_share;
+  double share_x;
+  ArtPoint *pts;
+
+  n_segs_max = 16;
+  new_vp = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
+                               (n_segs_max - 1) * sizeof(ArtSVPSeg));
+  new_vp->n_segs = 0;
+
+  if (vp->n_segs == 0)
+    return new_vp;
+
+  active_segs = art_new (int, vp->n_segs);
+  cursor = art_new (int, vp->n_segs);
+
+  seg_map = art_new (int, vp->n_segs);
+  n_ips = art_new (int, vp->n_segs);
+  n_ips_max = art_new (int, vp->n_segs);
+  ips = art_new (ArtPoint *, vp->n_segs);
+
+  n_points_max = art_new (int, n_segs_max);
+
+  n_active_segs = 0;
+  seg_idx = 0;
+  y = vp->segs[0].points[0].y;
+  while (seg_idx < vp->n_segs || n_active_segs > 0)
+    {
+#ifdef VERBOSE
+      printf ("y = %g\n", y);
+#endif
+
+      /* maybe move deletions to end of loop (to avoid so much special
+        casing on the end of a segment)? */
+
+      /* delete segments ending at y from active list */
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         if (vp->segs[asi].n_points - 1 == cursor[asi] &&
+             vp->segs[asi].points[cursor[asi]].y == y)
+           {
+             do
+               {
+#ifdef VERBOSE
+                 printf ("deleting %d\n", asi);
+#endif
+                 art_free (ips[asi]);
+                 n_active_segs--;
+                 for (j = i; j < n_active_segs; j++)
+                   active_segs[j] = active_segs[j + 1];
+                 if (i < n_active_segs)
+                   asi = active_segs[i];
+                 else
+                   break;
+               }
+             while (vp->segs[asi].n_points - 1 == cursor[asi] &&
+                    vp->segs[asi].points[cursor[asi]].y == y);
+
+             /* test intersection of neighbors */
+             if (i > 0 && i < n_active_segs)
+               intersect_neighbors (i, active_segs,
+                                    n_ips, n_ips_max, ips,
+                                    cursor, vp);
+
+             i--;
+           }         
+       }
+
+      /* insert new segments into the active list */
+      while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y)
+       {
+#ifdef VERBOSE
+         printf ("inserting %d\n", seg_idx);
+#endif
+         cursor[seg_idx] = 0;
+         for (i = 0; i < n_active_segs; i++)
+           {
+             asi = active_segs[i];
+             if (x_order_2 (vp->segs[seg_idx].points[0],
+                            vp->segs[seg_idx].points[1],
+                            vp->segs[asi].points[cursor[asi]],
+                            vp->segs[asi].points[cursor[asi] + 1]) == -1)
+               break;
+           }
+
+         /* Create and initialize the intersection points data structure */
+         n_ips[seg_idx] = 1;
+         n_ips_max[seg_idx] = 2;
+         ips[seg_idx] = art_new (ArtPoint, n_ips_max[seg_idx]);
+         ips[seg_idx][0] = vp->segs[seg_idx].points[0];
+
+         /* Start a new segment in the new vector path */
+         pts = art_new (ArtPoint, 16);
+         pts[0] = vp->segs[seg_idx].points[0];
+         seg_num = art_svp_add_segment (&new_vp, &n_segs_max,
+                                        &n_points_max,
+                                        1, vp->segs[seg_idx].dir,
+                                        pts,
+                                        NULL);
+         n_points_max[seg_num] = 16;
+         seg_map[seg_idx] = seg_num;
+
+         tmp1 = seg_idx;
+         for (j = i; j < n_active_segs; j++)
+           {
+             tmp2 = active_segs[j];
+             active_segs[j] = tmp1;
+             tmp1 = tmp2;
+           }
+         active_segs[n_active_segs] = tmp1;
+         n_active_segs++;
+
+         if (i > 0)
+           intersect_neighbors (i, active_segs,
+                                n_ips, n_ips_max, ips,
+                                cursor, vp);
+
+         if (i + 1 < n_active_segs)
+           intersect_neighbors (i + 1, active_segs,
+                                n_ips, n_ips_max, ips,
+                                cursor, vp);
+
+         seg_idx++;
+       }
+
+      /* all active segs cross the y scanline (considering segs to be
+       closed on top and open on bottom) */
+#ifdef VERBOSE
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         printf ("%d ", asi);
+         for (j = 0; j < n_ips[asi]; j++)
+           printf ("(%g, %g) - ",
+                   ips[asi][j].x,
+                   ips[asi][j].y);
+         printf ("(%g, %g) %s\n",
+                 vp->segs[asi].points[cursor[asi] + 1].x,
+                 vp->segs[asi].points[cursor[asi] + 1].y,
+                 vp->segs[asi].dir ? "v" : "^");
+       }
+#endif
+
+      /* advance y to the next event 
+       Note: this is quadratic. We'd probably get decent constant
+       factor speed improvement by caching the y_curs values. */
+      if (n_active_segs == 0)
+       {
+         if (seg_idx < vp->n_segs)
+           y = vp->segs[seg_idx].points[0].y;
+         /* else we're done */
+       }
+      else
+       {
+         asi = active_segs[0];
+         if (n_ips[asi] == 1)
+           y = vp->segs[asi].points[cursor[asi] + 1].y;
+         else
+           y = ips[asi][1].y;
+         for (i = 1; i < n_active_segs; i++)
+           {
+             asi = active_segs[i];
+             if (n_ips[asi] == 1)
+               y_curs = vp->segs[asi].points[cursor[asi] + 1].y;
+             else
+               y_curs = ips[asi][1].y;
+             if (y > y_curs)
+               y = y_curs;
+           }
+         if (seg_idx < vp->n_segs && y > vp->segs[seg_idx].points[0].y)
+           y = vp->segs[seg_idx].points[0].y;
+       }
+
+      first_share = -1;
+      share_x = 0; /* to avoid gcc warning, although share_x is never
+                     used when first_share is -1 */
+      /* advance cursors to reach new y */
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         if (n_ips[asi] == 1)
+           p_curs = vp->segs[asi].points[cursor[asi] + 1];
+         else
+           p_curs = ips[asi][1];
+         if (p_curs.y == y)
+           {
+             svp_add_point (new_vp, n_points_max,
+                            p_curs, seg_map, active_segs, n_active_segs, i);
+
+             n_ips[asi]--;
+             for (j = 0; j < n_ips[asi]; j++)
+               ips[asi][j] = ips[asi][j + 1];
+
+             if (n_ips[asi] == 0)
+               {
+                 ips[asi][0] = p_curs;
+                 n_ips[asi] = 1;
+                 cursor[asi]++;
+               }
+
+             if (first_share < 0 || p_curs.x != share_x)
+               {
+                 /* this is where crossings are detected, and if
+                    found, the active segments switched around. */
+                     
+                 fix_crossing (first_share, i,
+                               active_segs, n_active_segs,
+                               cursor, ips, n_ips, n_ips_max, vp, seg_map,
+                               &new_vp,
+                               &n_segs_max, &n_points_max);
+
+                 first_share = i;
+                 share_x = p_curs.x;
+               }
+
+             if (cursor[asi] < vp->segs[asi].n_points - 1)
+               {
+
+                 if (i > 0)
+                   intersect_neighbors (i, active_segs,
+                                        n_ips, n_ips_max, ips,
+                                        cursor, vp);
+                 
+                 if (i + 1 < n_active_segs)
+                   intersect_neighbors (i + 1, active_segs,
+                                        n_ips, n_ips_max, ips,
+                                        cursor, vp);
+               }
+           }
+         else
+           {
+             /* not on a cursor point */
+             fix_crossing (first_share, i,
+                           active_segs, n_active_segs,
+                           cursor, ips, n_ips, n_ips_max, vp, seg_map,
+                           &new_vp,
+                           &n_segs_max, &n_points_max);
+             first_share = -1;
+           }
+       }
+
+      /* fix crossing on last shared group */
+      fix_crossing (first_share, i,
+                   active_segs, n_active_segs,
+                   cursor, ips, n_ips, n_ips_max, vp, seg_map,
+                   &new_vp,
+                   &n_segs_max, &n_points_max);
+
+#ifdef VERBOSE
+      printf ("\n");
+#endif
+    }
+
+  /* not necessary to sort, new segments only get added at y, which
+     increases monotonically */
+#if 0
+  qsort (&new_vp->segs, new_vp->n_segs, sizeof (svp_seg), svp_seg_compare);
+  {
+    int k;
+    for (k = 0; k < new_vp->n_segs - 1; k++)
+      {
+       printf ("(%g, %g) - (%g, %g) %s (%g, %g) - (%g, %g)\n",
+               new_vp->segs[k].points[0].x,
+               new_vp->segs[k].points[0].y,
+               new_vp->segs[k].points[1].x,
+               new_vp->segs[k].points[1].y,
+               svp_seg_compare (&new_vp->segs[k], &new_vp->segs[k + 1]) > 1 ? ">": "<",
+               new_vp->segs[k + 1].points[0].x,
+               new_vp->segs[k + 1].points[0].y,
+               new_vp->segs[k + 1].points[1].x,
+               new_vp->segs[k + 1].points[1].y);
+      }
+  }
+#endif
+
+  art_free (n_points_max);
+  art_free (seg_map);
+  art_free (n_ips_max);
+  art_free (n_ips);
+  art_free (ips);
+  art_free (cursor);
+  art_free (active_segs);
+
+  return new_vp;
+}
+
+#define noVERBOSE
+
+/* Rewind a svp satisfying the nocross invariant.
+
+   The winding number of a segment is defined as the winding number of
+   the points to the left while travelling in the direction of the
+   segment. Therefore it preincrements and postdecrements as a scan
+   line is traversed from left to right.
+
+   Status of this routine:
+
+   Basic correctness: Was ok in gfonted. However, this code does not
+   yet compute bboxes for the resulting svp segs.
+
+   Numerical stability: known problems in the case of horizontal
+   segments in polygons with any complexity. For actual use, randomly
+   perturbing the vertices is recommended.
+
+   Speed: good.
+
+   Precision: good, except that no attempt is made to remove "hair".
+   Doing random perturbation just makes matters worse.
+
+*/
+/**
+ * art_svp_rewind_uncrossed: Rewind an svp satisfying the nocross invariant.
+ * @vp: The original svp.
+ * @rule: The winding rule.
+ *
+ * Creates a new svp with winding number of 0 or 1 everywhere. The @rule
+ * argument specifies a rule for how winding numbers in the original
+ * @vp map to the winding numbers in the result.
+ *
+ * With @rule == ART_WIND_RULE_NONZERO, the resulting svp has a
+ * winding number of 1 where @vp has a nonzero winding number.
+ *
+ * With @rule == ART_WIND_RULE_INTERSECT, the resulting svp has a
+ * winding number of 1 where @vp has a winding number greater than
+ * 1. It is useful for computing intersections.
+ *
+ * With @rule == ART_WIND_RULE_ODDEVEN, the resulting svp has a
+ * winding number of 1 where @vp has an odd winding number. It is
+ * useful for implementing the even-odd winding rule of the
+ * PostScript imaging model.
+ *
+ * With @rule == ART_WIND_RULE_POSITIVE, the resulting svp has a
+ * winding number of 1 where @vp has a positive winding number. It is
+ * useful for implementing asymmetric difference.
+ *
+ * This routine needs to be redone from scratch with numerical robustness
+ * in mind. I'm working on it.
+ *
+ * Return value: The new svp.
+ **/
+ArtSVP *
+art_svp_rewind_uncrossed (ArtSVP *vp, ArtWindRule rule)
+{
+  int *active_segs;
+  int n_active_segs;
+  int *cursor;
+  int seg_idx;
+  double y;
+  int tmp1, tmp2;
+  int asi;
+  int i, j;
+
+  ArtSVP *new_vp;
+  int n_segs_max;
+  int *winding;
+  int left_wind;
+  int wind;
+  int keep, invert;
+
+#ifdef VERBOSE
+  print_svp (vp);
+#endif
+  n_segs_max = 16;
+  new_vp = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
+                               (n_segs_max - 1) * sizeof(ArtSVPSeg));
+  new_vp->n_segs = 0;
+
+  if (vp->n_segs == 0)
+    return new_vp;
+
+  winding = art_new (int, vp->n_segs);
+
+  active_segs = art_new (int, vp->n_segs);
+  cursor = art_new (int, vp->n_segs);
+
+  n_active_segs = 0;
+  seg_idx = 0;
+  y = vp->segs[0].points[0].y;
+  while (seg_idx < vp->n_segs || n_active_segs > 0)
+    {
+#ifdef VERBOSE
+      printf ("y = %g\n", y);
+#endif
+      /* delete segments ending at y from active list */
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         if (vp->segs[asi].n_points - 1 == cursor[asi] &&
+             vp->segs[asi].points[cursor[asi]].y == y)
+           {
+#ifdef VERBOSE
+             printf ("deleting %d\n", asi);
+#endif
+             n_active_segs--;
+             for (j = i; j < n_active_segs; j++)
+               active_segs[j] = active_segs[j + 1];
+             i--;
+           }
+       }
+
+      /* insert new segments into the active list */
+      while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y)
+       {
+#ifdef VERBOSE
+         printf ("inserting %d\n", seg_idx);
+#endif
+         cursor[seg_idx] = 0;
+         for (i = 0; i < n_active_segs; i++)
+           {
+             asi = active_segs[i];
+             if (x_order_2 (vp->segs[seg_idx].points[0],
+                            vp->segs[seg_idx].points[1],
+                            vp->segs[asi].points[cursor[asi]],
+                            vp->segs[asi].points[cursor[asi] + 1]) == -1)
+               break;
+           }
+
+         /* Determine winding number for this segment */
+         if (i == 0)
+           left_wind = 0;
+         else if (vp->segs[active_segs[i - 1]].dir)
+           left_wind = winding[active_segs[i - 1]];
+         else
+           left_wind = winding[active_segs[i - 1]] - 1;
+
+         if (vp->segs[seg_idx].dir)
+           wind = left_wind + 1;
+         else
+           wind = left_wind;
+
+         winding[seg_idx] = wind;
+
+         switch (rule)
+           {
+           case ART_WIND_RULE_NONZERO:
+             keep = (wind == 1 || wind == 0);
+             invert = (wind == 0);
+             break;
+           case ART_WIND_RULE_INTERSECT:
+             keep = (wind == 2);
+             invert = 0;
+             break;
+           case ART_WIND_RULE_ODDEVEN:
+             keep = 1;
+             invert = !(wind & 1);
+             break;
+           case ART_WIND_RULE_POSITIVE:
+             keep = (wind == 1);
+             invert = 0;
+             break;
+           default:
+             keep = 0;
+             invert = 0;
+             break;
+           }
+
+         if (keep)
+           {
+             ArtPoint *points, *new_points;
+             int n_points;
+             int new_dir;
+
+#ifdef VERBOSE
+             printf ("keeping segment %d\n", seg_idx);
+#endif
+             n_points = vp->segs[seg_idx].n_points;
+             points = vp->segs[seg_idx].points;
+             new_points = art_new (ArtPoint, n_points);
+             memcpy (new_points, points, n_points * sizeof (ArtPoint));
+             new_dir = vp->segs[seg_idx].dir ^ invert;
+             art_svp_add_segment (&new_vp, &n_segs_max,
+                                  NULL,
+                                  n_points, new_dir, new_points,
+                                  &vp->segs[seg_idx].bbox);
+           }
+
+         tmp1 = seg_idx;
+         for (j = i; j < n_active_segs; j++)
+           {
+             tmp2 = active_segs[j];
+             active_segs[j] = tmp1;
+             tmp1 = tmp2;
+           }
+         active_segs[n_active_segs] = tmp1;
+         n_active_segs++;
+         seg_idx++;
+       }
+
+#ifdef VERBOSE
+      /* all active segs cross the y scanline (considering segs to be
+       closed on top and open on bottom) */
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         printf ("%d:%d (%g, %g) - (%g, %g) %s %d\n", asi,
+                 cursor[asi],
+                 vp->segs[asi].points[cursor[asi]].x,
+                 vp->segs[asi].points[cursor[asi]].y,
+                 vp->segs[asi].points[cursor[asi] + 1].x,
+                 vp->segs[asi].points[cursor[asi] + 1].y,
+                 vp->segs[asi].dir ? "v" : "^",
+                 winding[asi]);
+       }
+#endif
+
+      /* advance y to the next event */
+      if (n_active_segs == 0)
+       {
+         if (seg_idx < vp->n_segs)
+           y = vp->segs[seg_idx].points[0].y;
+         /* else we're done */
+       }
+      else
+       {
+         asi = active_segs[0];
+         y = vp->segs[asi].points[cursor[asi] + 1].y;
+         for (i = 1; i < n_active_segs; i++)
+           {
+             asi = active_segs[i];
+             if (y > vp->segs[asi].points[cursor[asi] + 1].y)
+               y = vp->segs[asi].points[cursor[asi] + 1].y;
+           }
+         if (seg_idx < vp->n_segs && y > vp->segs[seg_idx].points[0].y)
+           y = vp->segs[seg_idx].points[0].y;
+       }
+
+      /* advance cursors to reach new y */
+      for (i = 0; i < n_active_segs; i++)
+       {
+         asi = active_segs[i];
+         while (cursor[asi] < vp->segs[asi].n_points - 1 &&
+                y >= vp->segs[asi].points[cursor[asi] + 1].y)
+           cursor[asi]++;
+       }
+#ifdef VERBOSE
+      printf ("\n");
+#endif
+    }
+  art_free (cursor);
+  art_free (active_segs);
+  art_free (winding);
+
+  return new_vp;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_svp_wind.h b/libraries/libart_lgpl-2.3.7/art_svp_wind.h
new file mode 100644 (file)
index 0000000..4d974c6
--- /dev/null
@@ -0,0 +1,51 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_WIND_H__
+#define __ART_SVP_WIND_H__
+
+/* Primitive intersection and winding number operations on sorted
+   vector paths. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef ART_WIND_RULE_DEFINED
+#define ART_WIND_RULE_DEFINED
+typedef enum {
+  ART_WIND_RULE_NONZERO,
+  ART_WIND_RULE_INTERSECT,
+  ART_WIND_RULE_ODDEVEN,
+  ART_WIND_RULE_POSITIVE
+} ArtWindRule;
+#endif
+
+ArtSVP *
+art_svp_uncross (ArtSVP *vp);
+
+ArtSVP *
+art_svp_rewind_uncrossed (ArtSVP *vp, ArtWindRule rule);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_WIND_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_uta.c b/libraries/libart_lgpl-2.3.7/art_uta.c
new file mode 100644 (file)
index 0000000..f065592
--- /dev/null
@@ -0,0 +1,86 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "art_misc.h"
+#include "art_uta.h"
+
+/**
+ * art_uta_new: Allocate a new uta.
+ * @x0: Left coordinate of uta.
+ * @y0: Top coordinate of uta.
+ * @x1: Right coordinate of uta.
+ * @y1: Bottom coordinate of uta.
+ *
+ * Allocates a new microtile array. The arguments are in units of
+ * tiles, not pixels.
+ *
+ * Returns: the newly allocated #ArtUta.
+ **/
+ArtUta *
+art_uta_new (int x0, int y0, int x1, int y1)
+{
+  ArtUta *uta;
+
+  uta = art_new (ArtUta, 1);
+  uta->x0 = x0;
+  uta->y0 = y0;
+  uta->width = x1 - x0;
+  uta->height = y1 - y0;
+
+  uta->utiles = art_new (ArtUtaBbox, uta->width * uta->height);
+
+  memset (uta->utiles, 0, uta->width * uta->height * sizeof(ArtUtaBbox));
+  return uta;
+  }
+
+/**
+ * art_uta_new_coords: Allocate a new uta, based on pixel coordinates.
+ * @x0: Left coordinate of uta.
+ * @y0: Top coordinate of uta.
+ * @x1: Right coordinate of uta.
+ * @y1: Bottom coordinate of uta.
+ *
+ * Allocates a new microtile array. The arguments are in pixels
+ *
+ * Returns: the newly allocated #ArtUta.
+ **/
+ArtUta *
+art_uta_new_coords (int x0, int y0, int x1, int y1)
+{
+  return art_uta_new (x0 >> ART_UTILE_SHIFT, y0 >> ART_UTILE_SHIFT,
+                     1 + (x1 >> ART_UTILE_SHIFT),
+                     1 + (y1 >> ART_UTILE_SHIFT));
+}
+
+/**
+ * art_uta_free: Free a uta.
+ * @uta: The uta to free.
+ *
+ * Frees the microtile array structure, including the actual microtile
+ * data.
+ **/
+void
+art_uta_free (ArtUta *uta)
+{
+  art_free (uta->utiles);
+  art_free (uta);
+}
+
+/* User to Aardvark! */
diff --git a/libraries/libart_lgpl-2.3.7/art_uta.h b/libraries/libart_lgpl-2.3.7/art_uta.h
new file mode 100644 (file)
index 0000000..075a0d5
--- /dev/null
@@ -0,0 +1,66 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_UTA_H__
+#define __ART_UTA_H__
+
+/* Basic data structures and constructors for microtile arrays */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef art_u32 ArtUtaBbox;
+typedef struct _ArtUta ArtUta;
+
+#define ART_UTA_BBOX_CONS(x0, y0, x1, y1) (((x0) << 24) | ((y0) << 16) | \
+                                      ((x1) << 8) | (y1))
+
+#define ART_UTA_BBOX_X0(ub) ((ub) >> 24)
+#define ART_UTA_BBOX_Y0(ub) (((ub) >> 16) & 0xff)
+#define ART_UTA_BBOX_X1(ub) (((ub) >> 8) & 0xff)
+#define ART_UTA_BBOX_Y1(ub) ((ub) & 0xff)
+
+#define ART_UTILE_SHIFT 5
+#define ART_UTILE_SIZE (1 << ART_UTILE_SHIFT)
+
+/* Coordinates are shifted right by ART_UTILE_SHIFT wrt the real
+   coordinates. */
+struct _ArtUta {
+  int x0;
+  int y0;
+  int width;
+  int height;
+  ArtUtaBbox *utiles;
+};
+
+ArtUta *
+art_uta_new (int x0, int y0, int x1, int y1);
+
+ArtUta *
+art_uta_new_coords (int x0, int y0, int x1, int y1);
+
+void
+art_uta_free (ArtUta *uta);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_UTA_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_uta_ops.c b/libraries/libart_lgpl-2.3.7/art_uta_ops.c
new file mode 100644 (file)
index 0000000..5c3e1ce
--- /dev/null
@@ -0,0 +1,110 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include "art_misc.h"
+#include "art_uta.h"
+#include "art_uta_ops.h"
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+/**
+ * art_uta_union: Compute union of two uta's.
+ * @uta1: One uta.
+ * @uta2: The other uta.
+ *
+ * Computes the union of @uta1 and @uta2. The union is approximate,
+ * but coverage is guaranteed over all pixels included in either of
+ * the arguments, ie more pixels may be covered than the "exact"
+ * union.
+ *
+ * Note: this routine is used in the Gnome Canvas to accumulate the
+ * region that needs to be repainted. However, since it copies over
+ * the entire uta (which might be largish) even when the update may be
+ * small, it can be a performance bottleneck. There are two approaches
+ * to this problem, both of which are probably worthwhile. First, the
+ * generated uta's should always be limited to the visible window,
+ * thus guaranteeing that uta's never become large. Second, there
+ * should be a new, destructive union operation that only touches a
+ * small part of the uta when the update is small.
+ *
+ * Return value: The new union uta.
+ **/
+ArtUta *
+art_uta_union (ArtUta *uta1, ArtUta *uta2)
+{
+  ArtUta *uta;
+  int x0, y0, x1, y1;
+  int x, y;
+  int ix, ix1, ix2;
+  ArtUtaBbox bb, bb1, bb2;
+
+  x0 = MIN(uta1->x0, uta2->x0);
+  y0 = MIN(uta1->y0, uta2->y0);
+  x1 = MAX(uta1->x0 + uta1->width, uta2->x0 + uta2->width);
+  y1 = MAX(uta1->y0 + uta1->height, uta2->y0 + uta2->height);
+  uta = art_uta_new (x0, y0, x1, y1);
+
+  /* could move the first two if/else statements out of the loop */
+  ix = 0;
+  for (y = y0; y < y1; y++)
+    {
+      ix1 = (y - uta1->y0) * uta1->width + x0 - uta1->x0;
+      ix2 = (y - uta2->y0) * uta2->width + x0 - uta2->x0;
+      for (x = x0; x < x1; x++)
+       {
+         if (x < uta1->x0 || y < uta1->y0 ||
+             x >= uta1->x0 + uta1->width || y >= uta1->y0 + uta1->height)
+           bb1 = 0;
+         else
+           bb1 = uta1->utiles[ix1];
+
+         if (x < uta2->x0 || y < uta2->y0 ||
+             x >= uta2->x0 + uta2->width || y >= uta2->y0 + uta2->height)
+           bb2 = 0;
+         else
+           bb2 = uta2->utiles[ix2];
+
+         if (bb1 == 0)
+           bb = bb2;
+         else if (bb2 == 0)
+           bb = bb1;
+         else
+           bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb1),
+                                      ART_UTA_BBOX_X0(bb2)),
+                                  MIN(ART_UTA_BBOX_Y0(bb1),
+                                      ART_UTA_BBOX_Y0(bb2)),
+                                  MAX(ART_UTA_BBOX_X1(bb1),
+                                      ART_UTA_BBOX_X1(bb2)),
+                                  MAX(ART_UTA_BBOX_Y1(bb1),
+                                      ART_UTA_BBOX_Y1(bb2)));
+         uta->utiles[ix] = bb;
+         ix++;
+         ix1++;
+         ix2++;
+       }
+    }
+  return uta;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_uta_ops.h b/libraries/libart_lgpl-2.3.7/art_uta_ops.h
new file mode 100644 (file)
index 0000000..4f175ba
--- /dev/null
@@ -0,0 +1,36 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_UTA_OPS_H__
+#define __ART_UTA_OPS_H__
+
+/* Basic operations on microtile arrays */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtUta *
+art_uta_union (ArtUta *uta1, ArtUta *uta2);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_UTA_OPS_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_uta_rect.c b/libraries/libart_lgpl-2.3.7/art_uta_rect.c
new file mode 100644 (file)
index 0000000..05bc9ad
--- /dev/null
@@ -0,0 +1,109 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "art_misc.h"
+#include "art_uta.h"
+#include "art_rect.h"
+#include "art_uta_rect.h"
+
+/**
+ * art_uta_from_irect: Generate uta covering a rectangle.
+ * @bbox: The source rectangle.
+ *
+ * Generates a uta exactly covering @bbox. Please do not call this
+ * function with a @bbox with zero height or width.
+ *
+ * Return value: the new uta.
+ **/
+ArtUta *
+art_uta_from_irect (ArtIRect *bbox)
+{
+  ArtUta *uta;
+  ArtUtaBbox *utiles;
+  ArtUtaBbox bb;
+  int width, height;
+  int x, y;
+  int xf0, yf0, xf1, yf1;
+  int ix;
+
+  uta = art_new (ArtUta, 1);
+  uta->x0 = bbox->x0 >> ART_UTILE_SHIFT;
+  uta->y0 = bbox->y0 >> ART_UTILE_SHIFT;
+  width = ((bbox->x1 + ART_UTILE_SIZE - 1) >> ART_UTILE_SHIFT) - uta->x0;
+  height = ((bbox->y1 + ART_UTILE_SIZE - 1) >> ART_UTILE_SHIFT) - uta->y0;
+  utiles = art_new (ArtUtaBbox, width * height);
+
+  uta->width = width;
+  uta->height = height;
+  uta->utiles = utiles;
+
+  xf0 = bbox->x0 & (ART_UTILE_SIZE - 1);
+  yf0 = bbox->y0 & (ART_UTILE_SIZE - 1);
+  xf1 = ((bbox->x1 - 1) & (ART_UTILE_SIZE - 1)) + 1;
+  yf1 = ((bbox->y1 - 1) & (ART_UTILE_SIZE - 1)) + 1;
+  if (height == 1)
+    {
+      if (width == 1)
+       utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, xf1, yf1);
+      else
+       {
+         utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, ART_UTILE_SIZE, yf1);
+         bb = ART_UTA_BBOX_CONS (0, yf0, ART_UTILE_SIZE, yf1);
+         for (x = 1; x < width - 1; x++)
+           utiles[x] = bb;
+         utiles[x] = ART_UTA_BBOX_CONS (0, yf0, xf1, yf1);
+       }
+    }
+  else
+    {
+      if (width == 1)
+       {
+         utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, xf1, ART_UTILE_SIZE);
+         bb = ART_UTA_BBOX_CONS (xf0, 0, xf1, ART_UTILE_SIZE);
+         for (y = 1; y < height - 1; y++)
+           utiles[y] = bb;
+         utiles[y] = ART_UTA_BBOX_CONS (xf0, 0, xf1, yf1);
+       }
+      else
+       {
+         utiles[0] =
+           ART_UTA_BBOX_CONS (xf0, yf0, ART_UTILE_SIZE, ART_UTILE_SIZE);
+         bb = ART_UTA_BBOX_CONS (0, yf0, ART_UTILE_SIZE, ART_UTILE_SIZE);
+         for (x = 1; x < width - 1; x++)
+           utiles[x] = bb;
+         utiles[x] = ART_UTA_BBOX_CONS (0, yf0, xf1, ART_UTILE_SIZE);
+         ix = width;
+         for (y = 1; y < height - 1; y++)
+           {
+             utiles[ix++] =
+               ART_UTA_BBOX_CONS (xf0, 0, ART_UTILE_SIZE, ART_UTILE_SIZE);
+             bb = ART_UTA_BBOX_CONS (0, 0, ART_UTILE_SIZE, ART_UTILE_SIZE);
+             for (x = 1; x < width - 1; x++)
+               utiles[ix++] = bb;
+             utiles[ix++] = ART_UTA_BBOX_CONS (0, 0, xf1, ART_UTILE_SIZE);
+           }
+         utiles[ix++] = ART_UTA_BBOX_CONS (xf0, 0, ART_UTILE_SIZE, yf1);
+         bb = ART_UTA_BBOX_CONS (0, 0, ART_UTILE_SIZE, yf1);
+         for (x = 1; x < width - 1; x++)
+           utiles[ix++] = bb;
+         utiles[ix++] = ART_UTA_BBOX_CONS (0, 0, xf1, yf1);
+       }
+    }
+  return uta;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_uta_rect.h b/libraries/libart_lgpl-2.3.7/art_uta_rect.h
new file mode 100644 (file)
index 0000000..ff8ed3b
--- /dev/null
@@ -0,0 +1,34 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_UTA_RECT_H__
+#define __ART_UTA_RECT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtUta *
+art_uta_from_irect (ArtIRect *bbox);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_UTA_RECT_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_uta_svp.c b/libraries/libart_lgpl-2.3.7/art_uta_svp.c
new file mode 100644 (file)
index 0000000..fc86eb9
--- /dev/null
@@ -0,0 +1,52 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* LGPL Copyright 1998 Raph Levien <raph@acm.org> */
+
+#include "art_misc.h"
+#include "art_vpath.h"
+#include "art_uta.h"
+#include "art_uta_vpath.h"
+#include "art_svp.h"
+#include "art_uta_svp.h"
+#include "art_vpath_svp.h"
+
+/**
+ * art_uta_from_svp: Generate uta covering an svp.
+ * @svp: The source svp.
+ *
+ * Generates a uta covering @svp. The resulting uta is of course
+ * approximate, ie it may cover more pixels than covered by @svp.
+ *
+ * Note: I will want to replace this with a more direct
+ * implementation. But this gets the api in place.
+ *
+ * Return value: the new uta.
+ **/
+ArtUta *
+art_uta_from_svp (const ArtSVP *svp)
+{
+  ArtVpath *vpath;
+  ArtUta *uta;
+
+  vpath = art_vpath_from_svp (svp);
+  uta = art_uta_from_vpath (vpath);
+  art_free (vpath);
+  return uta;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_uta_svp.h b/libraries/libart_lgpl-2.3.7/art_uta_svp.h
new file mode 100644 (file)
index 0000000..5333080
--- /dev/null
@@ -0,0 +1,37 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_UTA_SVP_H__
+#define __ART_UTA_SVP_H__
+
+/* Basic data structures and constructors for microtile arrays */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtUta *
+art_uta_from_svp (const ArtSVP *svp);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_UTA_SVP_H__ */
+
diff --git a/libraries/libart_lgpl-2.3.7/art_uta_vpath.c b/libraries/libart_lgpl-2.3.7/art_uta_vpath.c
new file mode 100644 (file)
index 0000000..4acbac1
--- /dev/null
@@ -0,0 +1,375 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* LGPL Copyright 1998 Raph Levien <raph@acm.org> */
+
+#include <math.h>
+
+#include "art_misc.h"
+#include "art_vpath.h"
+#include "art_uta.h"
+#include "art_uta_vpath.h"
+
+#ifndef MAX
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+#ifndef MIN
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+/**
+ * art_uta_add_line: Add a line to the uta.
+ * @uta: The uta to modify.
+ * @x0: X coordinate of line start point.
+ * @y0: Y coordinate of line start point.
+ * @x1: X coordinate of line end point.
+ * @y1: Y coordinate of line end point.
+ * @rbuf: Buffer containing first difference of winding number.
+ * @rbuf_rowstride: Rowstride of @rbuf.
+ *
+ * Add the line (@x0, @y0) - (@x1, @y1) to @uta, and also update the
+ * winding number buffer used for rendering the interior. @rbuf
+ * contains the first partial difference (in the X direction) of the
+ * winding number, measured in grid cells. Thus, each time that a line
+ * crosses a horizontal uta grid line, an entry of @rbuf is
+ * incremented if @y1 > @y0, decremented otherwise.
+ *
+ * Note that edge handling is fairly delicate. Please rtfs for
+ * details.
+ **/
+void
+art_uta_add_line (ArtUta *uta, double x0, double y0, double x1, double y1,
+                 int *rbuf, int rbuf_rowstride)
+{
+  int xmin, ymin;
+  double xmax, ymax;
+  int xmaxf, ymaxf;
+  int xmaxc, ymaxc;
+  int xt0, yt0;
+  int xt1, yt1;
+  int xf0, yf0;
+  int xf1, yf1;
+  int ix, ix1;
+  ArtUtaBbox bb;
+
+  xmin = floor (MIN(x0, x1));
+  xmax = MAX(x0, x1);
+  xmaxf = floor (xmax);
+  xmaxc = ceil (xmax);
+  ymin = floor (MIN(y0, y1));
+  ymax = MAX(y0, y1);
+  ymaxf = floor (ymax);
+  ymaxc = ceil (ymax);
+  xt0 = (xmin >> ART_UTILE_SHIFT) - uta->x0;
+  yt0 = (ymin >> ART_UTILE_SHIFT) - uta->y0;
+  xt1 = (xmaxf >> ART_UTILE_SHIFT) - uta->x0;
+  yt1 = (ymaxf >> ART_UTILE_SHIFT) - uta->y0;
+  if (xt0 == xt1 && yt0 == yt1)
+    {
+      /* entirely inside a microtile, this is easy! */
+      xf0 = xmin & (ART_UTILE_SIZE - 1);
+      yf0 = ymin & (ART_UTILE_SIZE - 1);
+      xf1 = (xmaxf & (ART_UTILE_SIZE - 1)) + xmaxc - xmaxf;
+      yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
+
+      ix = yt0 * uta->width + xt0;
+      bb = uta->utiles[ix];
+      if (bb == 0)
+       bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
+      else
+       bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
+                          MIN(ART_UTA_BBOX_Y0(bb), yf0),
+                          MAX(ART_UTA_BBOX_X1(bb), xf1),
+                          MAX(ART_UTA_BBOX_Y1(bb), yf1));
+      uta->utiles[ix] = bb;
+    }
+  else
+    {
+      double dx, dy;
+      int sx, sy;
+
+      dx = x1 - x0;
+      dy = y1 - y0;
+      sx = dx > 0 ? 1 : dx < 0 ? -1 : 0;
+      sy = dy > 0 ? 1 : dy < 0 ? -1 : 0;
+      if (ymin == ymaxf)
+       {
+         /* special case horizontal (dx/dy slope would be infinite) */
+         xf0 = xmin & (ART_UTILE_SIZE - 1);
+         yf0 = ymin & (ART_UTILE_SIZE - 1);
+         xf1 = (xmaxf & (ART_UTILE_SIZE - 1)) + xmaxc - xmaxf;
+         yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
+
+         ix = yt0 * uta->width + xt0;
+         ix1 = yt0 * uta->width + xt1;
+         while (ix != ix1)
+           {
+             bb = uta->utiles[ix];
+             if (bb == 0)
+               bb = ART_UTA_BBOX_CONS(xf0, yf0, ART_UTILE_SIZE, yf1);
+             else
+               bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
+                                  MIN(ART_UTA_BBOX_Y0(bb), yf0),
+                                  ART_UTILE_SIZE,
+                                  MAX(ART_UTA_BBOX_Y1(bb), yf1));
+             uta->utiles[ix] = bb;
+             xf0 = 0;
+             ix++;
+           }
+         bb = uta->utiles[ix];
+         if (bb == 0)
+           bb = ART_UTA_BBOX_CONS(0, yf0, xf1, yf1);
+         else
+           bb = ART_UTA_BBOX_CONS(0,
+                              MIN(ART_UTA_BBOX_Y0(bb), yf0),
+                              MAX(ART_UTA_BBOX_X1(bb), xf1),
+                              MAX(ART_UTA_BBOX_Y1(bb), yf1));
+         uta->utiles[ix] = bb;
+       }
+      else
+       {
+         /* Do a Bresenham-style traversal of the line */
+         double dx_dy;
+         double x, y;
+         double xn, yn;
+
+         /* normalize coordinates to uta origin */
+         x0 -= uta->x0 << ART_UTILE_SHIFT;
+         y0 -= uta->y0 << ART_UTILE_SHIFT;
+         x1 -= uta->x0 << ART_UTILE_SHIFT;
+         y1 -= uta->y0 << ART_UTILE_SHIFT;
+         if (dy < 0)
+           {
+             double tmp;
+
+             tmp = x0;
+             x0 = x1;
+             x1 = tmp;
+
+             tmp = y0;
+             y0 = y1;
+             y1 = tmp;
+
+             dx = -dx;
+             sx = -sx;
+             dy = -dy;
+             /* we leave sy alone, because it would always be 1,
+                and we need it for the rbuf stuff. */
+           }
+         xt0 = ((int)floor (x0) >> ART_UTILE_SHIFT);
+         xt1 = ((int)floor (x1) >> ART_UTILE_SHIFT);
+         /* now [xy]0 is above [xy]1 */
+
+         ix = yt0 * uta->width + xt0;
+         ix1 = yt1 * uta->width + xt1;
+#ifdef VERBOSE
+         printf ("%% ix = %d,%d; ix1 = %d,%d\n", xt0, yt0, xt1, yt1);
+#endif
+
+         dx_dy = dx / dy;
+         x = x0;
+         y = y0;
+         while (ix != ix1)
+           {
+             int dix;
+
+             /* figure out whether next crossing is horizontal or vertical */
+#ifdef VERBOSE
+             printf ("%% %d,%d\n", xt0, yt0);
+#endif
+             yn = (yt0 + 1) << ART_UTILE_SHIFT;
+             xn = x0 + dx_dy * (yn - y0);
+             if (xt0 != (int)floor (xn) >> ART_UTILE_SHIFT)
+               {
+                 /* horizontal crossing */
+                 xt0 += sx;
+                 dix = sx;
+                 if (dx > 0)
+                   {
+                     xn = xt0 << ART_UTILE_SHIFT;
+                     yn = y0 + (xn - x0) / dx_dy;
+
+                     xf0 = (int)floor (x) & (ART_UTILE_SIZE - 1);
+                     xf1 = ART_UTILE_SIZE;
+                   }
+                 else
+                   {
+                     xn = (xt0 + 1) << ART_UTILE_SHIFT;
+                     yn = y0 + (xn - x0) / dx_dy;
+
+                     xf0 = 0;
+                     xmaxc = (int)ceil (x);
+                     xf1 = xmaxc - ((xt0 + 1) << ART_UTILE_SHIFT);
+                   }
+                 ymaxf = (int)floor (yn);
+                 ymaxc = (int)ceil (yn);
+                 yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
+               }
+             else
+               {
+                 /* vertical crossing */
+                 dix = uta->width;
+                 xf0 = (int)floor (MIN(x, xn)) & (ART_UTILE_SIZE - 1);
+                 xmax = MAX(x, xn);
+                 xmaxc = (int)ceil (xmax);
+                 xf1 = xmaxc - (xt0 << ART_UTILE_SHIFT);
+                 yf1 = ART_UTILE_SIZE;
+
+                 if (rbuf != NULL)
+                   rbuf[yt0 * rbuf_rowstride + xt0] += sy;
+
+                 yt0++;
+               }
+             yf0 = (int)floor (y) & (ART_UTILE_SIZE - 1);
+             bb = uta->utiles[ix];
+             if (bb == 0)
+               bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
+             else
+               bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
+                                      MIN(ART_UTA_BBOX_Y0(bb), yf0),
+                                      MAX(ART_UTA_BBOX_X1(bb), xf1),
+                                      MAX(ART_UTA_BBOX_Y1(bb), yf1));
+             uta->utiles[ix] = bb;
+
+             x = xn;
+             y = yn;
+             ix += dix;
+           }
+         xmax = MAX(x, x1);
+         xmaxc = ceil (xmax);
+         ymaxc = ceil (y1);
+         xf0 = (int)floor (MIN(x1, x)) & (ART_UTILE_SIZE - 1);
+         yf0 = (int)floor (y) & (ART_UTILE_SIZE - 1);
+         xf1 = xmaxc - (xt0 << ART_UTILE_SHIFT);
+         yf1 = ymaxc - (yt0 << ART_UTILE_SHIFT);
+         bb = uta->utiles[ix];
+         if (bb == 0)
+           bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
+         else
+           bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
+                                  MIN(ART_UTA_BBOX_Y0(bb), yf0),
+                                  MAX(ART_UTA_BBOX_X1(bb), xf1),
+                                  MAX(ART_UTA_BBOX_Y1(bb), yf1));
+         uta->utiles[ix] = bb;
+       }
+    }
+}
+
+/**
+ * art_uta_from_vpath: Generate uta covering a vpath.
+ * @vec: The source vpath.
+ *
+ * Generates a uta covering @vec. The resulting uta is of course
+ * approximate, ie it may cover more pixels than covered by @vec.
+ *
+ * Return value: the new uta.
+ **/
+ArtUta *
+art_uta_from_vpath (const ArtVpath *vec)
+{
+  ArtUta *uta;
+  ArtIRect bbox;
+  int *rbuf;
+  int i;
+  double x, y;
+  int sum;
+  int xt, yt;
+  ArtUtaBbox *utiles;
+  ArtUtaBbox bb;
+  int width;
+  int height;
+  int ix;
+
+  art_vpath_bbox_irect (vec, &bbox);
+
+  uta = art_uta_new_coords (bbox.x0, bbox.y0, bbox.x1, bbox.y1);
+
+  width = uta->width;
+  height = uta->height;
+  utiles = uta->utiles;
+
+  rbuf = art_new (int, width * height);
+  for (i = 0; i < width * height; i++)
+    rbuf[i] = 0;
+
+  x = 0;
+  y = 0;
+  for (i = 0; vec[i].code != ART_END; i++)
+    {
+      switch (vec[i].code)
+       {
+       case ART_MOVETO:
+         x = vec[i].x;
+         y = vec[i].y;
+         break;
+       case ART_LINETO:
+         art_uta_add_line (uta, vec[i].x, vec[i].y, x, y, rbuf, width);
+         x = vec[i].x;
+         y = vec[i].y;
+         break;
+       default:
+         /* this shouldn't happen */
+         break;
+       }
+    }
+
+  /* now add in the filling from rbuf */
+  ix = 0;
+  for (yt = 0; yt < height; yt++)
+    {
+      sum = 0;
+      for (xt = 0; xt < width; xt++)
+       {
+         sum += rbuf[ix];
+         /* Nonzero winding rule - others are possible, but hardly
+            worth it. */
+         if (sum != 0)
+           {
+             bb = utiles[ix];
+             bb &= 0xffff0000;
+             bb |= (ART_UTILE_SIZE << 8) | ART_UTILE_SIZE;
+             utiles[ix] = bb;
+             if (xt != width - 1)
+               {
+                 bb = utiles[ix + 1];
+                 bb &= 0xffff00;
+                 bb |= ART_UTILE_SIZE;
+                 utiles[ix + 1] = bb;
+               }
+             if (yt != height - 1)
+               {
+                 bb = utiles[ix + width];
+                 bb &= 0xff0000ff;
+                 bb |= ART_UTILE_SIZE << 8;
+                 utiles[ix + width] = bb;
+                 if (xt != width - 1)
+                   {
+                     utiles[ix + width + 1] &= 0xffff;
+                   }
+               }
+           }
+         ix++;
+       }
+    }
+
+  art_free (rbuf);
+
+  return uta;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_uta_vpath.h b/libraries/libart_lgpl-2.3.7/art_uta_vpath.h
new file mode 100644 (file)
index 0000000..5ebe92a
--- /dev/null
@@ -0,0 +1,42 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_UTA_VPATH_H__
+#define __ART_UTA_VPATH_H__
+
+/* Basic data structures and constructors for microtile arrays */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtUta *
+art_uta_from_vpath (const ArtVpath *vec);
+
+/* This is a private function: */
+void
+art_uta_add_line (ArtUta *uta, double x0, double y0, double x1, double y1,
+                 int *rbuf, int rbuf_rowstride);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_UTA_VPATH_H__ */
+
diff --git a/libraries/libart_lgpl-2.3.7/art_vpath.c b/libraries/libart_lgpl-2.3.7/art_vpath.c
new file mode 100644 (file)
index 0000000..6cb7ed9
--- /dev/null
@@ -0,0 +1,239 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Basic constructors and operations for vector paths */
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "art_misc.h"
+
+#include "art_rect.h"
+#include "art_vpath.h"
+
+/**
+ * art_vpath_add_point: Add point to vpath.
+ * @p_vpath: Where the pointer to the #ArtVpath structure is stored.
+ * @pn_points: Pointer to the number of points in *@p_vpath.
+ * @pn_points_max: Pointer to the number of points allocated.
+ * @code: The pathcode for the new point.
+ * @x: The X coordinate of the new point.
+ * @y: The Y coordinate of the new point.
+ *
+ * Adds a new point to *@p_vpath, reallocating and updating *@p_vpath
+ * and *@pn_points_max as necessary. *@pn_points is incremented.
+ *
+ * This routine always adds the point after all points already in the
+ * vpath. Thus, it should be called in the order the points are
+ * desired.
+ **/
+void
+art_vpath_add_point (ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
+                    ArtPathcode code, double x, double y)
+{
+  int i;
+
+  i = (*pn_points)++;
+  if (i == *pn_points_max)
+    art_expand (*p_vpath, ArtVpath, *pn_points_max);
+  (*p_vpath)[i].code = code;
+  (*p_vpath)[i].x = x;
+  (*p_vpath)[i].y = y;
+}
+
+/* number of steps should really depend on radius. */
+#define CIRCLE_STEPS 128
+
+/**
+ * art_vpath_new_circle: Create a new circle.
+ * @x: X coordinate of center.
+ * @y: Y coordinate of center.
+ * @r: radius.
+ *
+ * Creates a new polygon closely approximating a circle with center
+ * (@x, @y) and radius @r. Currently, the number of points used in the
+ * approximation is fixed, but that will probably change.
+ *
+ * Return value: The newly created #ArtVpath.
+ **/
+ArtVpath *
+art_vpath_new_circle (double x, double y, double r)
+{
+  int i;
+  ArtVpath *vec;
+  double theta;
+
+  vec = art_new (ArtVpath, CIRCLE_STEPS + 2);
+
+  for (i = 0; i < CIRCLE_STEPS + 1; i++)
+    {
+      vec[i].code = i ? ART_LINETO : ART_MOVETO;
+      theta = (i & (CIRCLE_STEPS - 1)) * (M_PI * 2.0 / CIRCLE_STEPS);
+      vec[i].x = x + r * cos (theta);
+      vec[i].y = y - r * sin (theta);
+    }
+  vec[i].code = ART_END;
+
+  return vec;
+}
+
+/**
+ * art_vpath_affine_transform: Affine transform a vpath.
+ * @src: Source vpath to transform.
+ * @matrix: Affine transform.
+ *
+ * Computes the affine transform of the vpath, using @matrix as the
+ * transform. @matrix is stored in the same format as PostScript, ie.
+ * x' = @matrix[0] * x + @matrix[2] * y + @matrix[4]
+ * y' = @matrix[1] * x + @matrix[3] * y + @matrix[5]
+ *
+ * Return value: the newly allocated vpath resulting from the transform.
+**/
+ArtVpath *
+art_vpath_affine_transform (const ArtVpath *src, const double matrix[6])
+{
+  int i;
+  int size;
+  ArtVpath *new;
+  double x, y;
+
+  for (i = 0; src[i].code != ART_END; i++);
+  size = i;
+
+  new = art_new (ArtVpath, size + 1);
+
+  for (i = 0; i < size; i++)
+    {
+      new[i].code = src[i].code;
+      x = src[i].x;
+      y = src[i].y;
+      new[i].x = matrix[0] * x + matrix[2] * y + matrix[4];
+      new[i].y = matrix[1] * x + matrix[3] * y + matrix[5];
+    }
+  new[i].code = ART_END;
+
+  return new;
+}
+
+/**
+ * art_vpath_bbox_drect: Determine bounding box of vpath.
+ * @vec: Source vpath.
+ * @drect: Where to store bounding box.
+ *
+ * Determines bounding box of @vec, and stores it in @drect.
+ **/
+void
+art_vpath_bbox_drect (const ArtVpath *vec, ArtDRect *drect)
+{
+  int i;
+  double x0, y0, x1, y1;
+
+  if (vec[0].code == ART_END)
+    {
+      x0 = y0 = x1 = y1 = 0;
+    }
+  else
+    {
+      x0 = x1 = vec[0].x;
+      y0 = y1 = vec[0].y;
+      for (i = 1; vec[i].code != ART_END; i++)
+       {
+         if (vec[i].x < x0) x0 = vec[i].x;
+         if (vec[i].x > x1) x1 = vec[i].x;
+         if (vec[i].y < y0) y0 = vec[i].y;
+         if (vec[i].y > y1) y1 = vec[i].y;
+       }
+    }
+  drect->x0 = x0;
+  drect->y0 = y0;
+  drect->x1 = x1;
+  drect->y1 = y1;
+}
+
+/**
+ * art_vpath_bbox_irect: Determine integer bounding box of vpath.
+ * @vec: Source vpath.
+ * idrect: Where to store bounding box.
+ *
+ * Determines integer bounding box of @vec, and stores it in @irect.
+ **/
+void
+art_vpath_bbox_irect (const ArtVpath *vec, ArtIRect *irect)
+{
+  ArtDRect drect;
+
+  art_vpath_bbox_drect (vec, &drect);
+  art_drect_to_irect (irect, &drect);
+}
+
+#define PERTURBATION 2e-3
+
+/**
+ * art_vpath_perturb: Perturb each point in vpath by small random amount.
+ * @src: Source vpath.
+ *
+ * Perturbs each of the points by a small random amount. This is
+ * helpful for cheating in cases when algorithms haven't attained
+ * numerical stability yet.
+ *
+ * Return value: Newly allocated vpath containing perturbed @src.
+ **/ 
+ArtVpath *
+art_vpath_perturb (ArtVpath *src)
+{
+  int i;
+  int size;
+  ArtVpath *new;
+  double x, y;
+  double x_start, y_start;
+  int open;
+
+  for (i = 0; src[i].code != ART_END; i++);
+  size = i;
+
+  new = art_new (ArtVpath, size + 1);
+
+  x_start = 0;
+  y_start = 0;
+  open = 0;
+  for (i = 0; i < size; i++)
+    {
+      new[i].code = src[i].code;
+      x = src[i].x + (PERTURBATION * rand ()) / RAND_MAX - PERTURBATION * 0.5;
+      y = src[i].y + (PERTURBATION * rand ()) / RAND_MAX - PERTURBATION * 0.5;
+      if (src[i].code == ART_MOVETO)
+       {
+         x_start = x;
+         y_start = y;
+         open = 0;
+       }
+      else if (src[i].code == ART_MOVETO_OPEN)
+       open = 1;
+      if (!open && (i + 1 == size || src[i + 1].code != ART_LINETO))
+       {
+         x = x_start;
+         y = y_start;
+       }
+      new[i].x = x;
+      new[i].y = y;
+    }
+  new[i].code = ART_END;
+
+  return new;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_vpath.h b/libraries/libart_lgpl-2.3.7/art_vpath.h
new file mode 100644 (file)
index 0000000..ae0dfab
--- /dev/null
@@ -0,0 +1,71 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_VPATH_H__
+#define __ART_VPATH_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_rect.h"
+#include "art_pathcode.h"
+#else
+#include <art_rect.h>
+#include <art_pathcode.h>
+#endif
+
+/* Basic data structures and constructors for simple vector paths */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtVpath ArtVpath;
+
+/* CURVETO is not allowed! */
+struct _ArtVpath {
+  ArtPathcode code;
+  double x;
+  double y;
+};
+
+/* Some of the functions need to go into their own modules */
+
+void
+art_vpath_add_point (ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
+                    ArtPathcode code, double x, double y);
+
+ArtVpath *
+art_vpath_new_circle (double x, double y, double r);
+
+ArtVpath *
+art_vpath_affine_transform (const ArtVpath *src, const double matrix[6]);
+
+void
+art_vpath_bbox_drect (const ArtVpath *vec, ArtDRect *drect);
+
+void
+art_vpath_bbox_irect (const ArtVpath *vec, ArtIRect *irect);
+
+ArtVpath *
+art_vpath_perturb (ArtVpath *src);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_VPATH_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_vpath_bpath.c b/libraries/libart_lgpl-2.3.7/art_vpath_bpath.c
new file mode 100644 (file)
index 0000000..9758f61
--- /dev/null
@@ -0,0 +1,315 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Basic constructors and operations for bezier paths */
+
+#include <math.h>
+
+#include "art_misc.h"
+
+#include "art_bpath.h"
+#include "art_vpath.h"
+#include "art_vpath_bpath.h"
+
+/* p must be allocated 2^level points. */
+
+/* level must be >= 1 */
+ArtPoint *
+art_bezier_to_vec (double x0, double y0,
+                  double x1, double y1,
+                  double x2, double y2,
+                  double x3, double y3,
+                  ArtPoint *p,
+                  int level)
+{
+  double x_m, y_m;
+
+#ifdef VERBOSE
+  printf ("bezier_to_vec: %g,%g %g,%g %g,%g %g,%g %d\n",
+         x0, y0, x1, y1, x2, y2, x3, y3, level);
+#endif
+  if (level == 1) {
+    x_m = (x0 + 3 * (x1 + x2) + x3) * 0.125;
+    y_m = (y0 + 3 * (y1 + y2) + y3) * 0.125;
+    p->x = x_m;
+    p->y = y_m;
+    p++;
+    p->x = x3;
+    p->y = y3;
+    p++;
+#ifdef VERBOSE
+    printf ("-> (%g, %g) -> (%g, %g)\n", x_m, y_m, x3, y3);
+#endif
+  } else {
+    double xa1, ya1;
+    double xa2, ya2;
+    double xb1, yb1;
+    double xb2, yb2;
+
+    xa1 = (x0 + x1) * 0.5;
+    ya1 = (y0 + y1) * 0.5;
+    xa2 = (x0 + 2 * x1 + x2) * 0.25;
+    ya2 = (y0 + 2 * y1 + y2) * 0.25;
+    xb1 = (x1 + 2 * x2 + x3) * 0.25;
+    yb1 = (y1 + 2 * y2 + y3) * 0.25;
+    xb2 = (x2 + x3) * 0.5;
+    yb2 = (y2 + y3) * 0.5;
+    x_m = (xa2 + xb1) * 0.5;
+    y_m = (ya2 + yb1) * 0.5;
+#ifdef VERBOSE
+    printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
+           xb1, yb1, xb2, yb2);
+#endif
+    p = art_bezier_to_vec (x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, p, level - 1);
+    p = art_bezier_to_vec (x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, p, level - 1);
+  }
+  return p;
+}
+
+#define RENDER_LEVEL 4
+#define RENDER_SIZE (1 << (RENDER_LEVEL))
+
+/**
+ * art_vpath_render_bez: Render a bezier segment into the vpath. 
+ * @p_vpath: Where the pointer to the #ArtVpath structure is stored.
+ * @pn_points: Pointer to the number of points in *@p_vpath.
+ * @pn_points_max: Pointer to the number of points allocated.
+ * @x0: X coordinate of starting bezier point.
+ * @y0: Y coordinate of starting bezier point.
+ * @x1: X coordinate of first bezier control point.
+ * @y1: Y coordinate of first bezier control point.
+ * @x2: X coordinate of second bezier control point.
+ * @y2: Y coordinate of second bezier control point.
+ * @x3: X coordinate of ending bezier point.
+ * @y3: Y coordinate of ending bezier point.
+ * @flatness: Flatness control.
+ *
+ * Renders a bezier segment into the vector path, reallocating and
+ * updating *@p_vpath and *@pn_vpath_max as necessary. *@pn_vpath is
+ * incremented by the number of vector points added.
+ *
+ * This step includes (@x0, @y0) but not (@x3, @y3).
+ *
+ * The @flatness argument guides the amount of subdivision. The Adobe
+ * PostScript reference manual defines flatness as the maximum
+ * deviation between the any point on the vpath approximation and the
+ * corresponding point on the "true" curve, and we follow this
+ * definition here. A value of 0.25 should ensure high quality for aa
+ * rendering.
+**/
+static void
+art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
+                     double x0, double y0,
+                     double x1, double y1,
+                     double x2, double y2,
+                     double x3, double y3,
+                     double flatness)
+{
+  double x3_0, y3_0;
+  double z3_0_dot;
+  double z1_dot, z2_dot;
+  double z1_perp, z2_perp;
+  double max_perp_sq;
+
+  double x_m, y_m;
+  double xa1, ya1;
+  double xa2, ya2;
+  double xb1, yb1;
+  double xb2, yb2;
+
+  /* It's possible to optimize this routine a fair amount.
+
+     First, once the _dot conditions are met, they will also be met in
+     all further subdivisions. So we might recurse to a different
+     routine that only checks the _perp conditions.
+
+     Second, the distance _should_ decrease according to fairly
+     predictable rules (a factor of 4 with each subdivision). So it might
+     be possible to note that the distance is within a factor of 4 of
+     acceptable, and subdivide once. But proving this might be hard.
+
+     Third, at the last subdivision, x_m and y_m can be computed more
+     expeditiously (as in the routine above).
+
+     Finally, if we were able to subdivide by, say 2 or 3, this would
+     allow considerably finer-grain control, i.e. fewer points for the
+     same flatness tolerance. This would speed things up downstream.
+
+     In any case, this routine is unlikely to be the bottleneck. It's
+     just that I have this undying quest for more speed...
+
+  */
+
+  x3_0 = x3 - x0;
+  y3_0 = y3 - y0;
+
+  /* z3_0_dot is dist z0-z3 squared */
+  z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
+
+  /* todo: this test is far from satisfactory. */
+  if (z3_0_dot < 0.001)
+    goto nosubdivide;
+
+  /* we can avoid subdivision if:
+
+     z1 has distance no more than flatness from the z0-z3 line
+
+     z1 is no more z0'ward than flatness past z0-z3
+
+     z1 is more z0'ward than z3'ward on the line traversing z0-z3
+
+     and correspondingly for z2 */
+
+  /* perp is distance from line, multiplied by dist z0-z3 */
+  max_perp_sq = flatness * flatness * z3_0_dot;
+
+  z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
+  if (z1_perp * z1_perp > max_perp_sq)
+    goto subdivide;
+
+  z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
+  if (z2_perp * z2_perp > max_perp_sq)
+    goto subdivide;
+
+  z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
+  if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
+    goto subdivide;
+
+  z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
+  if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
+    goto subdivide;
+
+  if (z1_dot + z1_dot > z3_0_dot)
+    goto subdivide;
+
+  if (z2_dot + z2_dot > z3_0_dot)
+    goto subdivide;
+
+ nosubdivide:
+  /* don't subdivide */
+  art_vpath_add_point (p_vpath, pn, pn_max,
+                      ART_LINETO, x3, y3);
+  return;
+
+ subdivide:
+
+  xa1 = (x0 + x1) * 0.5;
+  ya1 = (y0 + y1) * 0.5;
+  xa2 = (x0 + 2 * x1 + x2) * 0.25;
+  ya2 = (y0 + 2 * y1 + y2) * 0.25;
+  xb1 = (x1 + 2 * x2 + x3) * 0.25;
+  yb1 = (y1 + 2 * y2 + y3) * 0.25;
+  xb2 = (x2 + x3) * 0.5;
+  yb2 = (y2 + y3) * 0.5;
+  x_m = (xa2 + xb1) * 0.5;
+  y_m = (ya2 + yb1) * 0.5;
+#ifdef VERBOSE
+  printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
+         xb1, yb1, xb2, yb2);
+#endif
+  art_vpath_render_bez (p_vpath, pn, pn_max,
+                       x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness);
+  art_vpath_render_bez (p_vpath, pn, pn_max,
+                       x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
+}
+
+/**
+ * art_bez_path_to_vec: Create vpath from bezier path.
+ * @bez: Bezier path.
+ * @flatness: Flatness control.
+ *
+ * Creates a vector path closely approximating the bezier path defined by
+ * @bez. The @flatness argument controls the amount of subdivision. In
+ * general, the resulting vpath deviates by at most @flatness pixels
+ * from the "ideal" path described by @bez.
+ *
+ * Return value: Newly allocated vpath.
+ **/
+ArtVpath *
+art_bez_path_to_vec (const ArtBpath *bez, double flatness)
+{
+  ArtVpath *vec;
+  int vec_n, vec_n_max;
+  int bez_index;
+  double x, y;
+
+  vec_n = 0;
+  vec_n_max = RENDER_SIZE;
+  vec = art_new (ArtVpath, vec_n_max);
+
+  /* Initialization is unnecessary because of the precondition that the
+     bezier path does not begin with LINETO or CURVETO, but is here
+     to make the code warning-free. */
+  x = 0;
+  y = 0;
+
+  bez_index = 0;
+  do
+    {
+#ifdef VERBOSE
+      printf ("%s %g %g\n",
+             bez[bez_index].code == ART_CURVETO ? "curveto" :
+             bez[bez_index].code == ART_LINETO ? "lineto" :
+             bez[bez_index].code == ART_MOVETO ? "moveto" :
+             bez[bez_index].code == ART_MOVETO_OPEN ? "moveto-open" :
+             "end", bez[bez_index].x3, bez[bez_index].y3);
+#endif
+      /* make sure space for at least one more code */
+      if (vec_n >= vec_n_max)
+       art_expand (vec, ArtVpath, vec_n_max);
+      switch (bez[bez_index].code)
+       {
+       case ART_MOVETO_OPEN:
+       case ART_MOVETO:
+       case ART_LINETO:
+         x = bez[bez_index].x3;
+         y = bez[bez_index].y3;
+         vec[vec_n].code = bez[bez_index].code;
+         vec[vec_n].x = x;
+         vec[vec_n].y = y;
+         vec_n++;
+         break;
+       case ART_END:
+         vec[vec_n].code = bez[bez_index].code;
+         vec[vec_n].x = 0;
+         vec[vec_n].y = 0;
+         vec_n++;
+         break;
+       case ART_CURVETO:
+#ifdef VERBOSE
+         printf ("%g,%g %g,%g %g,%g %g,%g\n", x, y,
+                        bez[bez_index].x1, bez[bez_index].y1,
+                        bez[bez_index].x2, bez[bez_index].y2,
+                        bez[bez_index].x3, bez[bez_index].y3);
+#endif
+         art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
+                               x, y,
+                               bez[bez_index].x1, bez[bez_index].y1,
+                               bez[bez_index].x2, bez[bez_index].y2,
+                               bez[bez_index].x3, bez[bez_index].y3,
+                               flatness);
+         x = bez[bez_index].x3;
+         y = bez[bez_index].y3;
+         break;
+       }
+    }
+  while (bez[bez_index++].code != ART_END);
+  return vec;
+}
+
diff --git a/libraries/libart_lgpl-2.3.7/art_vpath_bpath.h b/libraries/libart_lgpl-2.3.7/art_vpath_bpath.h
new file mode 100644 (file)
index 0000000..49c1760
--- /dev/null
@@ -0,0 +1,40 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_VPATH_BPATH_H__
+#define __ART_VPATH_BPATH_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtPoint *art_bezier_to_vec (double x0, double y0,
+                            double x1, double y1,
+                            double x2, double y2,
+                            double x3, double y3,
+                            ArtPoint *p,
+                            int level);
+
+ArtVpath *art_bez_path_to_vec (const ArtBpath *bez, double flatness);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_VPATH_BPATH_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_vpath_dash.c b/libraries/libart_lgpl-2.3.7/art_vpath_dash.c
new file mode 100644 (file)
index 0000000..0c3a23b
--- /dev/null
@@ -0,0 +1,198 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1999-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Apply a dash style to a vector path. */
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "art_misc.h"
+
+#include "art_vpath.h"
+#include "art_vpath_dash.h"
+
+
+/* Return the length of the largest subpath within vpath */
+static int
+art_vpath_dash_max_subpath (const ArtVpath *vpath)
+{
+  int max_subpath;
+  int i;
+  int start;
+
+  max_subpath = 0;
+  start = 0;
+  for (i = 0; vpath[i].code != ART_END; i++)
+    {
+      if (vpath[i].code == ART_MOVETO || vpath[i].code == ART_MOVETO_OPEN)
+       {
+         if (i - start > max_subpath)
+           max_subpath = i - start;
+         start = i;
+       }
+    }
+  if (i - start > max_subpath)
+    max_subpath = i - start;
+
+  return max_subpath;
+}
+
+/**
+ * art_vpath_dash: Add dash style to vpath.
+ * @vpath: Original vpath.
+ * @dash: Dash style.
+ *
+ * Creates a new vpath that is the result of applying dash style @dash
+ * to @vpath.
+ *
+ * This implementation has two known flaws:
+ *
+ * First, it adds a spurious break at the beginning of the vpath. The
+ * only way I see to resolve this flaw is to run the state forward one
+ * dash break at the beginning, and fix up by looping back to the
+ * first dash break at the end. This is doable but of course adds some
+ * complexity.
+ *
+ * Second, it does not suppress output points that are within epsilon
+ * of each other.
+ *
+ * Return value: Newly created vpath.
+ **/
+ArtVpath *
+art_vpath_dash (const ArtVpath *vpath, const ArtVpathDash *dash)
+{
+  int max_subpath;
+  double *dists;
+  ArtVpath *result;
+  int n_result, n_result_max;
+  int start, end;
+  int i;
+  double total_dist;
+
+  /* state while traversing dasharray - offset is offset of current dash
+     value, toggle is 0 for "off" and 1 for "on", and phase is the distance
+     in, >= 0, < dash->dash[offset]. */
+  int offset, toggle;
+  double phase;
+
+  /* initial values */
+  int offset_init, toggle_init;
+  double phase_init;
+
+  max_subpath = art_vpath_dash_max_subpath (vpath);
+  dists = art_new (double, max_subpath);
+
+  n_result = 0;
+  n_result_max = 16;
+  result = art_new (ArtVpath, n_result_max);
+
+  /* determine initial values of dash state */
+  toggle_init = 1;
+  offset_init = 0;
+  phase_init = dash->offset;
+  while (phase_init >= dash->dash[offset_init])
+    {
+      toggle_init = !toggle_init;
+      phase_init -= dash->dash[offset_init];
+      offset_init++;
+      if (offset_init == dash->n_dash)
+       offset_init = 0;
+    }
+
+  for (start = 0; vpath[start].code != ART_END; start = end)
+    {
+      for (end = start + 1; vpath[end].code == ART_LINETO; end++);
+      /* subpath is [start..end) */
+      total_dist = 0;
+      for (i = start; i < end - 1; i++)
+       {
+         double dx, dy;
+
+         dx = vpath[i + 1].x - vpath[i].x;
+         dy = vpath[i + 1].y - vpath[i].y;
+         dists[i - start] = sqrt (dx * dx + dy * dy);
+         total_dist += dists[i - start];
+       }
+      if (total_dist <= dash->dash[offset_init] - phase_init)
+       {
+         /* subpath fits entirely within first dash */
+         if (toggle_init)
+           {
+             for (i = start; i < end; i++)
+               art_vpath_add_point (&result, &n_result, &n_result_max,
+                                    vpath[i].code, vpath[i].x, vpath[i].y);
+           }
+       }
+      else
+       {
+         /* subpath is composed of at least one dash - thus all
+            generated pieces are open */
+         double dist;
+
+         phase = phase_init;
+         offset = offset_init;
+         toggle = toggle_init;
+         dist = 0;
+         i = start;
+         if (toggle)
+           art_vpath_add_point (&result, &n_result, &n_result_max,
+                                ART_MOVETO_OPEN, vpath[i].x, vpath[i].y);
+         while (i != end - 1)
+           {
+             if (dists[i - start] - dist > dash->dash[offset] - phase)
+               {
+                 /* dash boundary is next */
+                 double a;
+                 double x, y;
+
+                 dist += dash->dash[offset] - phase;
+                 a = dist / dists[i - start];
+                 x = vpath[i].x + a * (vpath[i + 1].x - vpath[i].x);
+                 y = vpath[i].y + a * (vpath[i + 1].y - vpath[i].y);
+                 art_vpath_add_point (&result, &n_result, &n_result_max,
+                                      toggle ? ART_LINETO : ART_MOVETO_OPEN,
+                                      x, y);
+                 /* advance to next dash */
+                 toggle = !toggle;
+                 phase = 0;
+                 offset++;
+                 if (offset == dash->n_dash)
+                   offset = 0;
+               }
+             else
+               {
+                 /* end of line in vpath is next */
+                 phase += dists[i - start] - dist;
+                 i++;
+                 dist = 0;
+                 if (toggle)
+                   art_vpath_add_point (&result, &n_result, &n_result_max,
+                                        ART_LINETO, vpath[i].x, vpath[i].y);
+               }
+           }
+       }
+    }
+
+  art_vpath_add_point (&result, &n_result, &n_result_max,
+                      ART_END, 0, 0);
+
+  art_free (dists);
+
+  return result;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_vpath_dash.h b/libraries/libart_lgpl-2.3.7/art_vpath_dash.h
new file mode 100644 (file)
index 0000000..881a5bc
--- /dev/null
@@ -0,0 +1,44 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1999 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_VPATH_DASH_H__
+#define __ART_VPATH_DASH_H__
+
+/* Apply a dash style to a vector path. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtVpathDash ArtVpathDash;
+
+struct _ArtVpathDash {
+  double offset;
+  int n_dash;
+  double *dash;
+};
+
+ArtVpath *
+art_vpath_dash (const ArtVpath *vpath, const ArtVpathDash *dash);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_VPATH_DASH_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/art_vpath_svp.c b/libraries/libart_lgpl-2.3.7/art_vpath_svp.c
new file mode 100644 (file)
index 0000000..57aa0db
--- /dev/null
@@ -0,0 +1,194 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* "Unsort" a sorted vector path into an ordinary vector path. */
+
+#include <stdio.h> /* for printf - debugging */
+#include "art_misc.h"
+
+#include "art_vpath.h"
+#include "art_svp.h"
+#include "art_vpath_svp.h"
+
+typedef struct _ArtVpathSVPEnd ArtVpathSVPEnd;
+
+struct _ArtVpathSVPEnd {
+  int seg_num;
+  int which; /* 0 = top, 1 = bottom */
+  double x, y;
+};
+
+#define EPSILON 1e-6
+
+static int
+art_vpath_svp_point_compare (double x1, double y1, double x2, double y2)
+{
+  if (y1 - EPSILON > y2) return 1;
+  if (y1 + EPSILON < y2) return -1;
+  if (x1 - EPSILON > x2) return 1;
+  if (x1 + EPSILON < x2) return -1;
+  return 0;
+}
+
+static int
+art_vpath_svp_compare (const void *s1, const void *s2)
+{
+  const ArtVpathSVPEnd *e1 = s1;
+  const ArtVpathSVPEnd *e2 = s2;
+
+  return art_vpath_svp_point_compare (e1->x, e1->y, e2->x, e2->y);
+}
+
+/* Convert from sorted vector path representation into regular
+   vector path representation.
+
+   Status of this routine:
+
+   Basic correctness: Only works with closed paths.
+
+   Numerical stability: Not known to work when more than two segments
+   meet at a point.
+
+   Speed: Should be pretty good.
+
+   Precision: Does not degrade precision.
+
+*/
+/**
+ * art_vpath_from_svp: Convert from svp to vpath form.
+ * @svp: Original #ArtSVP.
+ *
+ * Converts the sorted vector path @svp into standard vpath form.
+ *
+ * Return value: the newly allocated vpath.
+ **/
+ArtVpath *
+art_vpath_from_svp (const ArtSVP *svp)
+{
+  int n_segs = svp->n_segs;
+  ArtVpathSVPEnd *ends;
+  ArtVpath *new;
+  int *visited;
+  int n_new, n_new_max;
+  int i, k;
+  int j = 0; /* Quiet compiler */
+  int seg_num;
+  int first;
+  double last_x, last_y;
+  int n_points;
+  int pt_num;
+
+  last_x = 0; /* to eliminate "uninitialized" warning */
+  last_y = 0;
+
+  ends = art_new (ArtVpathSVPEnd, n_segs * 2);
+  for (i = 0; i < svp->n_segs; i++)
+    {
+      int lastpt;
+
+      ends[i * 2].seg_num = i;
+      ends[i * 2].which = 0;
+      ends[i * 2].x = svp->segs[i].points[0].x;
+      ends[i * 2].y = svp->segs[i].points[0].y;
+
+      lastpt = svp->segs[i].n_points - 1;
+      ends[i * 2 + 1].seg_num = i;
+      ends[i * 2 + 1].which = 1;
+      ends[i * 2 + 1].x = svp->segs[i].points[lastpt].x;
+      ends[i * 2 + 1].y = svp->segs[i].points[lastpt].y;
+    }
+  qsort (ends, n_segs * 2, sizeof (ArtVpathSVPEnd), art_vpath_svp_compare);
+
+  n_new = 0;
+  n_new_max = 16; /* I suppose we _could_ estimate this from traversing
+                    the svp, so we don't have to reallocate */
+  new = art_new (ArtVpath, n_new_max);
+
+  visited = art_new (int, n_segs);
+  for (i = 0; i < n_segs; i++)
+    visited[i] = 0;
+
+  first = 1;
+  for (i = 0; i < n_segs; i++)
+    {
+      if (!first)
+       {
+         /* search for the continuation of the existing subpath */
+         /* This could be a binary search (which is why we sorted, above) */
+         for (j = 0; j < n_segs * 2; j++)
+           {
+             if (!visited[ends[j].seg_num] &&
+                 art_vpath_svp_point_compare (last_x, last_y,
+                                              ends[j].x, ends[j].y) == 0)
+               break;
+           }
+         if (j == n_segs * 2)
+           first = 1;
+       }
+      if (first)
+       {
+         /* start a new subpath */
+         for (j = 0; j < n_segs * 2; j++)
+           if (!visited[ends[j].seg_num])
+             break;
+       }
+      if (j == n_segs * 2)
+       {
+         printf ("failure\n");
+       }
+      seg_num = ends[j].seg_num;
+      n_points = svp->segs[seg_num].n_points;
+      for (k = 0; k < n_points; k++)
+       {
+         pt_num = svp->segs[seg_num].dir ? k : n_points - (1 + k);
+         if (k == 0)
+           {
+             if (first)
+               {
+                 art_vpath_add_point (&new, &n_new, &n_new_max,
+                                      ART_MOVETO,
+                                      svp->segs[seg_num].points[pt_num].x,
+                                      svp->segs[seg_num].points[pt_num].y);
+               }
+           }
+         else
+           {
+             art_vpath_add_point (&new, &n_new, &n_new_max,
+                                  ART_LINETO,
+                                  svp->segs[seg_num].points[pt_num].x,
+                                  svp->segs[seg_num].points[pt_num].y);
+             if (k == n_points - 1)
+               {
+                 last_x = svp->segs[seg_num].points[pt_num].x;
+                 last_y = svp->segs[seg_num].points[pt_num].y;
+                 /* to make more robust, check for meeting first_[xy],
+                    set first if so */
+               }
+           }
+         first = 0;
+       }
+      visited[seg_num] = 1;
+    }
+
+  art_vpath_add_point (&new, &n_new, &n_new_max,
+                      ART_END, 0, 0);
+  art_free (visited);
+  art_free (ends);
+  return new;
+}
diff --git a/libraries/libart_lgpl-2.3.7/art_vpath_svp.h b/libraries/libart_lgpl-2.3.7/art_vpath_svp.h
new file mode 100644 (file)
index 0000000..7d1a4c5
--- /dev/null
@@ -0,0 +1,43 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_VPATH_SVP_H__
+#define __ART_VPATH_SVP_H__
+
+/* "Unsort" a sorted vector path into an ordinary vector path. */
+
+#ifdef LIBART_COMPILATION
+#include "art_rect.h"
+#include "art_point.h"
+#else
+#include <art_rect.h>
+#include <art_point.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtVpath *art_vpath_from_svp (const ArtSVP *svp);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_VPATH_SVP_H__ */
diff --git a/libraries/libart_lgpl-2.3.7/gen_art_config.c b/libraries/libart_lgpl-2.3.7/gen_art_config.c
new file mode 100644 (file)
index 0000000..8d88815
--- /dev/null
@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include "config.h"
+#include <stdlib.h>
+
+/**
+ * A little utility function to generate header info.
+ *
+ * Yes, it would be possible to do this using more "native" autoconf
+ * features, but I personally find this approach to be cleaner.
+ *
+ * The output of this program is generally written to art_config.h,
+ * which is installed in libart's include dir.
+ **/
+
+static void
+die (char *why)
+{
+  fprintf (stderr, "gen_art_config: %s\n", why);
+  exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+  printf ("/* Automatically generated by gen_art_config.c */\n"
+         "\n"
+         "#define ART_SIZEOF_CHAR %d\n"
+         "#define ART_SIZEOF_SHORT %d\n"
+         "#define ART_SIZEOF_INT %d\n"
+         "#define ART_SIZEOF_LONG %d\n"
+         "\n",
+         (int)sizeof(char), (int)sizeof(short), (int)sizeof(int), (int)sizeof(long));
+
+  if (sizeof(char) == 1)
+    printf ("typedef unsigned char art_u8;\n");
+  else
+    die ("sizeof(char) != 1");
+
+  if (sizeof(short) == 2)
+    printf ("typedef unsigned short art_u16;\n");
+  else
+    die ("sizeof(short) != 2");
+
+  if (sizeof(int) == 4)
+    printf ("typedef unsigned int art_u32;\n");
+  else if (sizeof(long) == 4)
+    printf ("typedef unsigned long art_u32;\n");
+  else
+    die ("sizeof(int) != 4 and sizeof(long) != 4");
+
+  return 0;
+}
diff --git a/libraries/libart_lgpl-2.3.7/install-sh b/libraries/libart_lgpl-2.3.7/install-sh
new file mode 100755 (executable)
index 0000000..e9de238
--- /dev/null
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+               chmodcmd=""
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/libraries/libart_lgpl-2.3.7/libart-2.0.pc.in b/libraries/libart_lgpl-2.3.7/libart-2.0.pc.in
new file mode 100644 (file)
index 0000000..1df143b
--- /dev/null
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libart
+Description: LGPL version of the libart library
+Version: @VERSION@
+Libs: -L${libdir} -lart_lgpl_2
+Cflags: -I${includedir}/libart-2.0
diff --git a/libraries/libart_lgpl-2.3.7/libart-config.in b/libraries/libart_lgpl-2.3.7/libart-config.in
new file mode 100644 (file)
index 0000000..0a2f3a9
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+exec_prefix_set=no
+
+usage="\
+Usage: libart-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]"
+
+if test $# -eq 0; then
+      echo "${usage}" 1>&2
+      exit 1
+fi
+
+while test $# -gt 0; do
+  case "$1" in
+  -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  case $1 in
+    --prefix=*)
+      prefix=$optarg
+      if test $exec_prefix_set = no ; then
+        exec_prefix=$optarg
+      fi
+      ;;
+    --prefix)
+      echo $prefix
+      ;;
+    --exec-prefix=*)
+      exec_prefix=$optarg
+      exec_prefix_set=yes
+      ;;
+    --exec-prefix)
+      echo $exec_prefix
+      ;;
+    --version)
+      echo @LIBART_VERSION@
+      ;;
+    --cflags)
+      includes=-I@includedir@/libart-2.0
+      echo $includes
+      ;;
+    --libs)
+      libdirs=-L@libdir@
+      echo $libdirs -lart_lgpl_2 -lm
+      ;;
+    *)
+      echo "${usage}" 1>&2
+      exit 1
+      ;;
+  esac
+  shift
+done
+
diff --git a/libraries/libart_lgpl-2.3.7/libart-features.c b/libraries/libart_lgpl-2.3.7/libart-features.c
new file mode 100644 (file)
index 0000000..ff99945
--- /dev/null
@@ -0,0 +1,18 @@
+#include "libart-features.h"
+
+/* General initialization hooks */
+const unsigned int libart_major_version=LIBART_MAJOR_VERSION,
+  libart_minor_version=LIBART_MINOR_VERSION,
+  libart_micro_version=LIBART_MICRO_VERSION;
+
+const char *libart_version = LIBART_VERSION;
+
+void
+libart_preinit(void *app, void *modinfo)
+{
+}
+
+void
+libart_postinit(void *app, void *modinfo)
+{
+}
diff --git a/libraries/libart_lgpl-2.3.7/libart-features.h b/libraries/libart_lgpl-2.3.7/libart-features.h
new file mode 100644 (file)
index 0000000..a99a4ad
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef LIBART_FEATURES_H
+#define LIBART_FEATURES_H 1
+
+#define LIBART_MAJOR_VERSION (2)
+#define LIBART_MINOR_VERSION (3)
+#define LIBART_MICRO_VERSION (7)
+#define LIBART_VERSION "2.3.7"
+
+extern const unsigned int libart_major_version, libart_minor_version, libart_micro_version;
+extern const char *libart_version;
+
+void libart_preinit(void *app, void *modinfo);
+void libart_postinit(void *app, void *modinfo);
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/libart-features.h.in b/libraries/libart_lgpl-2.3.7/libart-features.h.in
new file mode 100644 (file)
index 0000000..e78bade
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef LIBART_FEATURES_H
+#define LIBART_FEATURES_H 1
+
+#define LIBART_MAJOR_VERSION (@LIBART_MAJOR_VERSION@)
+#define LIBART_MINOR_VERSION (@LIBART_MINOR_VERSION@)
+#define LIBART_MICRO_VERSION (@LIBART_MICRO_VERSION@)
+#define LIBART_VERSION "@LIBART_VERSION@"
+
+extern const unsigned int libart_major_version, libart_minor_version, libart_micro_version;
+extern const char *libart_version;
+
+void libart_preinit(void *app, void *modinfo);
+void libart_postinit(void *app, void *modinfo);
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/libart.h b/libraries/libart_lgpl-2.3.7/libart.h
new file mode 100644 (file)
index 0000000..c472f59
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef LIBART_H
+#define LIBART_H 1
+
+#include <art_affine.h>
+#include <art_alphagamma.h>
+#include <art_bpath.h>
+#include <art_filterlevel.h>
+#include <art_gray_svp.h>
+#include <art_misc.h>
+#include <art_pathcode.h>
+#include <art_pixbuf.h>
+#include <art_point.h>
+#include <art_rect.h>
+#include <art_rect_svp.h>
+#include <art_rect_uta.h>
+#include <art_rgb.h>
+#include <art_rgb_affine.h>
+#include <art_rgb_bitmap_affine.h>
+#include <art_rgb_pixbuf_affine.h>
+#include <art_rgb_rgba_affine.h>
+#include <art_rgb_svp.h>
+#include <art_svp.h>
+#include <art_svp_ops.h>
+#include <art_svp_point.h>
+#include <art_svp_render_aa.h>
+#include <art_svp_vpath.h>
+#include <art_svp_vpath_stroke.h>
+#include <art_svp_wind.h>
+#include <art_uta.h>
+#include <art_uta_ops.h>
+#include <art_uta_rect.h>
+#include <art_uta_svp.h>
+#include <art_uta_vpath.h>
+#include <art_vpath.h>
+#include <art_vpath_bpath.h>
+#include <art_vpath_dash.h>
+#include <art_vpath_svp.h>
+
+#endif
diff --git a/libraries/libart_lgpl-2.3.7/libart_lgpl_2.la b/libraries/libart_lgpl-2.3.7/libart_lgpl_2.la
new file mode 100644 (file)
index 0000000..93ee8c1
--- /dev/null
@@ -0,0 +1,32 @@
+# libart_lgpl_2.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.4 (1.920 2001/04/24 23:26:18)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname=''
+
+# Names of this library.
+library_names=''
+
+# The name of the static archive.
+old_library='libart_lgpl_2.a'
+
+# Libraries that this one depends upon.
+dependency_libs=' -lm'
+
+# Version information for libart_lgpl_2.
+current=5
+age=3
+revision=7
+
+# Is this an already installed library?
+installed=no
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='/usr/local/rrdtool-1.0.33/lib'
diff --git a/libraries/libart_lgpl-2.3.7/missing b/libraries/libart_lgpl-2.3.7/missing
new file mode 100755 (executable)
index 0000000..7789652
--- /dev/null
@@ -0,0 +1,190 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+case "$1" in
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]"
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing - GNU libit 0.0"
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+  aclocal)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acinclude.m4' or \`configure.in'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`configure.in'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acconfig.h' or \`configure.in'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case "$f" in
+      *:*) touch_files="$touch_files "`echo "$f" |
+                                      sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+          sed 's/\.am$/.in/' |
+          while read f; do touch "$f"; done
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+       case "$LASTARG" in
+       *.y)
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" y.tab.c
+           fi
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" y.tab.h
+           fi
+         ;;
+       esac
+    fi
+    if [ ! -f y.tab.h ]; then
+       echo >y.tab.h
+    fi
+    if [ ! -f y.tab.c ]; then
+       echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+       case "$LASTARG" in
+       *.l)
+           SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" lex.yy.c
+           fi
+         ;;
+       esac
+    fi
+    if [ ! -f lex.yy.c ]; then
+       echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  makeinfo)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+      file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+    fi
+    touch $file
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequirements for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
diff --git a/libraries/libart_lgpl-2.3.7/mkinstalldirs b/libraries/libart_lgpl-2.3.7/mkinstalldirs
new file mode 100755 (executable)
index 0000000..6b3b5fc
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id$
+
+errstatus=0
+
+for file
+do
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d
+   do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp"
+
+        mkdir "$pathcomp" || lasterr=$?
+
+        if test ! -d "$pathcomp"; then
+         errstatus=$lasterr
+        fi
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/libraries/libart_lgpl-2.3.7/stamp-h.in b/libraries/libart_lgpl-2.3.7/stamp-h.in
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libraries/libart_lgpl-2.3.7/testart.c b/libraries/libart_lgpl-2.3.7/testart.c
new file mode 100644 (file)
index 0000000..9d9c069
--- /dev/null
@@ -0,0 +1,634 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998, 1999 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "art_misc.h"
+#include "art_vpath.h"
+#include "art_svp.h"
+#include "art_svp_vpath.h"
+#include "art_gray_svp.h"
+#include "art_rgb_svp.h"
+#include "art_svp_vpath_stroke.h"
+#include "art_svp_ops.h"
+#include "art_affine.h"
+#include "art_rgb_affine.h"
+#include "art_rgb_bitmap_affine.h"
+#include "art_rgb_rgba_affine.h"
+#include "art_alphagamma.h"
+#include "art_svp_point.h"
+#include "art_vpath_dash.h"
+#include "art_render.h"
+#include "art_render_gradient.h"
+#include "art_render_svp.h"
+#include "art_svp_intersect.h"
+
+#ifdef DEAD_CODE
+static void
+test_affine (void) {
+  double src[6];
+  double dst[6];
+  double src2[6];
+  char str[128];
+  int i;
+  ArtPoint ps, pd, ptmp;
+
+  for (i = 0; i < 6; i++)
+    {
+      src[i] = (rand () * 2.0 / RAND_MAX) - 1.0;
+      src2[i] = (rand () * 2.0 / RAND_MAX) - 1.0;
+    }
+#if 0
+  src[0] = 0.9999999;
+  src[1] = -0.000001;
+  src[2] = 0.000001;
+  src[3] = 0.9999999;
+  src[4] = 0;
+  src[5] = 0;
+#if 1
+  src[0] = 0.98480775;
+  src[1] = -0.17364818;
+  src[2] = 0.17364818;
+  src[3] = 0.98480775;
+#endif
+
+  src2[0] = 0.98480775;
+  src2[1] = -0.17364818;
+  src2[2] = 0.17364818;
+  src2[3] = 0.98480775;
+#endif
+
+
+  ps.x = rand() * 100.0 / RAND_MAX;
+  ps.y = rand() * 100.0 / RAND_MAX;
+
+  art_affine_point (&pd, &ps, src);
+  art_affine_invert (dst, src);
+  art_affine_point (&ptmp, &pd, dst);
+  art_affine_to_string (str, src);
+  printf ("src = %s\n", str);
+  art_affine_to_string (str, dst);
+  printf ("dst = %s\n", str);
+  printf ("point (%g, %g) -> (%g, %g) -> (%g, %g)\n",
+         ps.x, ps.y, pd.x, pd.y, ptmp.x, ptmp.y);
+
+  art_affine_point (&ptmp, &ps, src);
+  art_affine_point (&pd, &ptmp, src2);
+  art_affine_to_string (str, src2);
+  printf ("src2 = %s\n", str);
+  printf ("point (%g, %g) -> (%g, %g) -> (%g, %g)\n",
+         ps.x, ps.y, ptmp.x, ptmp.y, pd.x, pd.y);
+  art_affine_multiply (dst, src, src2);
+  art_affine_to_string (str, dst);
+  printf ("dst = %s\n", str);
+  art_affine_point (&pd, &ps, dst);
+  printf ("point (%g, %g) -> (%g, %g)\n",
+         ps.x, ps.y, pd.x, pd.y);
+
+}
+#endif
+
+static ArtVpath *
+randstar (int n)
+{
+  ArtVpath *vec;
+  int i;
+  double r, th;
+
+  vec = art_new (ArtVpath, n + 2);
+  for (i = 0; i < n; i++)
+    {
+      vec[i].code = i ? ART_LINETO : ART_MOVETO;
+      r = rand () * (250.0 / RAND_MAX);
+#if 0
+      r = r + 0.9 * (250 - r);
+#endif
+      th = i * 2 * M_PI / n;
+      vec[i].x = 250 + r * cos (th);
+      vec[i].y = 250 - r * sin (th);
+    }
+  vec[i].code = ART_LINETO;
+  vec[i].x = vec[0].x;
+  vec[i].y = vec[0].y;
+  i++;
+  vec[i].code = ART_END;
+  vec[i].x = 0;
+  vec[i].y = 0;
+  return vec;
+}
+
+#define TILE_SIZE 512
+#define NUM_ITERS 1
+#define COLOR
+
+#ifdef COLOR
+#define BYTES_PP 3
+#else
+#define BYTES_PP 1
+#endif
+
+#ifndef nDEAD_CODE
+static void
+print_svp (ArtSVP *vp)
+{
+  int i, j;
+
+  for (i = 0; i < vp->n_segs; i++)
+    {
+      printf ("segment %d, dir = %s (%f, %f) - (%f, %f)\n",
+             i, vp->segs[i].dir ? "down" : "up",
+             vp->segs[i].bbox.x0,
+             vp->segs[i].bbox.y0,
+             vp->segs[i].bbox.x1,
+             vp->segs[i].bbox.y1);
+      for (j = 0; j < vp->segs[i].n_points; j++)
+        printf ("  (%g, %g)\n",
+                vp->segs[i].points[j].x,
+                vp->segs[i].points[j].y);
+    }
+}
+#endif
+
+static void
+print_vpath (ArtVpath *vpath)
+{
+  int i;
+
+  for (i = 0; vpath[i].code != ART_END; i++)
+    printf ("%g %g %s\n",
+           vpath[i].x, vpath[i].y,
+           vpath[i].code == ART_MOVETO_OPEN ? "moveto %open" :
+           vpath[i].code == ART_MOVETO ? "moveto" :
+           vpath[i].code == ART_LINETO ? "lineto" :
+           "?");
+
+  printf ("stroke\n");
+}
+
+static void
+make_testpat (void)
+{
+  ArtVpath *vpath, *vpath2, *vpath3;
+  ArtSVP *svp, *svp2;
+  ArtSVP *svp3;
+  art_u8 buf[512 * 512 * BYTES_PP];
+  int i, j;
+  int iter;
+  art_u8 colorimg[256][256][3];
+  art_u8 rgbaimg[256][256][4];
+  art_u8 bitimg[16][2];
+  int x, y;
+  double affine[6];
+  double affine2[6];
+  double affine3[6];
+  ArtAlphaGamma *alphagamma;
+  double dash_data[] = { 20 };
+  ArtVpathDash dash;
+
+  dash.offset = 0;
+  dash.n_dash = 1;
+  dash.dash = dash_data;
+
+#ifdef TEST_AFFINE
+  test_affine ();
+  exit (0);
+#endif
+
+  vpath = randstar (50);
+  svp = art_svp_from_vpath (vpath);
+  art_free (vpath);
+
+  vpath2 = randstar (50);
+#if 1
+  vpath3 = art_vpath_dash (vpath2, &dash);
+  art_free (vpath2);
+  svp2 = art_svp_vpath_stroke (vpath3,
+                              ART_PATH_STROKE_JOIN_MITER,
+                              ART_PATH_STROKE_CAP_BUTT,
+                              15,
+                              4,
+                              0.5);
+  art_free (vpath3);
+#else
+  svp2 = art_svp_from_vpath (vpath2);
+#endif
+
+#if 1
+  svp3 = art_svp_intersect (svp, svp2);
+#else
+  svp3 = svp2;
+#endif
+
+#if 0
+  print_svp (svp);
+#endif
+
+  for (y = 0; y < 256; y++)
+    for (x = 0; x < 256; x++)
+      {
+       colorimg[y][x][0] = (x + y) >> 1;
+       colorimg[y][x][1] = (x + (255 - y)) >> 1;
+       colorimg[y][x][2] = ((255 - x) + y) >> 1;
+
+       rgbaimg[y][x][0] = (x + y) >> 1;
+       rgbaimg[y][x][1] = (x + (255 - y)) >> 1;
+       rgbaimg[y][x][2] = ((255 - x) + y) >> 1;
+       rgbaimg[y][x][3] = y;
+      }
+
+  for (y = 0; y < 16; y++)
+    for (x = 0; x < 2; x++)
+      bitimg[y][x] = (x << 4) | y;
+
+  affine[0] = 0.5;
+  affine[1] = .2;
+  affine[2] = -.2;
+  affine[3] = 0.5;
+  affine[4] = 64;
+  affine[5] = 64;
+  
+  affine2[0] = 1;
+  affine2[1] = -.2;
+  affine2[2] = .2;
+  affine2[3] = 1;
+  affine2[4] = 128;
+  affine2[5] = 128;
+
+  affine3[0] = 5;
+  affine3[1] = -.2;
+  affine3[2] = .2;
+  affine3[3] = 5;
+  affine3[4] = 384;
+  affine3[5] = 32;
+
+#if 0
+  alphagamma = art_alphagamma_new (1.8);
+#else
+  alphagamma = NULL;
+#endif
+
+#ifdef COLOR
+  printf ("P6\n512 512\n255\n");
+#else
+  printf ("P5\n512 512\n255\n");
+#endif
+  for (iter = 0; iter < NUM_ITERS; iter++)
+    for (j = 0; j < 512; j += TILE_SIZE)
+      for (i = 0; i < 512; i += TILE_SIZE)
+       {
+#ifdef COLOR
+         art_rgb_svp_aa (svp, i, j, i + TILE_SIZE, j + TILE_SIZE,
+                         0xffe0a0, 0x100040,
+                         buf + (j * 512 + i) * BYTES_PP, 512 * BYTES_PP,
+                         alphagamma);
+         art_rgb_svp_alpha (svp2, i, j, i + TILE_SIZE, j + TILE_SIZE,
+                            0xff000080,
+                            buf + (j * 512 + i) * BYTES_PP, 512 * BYTES_PP,
+                            alphagamma);
+         art_rgb_svp_alpha (svp3, i, j, i + TILE_SIZE, j + TILE_SIZE,
+                            0x00ff0080,
+                            buf + (j * 512 + i) * BYTES_PP, 512 * BYTES_PP,
+                            alphagamma);
+         art_rgb_affine (buf + (j * 512 + i) * BYTES_PP,
+                         i, j, i + TILE_SIZE, j + TILE_SIZE, 512 * BYTES_PP,
+                         (art_u8 *)colorimg, 256, 256, 256 * 3,
+                         affine,
+                         ART_FILTER_NEAREST, alphagamma);
+         art_rgb_rgba_affine (buf + (j * 512 + i) * BYTES_PP,
+                              i, j, i + TILE_SIZE, j + TILE_SIZE,
+                              512 * BYTES_PP,
+                              (art_u8 *)rgbaimg, 256, 256, 256 * 4,
+                              affine2,
+                              ART_FILTER_NEAREST, alphagamma);
+         art_rgb_bitmap_affine (buf + (j * 512 + i) * BYTES_PP,
+                                i, j, i + TILE_SIZE, j + TILE_SIZE,
+                                512 * BYTES_PP,
+                                (art_u8 *)bitimg, 16, 16, 2,
+                                0xffff00ff,
+                                affine3,
+                                ART_FILTER_NEAREST, alphagamma);
+#else
+         art_gray_svp_aa (svp, i, j, i + TILE_SIZE, j + TILE_SIZE,
+                          buf + (j * 512 + i) * BYTES_PP, 512 * BYTES_PP);
+#endif
+       }
+
+  art_svp_free (svp2);
+  art_svp_free (svp3);
+  art_svp_free (svp);
+
+#if 1
+  fwrite (buf, 1, 512 * 512 * BYTES_PP, stdout);
+#endif
+}
+
+static void
+test_dist (void)
+{
+  ArtVpath *vpath;
+  ArtSVP *svp;
+  art_u8 buf[512 * 512 * BYTES_PP];
+  int x, y;
+  int ix;
+  double dist;
+  int wind;
+
+  vpath = randstar (20);
+#ifdef NO_STROKE
+  svp = art_svp_from_vpath (vpath);
+#else
+  svp = art_svp_vpath_stroke (vpath,
+                              ART_PATH_STROKE_JOIN_MITER,
+                              ART_PATH_STROKE_CAP_BUTT,
+                              15,
+                              4,
+                              0.5);
+#endif
+
+  art_rgb_svp_aa (svp, 0, 0, 512, 512,
+                 0xffe0a0, 0x100040,
+                 buf, 512 * BYTES_PP,
+                 NULL);
+
+  ix = 0;
+  for (y = 0; y < 512; y++)
+    {
+      for (x = 0; x < 512; x++)
+       {
+         wind = art_svp_point_wind (svp, x, y);
+         buf[ix] = 204 - wind * 51;
+         dist = art_svp_point_dist (svp, x, y);
+         if (((x | y) & 0x3f) == 0)
+           {
+             fprintf (stderr, "%d,%d: %f\n", x, y, dist);
+           }
+         buf[ix + 1] = 255 - dist;
+         ix += 3;
+       }
+    }
+
+  printf ("P6\n512 512\n255\n");
+  fwrite (buf, 1, 512 * 512 * BYTES_PP, stdout);
+
+}
+
+static void
+test_dash (void)
+{
+  ArtVpath *vpath, *vpath2;
+  double dash_data[] = { 10, 4, 1, 4};
+  ArtVpathDash dash;
+         
+  dash.offset = 0;
+  dash.n_dash = 3;
+  dash.dash = dash_data;
+  
+  vpath = randstar (50);
+  vpath2 = art_vpath_dash (vpath, &dash);
+  printf ("%%!\n");
+  print_vpath (vpath2);
+  printf ("showpage\n");
+  art_free (vpath);
+  art_free (vpath2);
+}
+
+static void
+test_render_gradient (art_u8 *buf)
+{
+  ArtGradientLinear gradient;
+  ArtGradientStop stops[3] = {
+    { 0.0, { 0x7fff, 0x0000, 0x0000, 0x7fff }},
+    { 0.5, { 0x0000, 0x0000, 0x0000, 0x1000 }},
+    { 1.0, { 0x0000, 0x7fff, 0x0000, 0x7fff }}
+  };
+  ArtVpath *vpath;
+  ArtSVP *svp;
+  ArtRender *render;
+
+  gradient.a = 0.003;
+  gradient.b = -0.0015;
+  gradient.c = 0.1;
+  gradient.spread = ART_GRADIENT_PAD;
+  gradient.n_stops = sizeof(stops) / sizeof(stops[0]);
+  gradient.stops = stops;
+
+  vpath = randstar (50);
+  svp = art_svp_from_vpath (vpath);
+
+  render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
+                          NULL);
+  art_render_svp (render, svp);
+  art_render_gradient_linear (render, &gradient, ART_FILTER_NEAREST);
+  art_render_invoke (render);
+
+}
+
+static void
+test_render_rad_gradient (art_u8 *buf)
+{
+  ArtGradientRadial gradient;
+  ArtGradientStop stops[3] = {
+    { 0.0, { 0xffff, 0x0000, 0x0000, 0xffff }},
+    { 0.5, { 0xe000, 0xe000, 0x0000, 0xe000 }},
+    { 1.0, { 0x0000, 0x0000, 0x0000, 0x0000 }}
+  };
+  ArtVpath *vpath;
+  ArtSVP *svp;
+  ArtRender *render;
+
+  gradient.affine[0] = 3.0 / 512;
+  gradient.affine[1] = 0;
+  gradient.affine[2] = 0;
+  gradient.affine[3] = 3.0 / 512;
+  gradient.affine[4] = -1.5;
+  gradient.affine[5] = -1.5;
+  gradient.fx = 0.9;
+  gradient.fy = 0.1;
+  
+  gradient.n_stops = sizeof(stops) / sizeof(stops[0]);
+  gradient.stops = stops;
+
+  vpath = randstar (50);
+  svp = art_svp_from_vpath (vpath);
+
+  render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
+                          NULL);
+  art_render_svp (render, svp);
+  art_render_gradient_radial (render, &gradient, ART_FILTER_NEAREST);
+  art_render_invoke (render);
+
+}
+
+static void
+test_gradient (void)
+{
+  ArtVpath *vpath;
+  ArtSVP *svp;
+  art_u8 buf[512 * 512 * 3];
+  ArtRender *render;
+  ArtPixMaxDepth color[3] = {0x0000, 0x0000, 0x8000 };
+  int i;
+  const int n_iter = 1;
+
+  vpath = randstar (50);
+  svp = art_svp_from_vpath (vpath);
+
+  for (i = 0; i < n_iter; i++)
+    {
+#define USE_RENDER
+#ifdef USE_RENDER
+      render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
+                              NULL);
+      art_render_clear_rgb (render, 0xfff0c0);
+      art_render_svp (render, svp);
+      art_render_image_solid (render, color);
+      art_render_invoke (render);
+#else
+      art_rgb_svp_aa (svp, 0, 0, 512, 512, 0xfff0c0, 0x000080,
+                     buf, 512 * 3, NULL);
+#endif
+    }
+
+#if 1
+  test_render_gradient (buf);
+#endif
+  test_render_rad_gradient (buf);
+
+  printf ("P6\n512 512\n255\n");
+  fwrite (buf, 1, 512 * 512 * 3, stdout);
+}
+
+static void
+output_svp_ppm (const ArtSVP *svp)
+{
+  art_u8 buf[512 * 512 * 3];
+  art_rgb_svp_aa (svp, 0, 0, 512, 512, 0xfff0c0, 0x000080,
+                 buf, 512 * 3, NULL);
+  printf ("P6\n512 512\n255\n");
+  fwrite (buf, 1, 512 * 512 * 3, stdout);
+}
+
+static void
+test_intersect (void)
+{
+  ArtVpath vpath[] = {
+
+#if 0
+    /* two triangles */
+    { ART_MOVETO, 100, 100 },
+    { ART_LINETO, 300, 400 },
+    { ART_LINETO, 400, 200 },
+    { ART_LINETO, 100, 100 },
+    { ART_MOVETO, 110, 110 },
+    { ART_LINETO, 310, 410 },
+    { ART_LINETO, 410, 210 },
+    { ART_LINETO, 110, 110 },
+#endif
+
+#if 0
+    /* a bowtie */
+    { ART_MOVETO, 100, 100 },
+    { ART_LINETO, 400, 400 },
+    { ART_LINETO, 400, 100 },
+    { ART_LINETO, 100, 400 },
+    { ART_LINETO, 100, 100 },
+#endif
+
+#if 1
+    /* a square */
+    { ART_MOVETO, 100, 100 },
+    { ART_LINETO, 100, 400 },
+    { ART_LINETO, 400, 400 },
+    { ART_LINETO, 400, 100 },
+    { ART_LINETO, 100, 100 },
+#endif
+
+#if 1
+    /* another square */
+#define XOFF 10
+#define YOFF 10
+    { ART_MOVETO, 100 + XOFF, 100 + YOFF },
+    { ART_LINETO, 100 + XOFF, 400 + YOFF },
+    { ART_LINETO, 400 + XOFF, 400 + YOFF },
+    { ART_LINETO, 400 + XOFF, 100 + YOFF },
+    { ART_LINETO, 100 + XOFF, 100 + YOFF },
+#endif
+
+    { ART_END, 0, 0}
+  };
+  ArtSVP *svp, *svp2;
+  ArtSvpWriter *swr;
+
+  svp = art_svp_from_vpath (vpath);
+
+#define RUN_INTERSECT
+#ifdef RUN_INTERSECT
+  swr = art_svp_writer_rewind_new (ART_WIND_RULE_ODDEVEN);
+  art_svp_intersector (svp, swr);
+
+  svp2 = art_svp_writer_rewind_reap (swr);
+#endif
+
+#if 0
+  output_svp_ppm (svp2);
+#else
+  print_svp (svp2);
+#endif
+
+  art_svp_free (svp);
+
+#ifdef RUN_INTERSECT
+  art_svp_free (svp2);
+#endif
+}
+
+static void
+usage (void)
+{
+  fprintf (stderr, "usage: testart <test>\n"
+"  where <test> is one of:\n"
+"  testpat    -- make random star + gradients test pattern\n"
+"  gradient   -- test pattern for rendered gradients\n"
+"  dash       -- dash test (output is valid PostScript)\n"
+"  dist       -- distance test\n"
+"  intersect  -- softball test for intersector\n");
+  exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+  if (argc < 2)
+    usage ();
+
+  if (!strcmp (argv[1], "testpat"))
+    make_testpat ();
+  else if (!strcmp (argv[1], "gradient"))
+    test_gradient ();
+  else if (!strcmp (argv[1], "dist"))
+    test_dist ();
+  else if (!strcmp (argv[1], "dash"))
+    test_dash ();
+  else if (!strcmp (argv[1], "intersect"))
+    test_intersect ();
+  else
+    usage ();
+  return 0;
+}
diff --git a/libraries/libart_lgpl-2.3.7/testuta.c b/libraries/libart_lgpl-2.3.7/testuta.c
new file mode 100644 (file)
index 0000000..54fe95c
--- /dev/null
@@ -0,0 +1,228 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "art_misc.h"
+#include "art_uta.h"
+#include "art_vpath.h"
+#include "art_uta_vpath.h"
+#include "art_rect.h"
+#include "art_rect_uta.h"
+#include "art_uta_rect.h"
+
+#define TEST_UTA
+#define noTEST_UTA_SPEED
+
+#define XOFF 50
+#define YOFF 700
+
+static void
+print_uta_ps (ArtUta *uta)
+{
+  int x, y;
+  int x0, y0, x1, y1;
+  int width = uta->width;
+  ArtUtaBbox ub;
+
+  for (y = 0; y < uta->height; y++)
+    for (x = 0; x < width; x++)
+      {
+       ub = uta->utiles[y * width + x];
+       if (ub != 0)
+         {
+           x0 = (uta->x0 + x) * ART_UTILE_SIZE + ART_UTA_BBOX_X0(ub);
+           x1 = (uta->x0 + x) * ART_UTILE_SIZE + ART_UTA_BBOX_X1(ub);
+           y0 = (uta->y0 + y) * ART_UTILE_SIZE + ART_UTA_BBOX_Y0(ub);
+           y1 = (uta->y0 + y) * ART_UTILE_SIZE + ART_UTA_BBOX_Y1(ub);
+           printf ("%% tile %d, %d: %d %d %d %d\n",
+                   x, y,
+                   ART_UTA_BBOX_X0(ub),
+                   ART_UTA_BBOX_Y0(ub),
+                   ART_UTA_BBOX_X1(ub),
+                   ART_UTA_BBOX_Y1(ub));
+           printf ("%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
+                   XOFF + x0, YOFF - y0, XOFF + x1, YOFF - y0,
+                   XOFF + x1, YOFF - y1, XOFF + x0, YOFF - y1);
+         }
+      }
+}
+
+static void
+print_rbuf_ps (int *rbuf, int width, int height)
+{
+  int x, y;
+
+  for (y = 0; y < height; y++)
+    for (x = 0; x < width; x++)
+      if (1 && rbuf[y * width + x] != 0)
+       printf ("%d %d moveto (%d) show\n", x * ART_UTILE_SIZE, y * ART_UTILE_SIZE,
+               rbuf[y * width + x]);   
+}
+
+#if 0
+void
+randline (ArtUta *uta, int *rbuf, int rbuf_rowstride)
+{
+  double x0, y0, x1, y1;
+
+  x0 = rand () * (500.0 / RAND_MAX);
+  y0 = rand () * (500.0 / RAND_MAX);
+  x1 = rand () * (500.0 / RAND_MAX);
+  y1 = rand () * (500.0 / RAND_MAX);
+
+  printf ("%g %g moveto %g %g lineto stroke\n", x0, y0, x1, y1);
+  art_uta_add_line (uta, x0, y0, x1, y1, rbuf, rbuf_rowstride);
+}
+#endif
+
+static void
+print_ps_vpath (ArtVpath *vpath)
+{
+  int i;
+
+  for (i = 0; vpath[i].code != ART_END; i++)
+    {
+      switch (vpath[i].code)
+       {
+       case ART_MOVETO:
+         printf ("%g %g moveto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
+         break;
+       case ART_LINETO:
+         printf ("%g %g lineto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
+         break;
+       default:
+         break;
+       }
+    }
+  printf ("stroke\n");
+}
+
+static ArtVpath *
+randstar (int n)
+{
+  ArtVpath *vec;
+  int i;
+  double r, th;
+
+  vec = art_new (ArtVpath, n + 2);
+  for (i = 0; i < n; i++)
+    {
+      vec[i].code = i ? ART_LINETO : ART_MOVETO;
+      r = rand () * (250.0 / RAND_MAX);
+      th = i * 2 * M_PI / n;
+      vec[i].x = 250 + r * cos (th);
+      vec[i].y = 250 - r * sin (th);
+    }
+  vec[i].code = ART_LINETO;
+  vec[i].x = vec[0].x;
+  vec[i].y = vec[0].y;
+  i++;
+  vec[i].code = ART_END;
+  vec[i].x = 0;
+  vec[i].y = 0;
+  return vec;
+}
+
+int
+main (int argc, char **argv)
+{
+  ArtUta *uta;
+  int i;
+  int *rbuf;
+  ArtVpath *vec;
+  ArtIRect *rects;
+  int n_rects;
+
+  if (argc == 2)
+    srand (atoi (argv[1]));
+
+#ifdef TEST_UTA
+  printf ("%%!PS-Adobe\n");
+  printf ("/Helvetica findfont 12 scalefont setfont\n");
+  printf ("0.5 setlinewidth\n");
+
+  printf ("0.5 setgray\n");
+  for (i = 0; i < 500; i += ART_UTILE_SIZE)
+    {
+      printf ("%d %d moveto %d %d lineto stroke\n",
+             XOFF, YOFF - i, XOFF + 500, YOFF - i);
+      printf ("%d %d moveto %d %d lineto stroke\n",
+             XOFF + i, YOFF, XOFF + i, YOFF - 500);
+    }
+
+  printf ("/a {\n");
+
+#if 1
+  vec = randstar (50);
+  print_ps_vpath (vec);
+  uta = art_uta_from_vpath (vec);
+#ifdef TEST_UTA_RECT
+  {
+    ArtIRect bbox = {5, 5, 450, 450};
+    uta = art_uta_from_irect (&bbox);
+  }
+#endif
+  rbuf = 0;
+#else
+  uta = art_uta_new_coords (0, 0, 500, 500);
+
+  rbuf = malloc (sizeof(int) * (500 >> ART_UTILE_SHIFT) * (500 >> ART_UTILE_SHIFT));
+  for (i = 0; i < 10; i++)
+    randline (uta, rbuf, 500 >> ART_UTILE_SHIFT);
+#endif
+
+  printf ("} def 1 0.5 0.5 setrgbcolor\n");
+
+  print_uta_ps (uta);
+
+  printf ("0 0 0.5 setrgbcolor\n");
+
+  if (rbuf)
+    print_rbuf_ps (rbuf, 500 >> ART_UTILE_SHIFT, 500 >> ART_UTILE_SHIFT);
+
+  printf ("0 setgray a\n");
+
+  rects = art_rect_list_from_uta (uta, 256, 64, &n_rects);
+
+  printf ("%% %d rectangles:\n0 0 1 setrgbcolor\n", n_rects);
+
+  for (i = 0; i < n_rects; i++)
+    printf ("%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath stroke\n",
+           XOFF + rects[i].x0, YOFF - rects[i].y0,
+           XOFF + rects[i].x1, YOFF - rects[i].y0,
+           XOFF + rects[i].x1, YOFF - rects[i].y1,
+           XOFF + rects[i].x0, YOFF - rects[i].y1);
+
+  printf ("showpage\n");
+#endif
+
+#ifdef TEST_UTA_SPEED
+  for (i = 0; i < 1000; i++)
+    {
+      vec = randstar (50);
+      uta = art_uta_from_vpath (vec);
+      art_free (vec);
+      art_uta_free (uta);
+    }
+#endif
+
+  return 0;
+}
diff --git a/libraries/libpng-1.2.0-import.txt b/libraries/libpng-1.2.0-import.txt
new file mode 100644 (file)
index 0000000..5db34b8
--- /dev/null
@@ -0,0 +1,4 @@
+cd libpng-1.2.0/
+rm -rf contrib/ projects/ scripts/ configure
+
+---- create Makefile.am
diff --git a/libraries/libpng-1.2.0/ANNOUNCE b/libraries/libpng-1.2.0/ANNOUNCE
new file mode 100644 (file)
index 0000000..c8cd5cc
--- /dev/null
@@ -0,0 +1,32 @@
+
+Libpng 1.2.0 - September 1, 2001
+
+This is a public release of libpng, intended for use in production codes.
+
+Changes since the last public release (1.0.12):
+
+  Enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED
+    by default.
+  Added runtime selection of MMX features.
+  Added png_set_strip_error_numbers function and related macros.
+  Enabled user memory function by default.
+  Increased png_mng_features flag from png_byte to png_uint_32.
+  Bumped shared-library (so-number) and dll-number to 3.
+  Updated makefile.ibmc, makefile.gcmmx
+  Added some typecasts to eliminate gcc 3.0 warnings.  Changed prototypes
+     of png_write_oFFS width and height from png_uint_32 to png_int_32.
+  Updated example.c
+  Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c
+  Revised pnggccrd.c to conditionally compile some thread-unsafe code only
+     when PNG_THREAD_UNSAFE_OK is defined.
+  Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with
+     value exceeding 2^bit_depth-1
+  Removed restriction that do_invert_mono only operate on 1-bit opaque files
+  Replaced calls to fprintf(stderr,...) with png_warning() or png_debug()
+     in pnggccrd.c
+  Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC().
+
+Send comments/corrections/commendations to
+png-implement@ccrc.wustl.edu or to randeg@alum.rpi.edu
+
+Glenn R-P
diff --git a/libraries/libpng-1.2.0/CHANGES b/libraries/libpng-1.2.0/CHANGES
new file mode 100644 (file)
index 0000000..fb6bc37
--- /dev/null
@@ -0,0 +1,987 @@
+
+CHANGES - changes for libpng
+
+version 0.2
+  added reader into png.h
+  fixed small problems in stub file
+version 0.3
+  added pull reader
+  split up pngwrite.c to several files
+  added pnglib.txt
+  added example.c
+  cleaned up writer, adding a few new tranformations
+  fixed some bugs in writer
+  interfaced with zlib 0.5
+  added K&R support
+  added check for 64 KB blocks for 16 bit machines
+version 0.4
+  cleaned up code and commented code
+  simplified time handling into png_time
+  created png_color_16 and png_color_8 to handle color needs
+  cleaned up color type defines
+  fixed various bugs
+  made various names more consistant
+  interfaced with zlib 0.71
+  cleaned up zTXt reader and writer (using zlib's Reset functions)
+  split transformations into pngrtran.c and pngwtran.c
+version 0.5
+  interfaced with zlib 0.8
+  fixed many reading and writing bugs
+  saved using 3 spaces instead of tabs
+version 0.6
+  added png_large_malloc() and png_large_free()
+  added png_size_t
+  cleaned up some compiler warnings
+  added png_start_read_image()
+version 0.7
+  cleaned up lots of bugs
+  finished dithering and other stuff
+  added test program
+  changed name from pnglib to libpng
+version 0.71 [June, 1995]
+  changed pngtest.png for zlib 0.93
+  fixed error in libpng.txt and example.c
+version 0.8
+  cleaned up some bugs
+  added png_set_filler()
+  split up pngstub.c into pngmem.c, pngio.c, and pngerror.c
+  added #define's to remove unwanted code
+  moved png_info_init() to png.c
+  added old_size into png_realloc()
+  added functions to manually set filtering and compression info
+  changed compression parameters based on image type
+  optimized filter selection code
+  added version info
+  changed external functions passing floats to doubles (k&r problems?)
+  put all the configurable stuff in pngconf.h
+  enabled png_set_shift to work with paletted images on read
+  added png_read_update_info() - updates info structure with
+     transformations
+version 0.81 [August, 1995]
+  incorporated Tim Wegner's medium model code (thanks, Tim)
+version 0.82 [September, 1995]
+  [unspecified changes]
+version 0.85 [December, 1995]
+  added more medium model code (almost everything's a far)
+  added i/o, error, and memory callback functions
+  fixed some bugs (16 bit, 4 bit interlaced, etc.)
+  added first run progressive reader (barely tested)
+version 0.86 [January, 1996]
+  fixed bugs
+  improved documentation
+version 0.87 [January, 1996]
+  fixed medium model bugs
+  fixed other bugs introduced in 0.85 and 0.86
+  added some minor documentation
+version 0.88 [January, 1996]
+  fixed progressive bugs
+  replaced tabs with spaces
+  cleaned up documentation
+  added callbacks for read/write and warning/error functions
+version 0.89 [July, 1996]
+  added new initialization API to make libpng work better with shared libs
+     we now have png_create_read_struct(), png_create_write_struct(),
+     png_create_info_struct(), png_destroy_read_struct(), and
+     png_destroy_write_struct() instead of the separate calls to
+     malloc and png_read_init(), png_info_init(), and png_write_init()
+  changed warning/error callback functions to fix bug - this means you
+     should use the new initialization API if you were using the old
+     png_set_message_fn() calls, and that the old API no longer exists
+     so that people are aware that they need to change their code
+  changed filter selection API to allow selection of multiple filters
+     since it didn't work in previous versions of libpng anyways
+  optimized filter selection code
+  fixed png_set_background() to allow using an arbitrary RGB color for
+     paletted images
+  fixed gamma and background correction for paletted images, so
+     png_correct_palette is not needed unless you are correcting an
+     external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED
+     in pngconf.h) - if nobody uses this, it may disappear in the future.
+  fixed bug with Borland 64K memory allocation (Alexander Lehmann)
+  fixed bug in interlace handling (Smarasderagd, I think)
+  added more error checking for writing and image to reduce invalid files
+  separated read and write functions so that they won't both be linked
+     into a binary when only reading or writing functionality is used
+  new pngtest image also has interlacing and zTXt
+  updated documentation to reflect new API
+version 0.90 [January, 1997]
+  made CRC errors/warnings on critical and ancillary chunks configurable
+  libpng will use the zlib CRC routines by (compile-time) default
+  changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner)
+  added external C++ wrapper statements to png.h (Gilles Dauphin)
+  allow PNG file to be read when some or all of file signature has already
+     been read from the beginning of the stream.  ****This affects the size
+     of info_struct and invalidates all programs that use a shared libpng****
+  fixed png_filler() declarations
+  fixed? background color conversions
+  fixed order of error function pointers to match documentation
+  current chunk name is now available in png_struct to reduce the number
+     of nearly identical error messages (will simplify multi-lingual
+     support when available)
+  try to get ready for unknown-chunk callback functions:
+     - previously read critical chunks are flagged, so the chunk handling
+       routines can determine if the chunk is in the right place
+     - all chunk handling routines have the same prototypes, so we will
+       be able to handle all chunks via a callback mechanism
+  try to fix Linux "setjmp" buffer size problems
+  removed png_large_malloc, png_large_free, and png_realloc functions.
+version 0.95 [March, 1997]
+  fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never
+  fixed bug in PNG file signature compares when start != 0
+  changed parameter type of png_set_filler(...filler...) from png_byte
+     to png_uint_32
+  added test for MACOS to ensure that both math.h and fp.h are not #included
+  added macros for libpng to be compiled as a Windows DLL (Andreas Kupries)
+  added "packswap" transformation, which changes the endianness of
+     packed-pixel bytes (Kevin Bracey)
+  added "strip_alpha" transformation, which removes the alpha channel of
+     input images without using it (not neccesarily a good idea)
+  added "swap_alpha" transformation, which puts the alpha channel in front
+     of the color bytes instead of after
+  removed all implicit variable tests which assume NULL == 0 (I think)
+  changed several variables to "png_size_t" to show 16/32-bit limitations
+  added new pCAL chunk read/write support
+  added experimental filter selection weighting (Greg Roelofs)
+  removed old png_set_rgbx() and png_set_xrgb() functions that have been
+     obsolete for about 2 years now (use png_set_filler() instead)
+  added macros to read 16- and 32-bit ints directly from buffer, to be
+     used only on those systems that support it (namely PowerPC and 680x0)
+     With some testing, this may become the default for MACOS/PPC systems.
+  only calculate CRC on data if we are going to use it
+  added macros for zTXt compression type PNG_zTXt_COMPRESSION_???
+  added macros for simple libpng debugging output selectable at compile time
+  removed PNG_READ_END_MODE in progressive reader (Smarasderagd)
+  more description of info_struct in libpng.txt and png.h
+  more instructions in example.c
+  more chunk types tested in pngtest.c
+  renamed pngrcb.c to pngset.c, and all png_read_<chunk> functions to be
+     png_set_<chunk>.  We now have corresponding png_get_<chunk>
+     functions in pngget.c to get infomation in info_ptr.  This isolates
+     the application from the internal organization of png_info_struct
+     (good for shared library implementations).
+version 0.96 [May, 1997]
+  fixed serious bug with < 8bpp images introduced in 0.95
+  fixed 256-color transparency bug (Greg Roelofs)
+  fixed up documentation (Greg Roelofs, Laszlo Nyul)
+  fixed "error" in pngconf.h for Linux setjmp() behaviour
+  fixed DOS medium model support (Tim Wegner)
+  fixed png_check_keyword() for case with error in static string text
+  added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul)
+  added typecasts to quiet compiler errors
+  added more debugging info
+version 0.97 [January, 1998]
+  removed PNG_USE_OWN_CRC capability
+  relocated png_set_crc_action from pngrutil.c to pngrtran.c
+  fixed typecasts of "new_key", etc. (Andreas Dilger)
+  added RFC 1152 [sic] date support
+  fixed bug in gamma handling of 4-bit grayscale
+  added 2-bit grayscale gamma handling (Glenn R-P)
+  added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P)
+  minor corrections in libpng.txt
+  added simple sRGB support (Glenn R-P)
+  easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED;
+     all configurable options can be selected from command-line instead
+     of having to edit pngconf.h (Glenn R-P)
+  fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P)
+  added more conditions for png_do_background, to avoid changing
+     black pixels to background when a background is supplied and
+     no pixels are transparent
+  repaired PNG_NO_STDIO behaviour
+  tested NODIV support and made it default behaviour (Greg Roelofs)
+  added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler)
+  regularized version numbering scheme and bumped shared-library major
+     version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs)
+version 0.98 [January, 1998]
+  cleaned up some typos in libpng.txt and in code documentation
+  fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler)
+  cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c
+  changed recommendation about file_gamma for PC images to .51 from .45,
+     in example.c and libpng.txt, added comments to distinguish between
+     screen_gamma, viewing_gamma, and display_gamma.
+  changed all references to RFC1152 to read RFC1123 and changed the
+     PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED
+  added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent)
+  changed srgb_intent from png_byte to int to avoid compiler bugs
+version 0.99 [January 30, 1998]
+  free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler)
+  fixed a longstanding "packswap" bug in pngtrans.c
+  fixed some inconsistencies in pngconf.h that prevented compiling with
+     PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined
+  fixed some typos and made other minor rearrangement of libpng.txt (Andreas)
+  changed recommendation about file_gamma for PC images to .50 from .51 in
+     example.c and libpng.txt, and changed file_gamma for sRGB images to .45
+  added a number of functions to access information from the png structure
+     png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit)
+  added TARGET_MACOS similar to zlib-1.0.8
+  define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined
+  added type casting to all png_malloc() function calls
+version 0.99a [January 31, 1998]
+  Added type casts and parentheses to all returns that return a value.(Tim W.)
+version 0.99b [February 4, 1998]
+  Added type cast png_uint_32 on malloc function calls where needed.
+  Changed type of num_hist from png_uint_32 to int (same as num_palette).
+  Added checks for rowbytes overflow, in case png_size_t is less than 32 bits.
+  Renamed makefile.elf to makefile.lnx.
+version 0.99c [February 7, 1998]
+  More type casting.  Removed erroneous overflow test in pngmem.c.
+  Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes.
+  Added UNIX manual pages libpng.3 (incorporating libpng.txt) and  png.5.
+version 0.99d [February 11, 1998]
+  Renamed "far_to_near()" "png_far_to_near()"
+  Revised libpng.3
+  Version 99c "buffered" operations didn't work as intended.  Replaced them
+    with png_memcpy_check() and png_memset_check().
+  Added many "if (png_ptr == NULL) return" to quell compiler warnings about
+    unused png_ptr, mostly in pngget.c and pngset.c.
+  Check for overlength tRNS chunk present when indexed-color PLTE is read.
+  Cleaned up spelling errors in libpng.3/libpng.txt
+  Corrected a problem with png_get_tRNS() which returned undefined trans array
+version 0.99e [February 28, 1998]
+  Corrected png_get_tRNS() again.
+  Add parentheses for easier reading of pngget.c, fixed "||" should be "&&".
+  Touched up example.c to make more of it compileable, although the entire
+    file still can't be compiled (Willem van Schaik)
+  Fixed a bug in png_do_shift() (Bryan Tsai)
+  Added a space in png.h prototype for png_write_chunk_start()
+  Replaced pngtest.png with one created with zlib 1.1.1
+  Changed pngtest to report PASS even when file size is different (Jean-loup G.)
+  Corrected some logic errors in png_do_invert_alpha() (Chris Patterson)
+version 0.99f [March 5, 1998]
+  Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey)
+  Moved makefiles into a "scripts" directory, and added INSTALL instruction file
+  Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok)
+  Added pointers to "note on libpng versions" in makefile.lnx and README
+  Added row callback feature when reading and writing nonprogressive rows
+     and added a test of this feature in pngtest.c
+  Added user transform callbacks, with test of the feature in pngtest.c
+version 0.99g [March 6, 1998, morning]
+  Minor changes to pngtest.c to suppress compiler warnings.
+  Removed "beta" language from documentation.
+version 0.99h [March 6, 1998, evening]
+  Minor changes to previous minor changes to pngtest.c
+  Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED
+  and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro
+  Added user transform capability
+version 1.00 [March 7, 1998]
+  Changed several typedefs in pngrutil.c
+  Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik)
+  replaced "while(1)" with "for(;;)"
+  added PNGARG() to prototypes in pngtest.c and removed some prototypes
+  updated some of the makefiles (Tom Lane)
+  changed some typedefs (s_start, etc.) in pngrutil.c
+  fixed dimensions of "short_months" array in pngwrite.c
+  Replaced ansi2knr.c with the one from jpeg-v6
+version 1.0.0 [March 8, 1998]
+  Changed name from 1.00 to 1.0.0 (Adam Costello)
+  Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert)
+version 1.0.0a [March 9, 1998]
+  Fixed three bugs in pngrtran.c to make gamma+background handling consistent
+  (Greg Roelofs)
+  Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz
+  for major, minor, and bugfix releases.  This is 10001. (Adam Costello,
+  Tom Lane)
+  Make months range from 1-12 in png_convert_to_rfc1123
+version 1.0.0b [March 13, 1998]
+  Quieted compiler complaints about two empty "for" loops in pngrutil.c
+  Minor changes to makefile.s2x
+  Removed #ifdef/#endif around a png_free() in pngread.c
+version 1.0.1 [March 14, 1998]
+  Changed makefile.s2x to reduce security risk of using a relative pathname
+  Fixed some typos in the documentation (Greg).
+  Fixed a problem with value of "channels" returned by png_read_update_info()
+version 1.0.1a [April 21, 1998]
+  Optimized Paeth calculations by replacing abs() function calls with intrinsics
+  plus other loop optimizations. Improves avg decoding speed by about 20%.
+  Commented out i386istic "align" compiler flags in makefile.lnx.
+  Reduced the default warning level in some makefiles, to make them consistent.
+  Removed references to IJG and JPEG in the ansi2knr.c copyright statement.
+  Fixed a bug in png_do_strip_filler with XXRRGGBB => RRGGBB transformation.
+  Added grayscale and 16-bit capability to png_do_read_filler().
+  Fixed a bug in pngset.c, introduced in version 0.99c, that sets rowbytes
+    too large when writing an image with bit_depth < 8 (Bob Dellaca).
+  Corrected some bugs in the experimental weighted filtering heuristics.
+  Moved a misplaced pngrutil code block that truncates tRNS if it has more
+    than num_palette entries -- test was done before num_palette was defined.
+  Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins).
+  Changed compiler flags in makefile.wat for better optimization (Pawel Mrochen).
+version 1.0.1b [May 2, 1998]
+  Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg).
+  Relocated the png_composite macros from pngrtran.c to png.h (Greg).
+  Added makefile.sco (contributed by Mike Hopkirk).
+  Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a.
+  Fixed a bug in pngrtran.c that would set channels=5 under some circumstances.
+  More work on the Paeth-filtering, achieving imperceptible speedup (A Kleinert).
+  More work on loop optimization which may help when compiled with C++ compilers.
+  Added warnings when people try to use transforms they've defined out.
+  Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran.
+  Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg)
+version 1.0.1c [May 11, 1998]
+  Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for
+    filler bytes should have been 0xff instead of 0xf.
+  Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images.
+  Moved PNG_WRITE_WEIGHTED_FILTER_SUPPORTED and PNG_WRITE_FLUSH_SUPPORTED
+    out of the PNG_WRITE_TRANSFORMS_NOT_SUPPORTED block of pngconf.h
+  Added "PNG_NO_WRITE_TRANSFORMS" etc., as alternatives for *_NOT_SUPPORTED,
+    for consistency, in pngconf.h
+  Added individual "ifndef PNG_NO_[CAPABILITY]" in pngconf.h to make it easier
+    to remove unwanted capabilities via the compile line
+  Made some corrections to grammar (which, it's) in documentation (Greg).
+  Corrected example.c, use of row_pointers in png_write_image().
+version 1.0.1d [May 24, 1998]
+  Corrected several statements that used side effects illegally in pngrutil.c
+    and pngtrans.c, that were introduced in version 1.0.1b
+  Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert)
+  More corrections to example.c, use of row_pointers in png_write_image()
+    and png_read_rows().
+  Added pngdll.mak and pngdef.pas to scripts directory, contributed by
+    Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5
+  Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.)
+  Changed several loops from count-down to count-up, for consistency.
+version 1.0.1e [June 6, 1998]
+  Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and
+    added warnings when people try to set png_read_fn and png_write_fn in
+    the same structure.
+  Added a test such that png_do_gamma will be done when num_trans==0
+    for truecolor images that have defined a background.  This corrects an
+    error that was introduced in libpng-0.90 that can cause gamma processing
+    to be skipped.
+  Added tests in png.h to include "trans" and "trans_values" in structures
+    when PNG_READ_BACKGROUND_SUPPORTED or PNG_READ_EXPAND_SUPPORTED is defined.
+  Add png_free(png_ptr->time_buffer) in png_destroy_read_struct()
+  Moved png_convert_to_rfc_1123() from pngwrite.c to png.c
+  Added capability for user-provided malloc_fn() and free_fn() functions,
+    and revised pngtest.c to demonstrate their use, replacing the
+    PNGTEST_DEBUG_MEM feature.
+  Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner).
+version 1.0.2 [June 14, 1998]
+  Fixed two bugs in makefile.bor .
+version 1.0.2a [December 30, 1998]
+  Replaced and extended code that was removed from png_set_filler() in 1.0.1a.
+  Fixed a bug in png_do_filler() that made it fail to write filler bytes in
+    the left-most pixel of each row (Kevin Bracey).
+  Changed "static pngcharp tIME_string" to "static char tIME_string[30]"
+    in pngtest.c (Duncan Simpson).
+  Fixed a bug in pngtest.c that caused pngtest to try to write a tIME chunk
+    even when no tIME chunk was present in the source file.
+  Fixed a problem in pngrutil.c: gray_to_rgb didn't always work with 16-bit.
+  Fixed a problem in png_read_push_finish_row(), which would not skip some
+    passes that it should skip, for images that are less than 3 pixels high.
+  Interchanged the order of calls to png_do_swap() and png_do_shift()
+    in pngwtran.c (John Cromer).
+  Added #ifdef PNG_DEBUG/#endif surrounding use of PNG_DEBUG in png.h .
+  Changed "bad adaptive filter type" from error to warning in pngrutil.c .
+  Fixed a documentation error about default filtering with 8-bit indexed-color.
+  Separated the PNG_NO_STDIO macro into PNG_NO_STDIO and PNG_NO_CONSOLE_IO
+    (L. Peter Deutsch).
+  Added png_set_rgb_to_gray() and png_get_rgb_to_gray_status() functions.
+  Added png_get_copyright() and png_get_header_version() functions.
+  Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c
+  Added information about debugging in libpng.txt and libpng.3 .
+  Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and makefile.sco.
+  Removed lines after Dynamic Dependencies" in makefile.aco .
+  Revised makefile.dec to make a shared library (Jeremie Petit).
+  Removed trailing blanks from all files.
+version 1.0.2a [January 6, 1999]
+  Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h
+  Added "if" tests to silence complaints about unused png_ptr in png.h and png.c
+  Changed "check_if_png" function in example.c to return true (nonzero) if PNG.
+  Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig()
+    which is obsolete.
+version 1.0.3 [January 14, 1999]
+  Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice)
+  Added a statement of Y2K compliance in png.h, libpng.3, and Y2KINFO.
+version 1.0.3a [August 12, 1999]
+  Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning
+     if an attempt is made to read an interlaced image when it's not supported.
+  Added check if png_ptr->trans is defined before freeing it in pngread.c
+  Modified the Y2K statement to include versions back to version 0.71
+  Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c
+  Modified makefile.wat (added -zp8 flag, ".symbolic", changed some comments)
+  Replaced leading blanks with tab characters in makefile.hux
+  Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents.
+  Changed (float)red and (float)green to (double)red, (double)green
+     in png_set_rgb_to_gray() to avoid "promotion" problems in AIX.
+  Fixed a bug in pngconf.h that omitted <stdio.h> when PNG_DEBUG==0 (K Bracey).
+  Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt).
+  Updated documentation to refer to the PNG-1.2 specification.
+  Removed ansi2knr.c and left pointers to the latest source for ansi2knr.c
+    in makefile.knr, INSTALL, and README (L. Peter Deutsch)
+  Fixed bugs in calculation of the length of rowbytes when adding alpha
+    channels to 16-bit images, in pngrtran.c (Chris Nokleberg)
+  Added function png_set_user_transform_info() to store user_transform_ptr,
+    user_depth, and user_channels into the png_struct, and a function
+    png_get_user_transform_ptr() to retrieve the pointer (Chris Nokleberg)
+  Added function png_set_empty_plte_permitted() to make libpng useable
+    in MNG applications.
+  Corrected the typedef for png_free_ptr in png.h (Jesse Jones).
+  Correct gamma with srgb is 45455 instead of 45000 in pngrutil.c, to be
+    consistent with PNG-1.2, and allow variance of 500 before complaining.
+  Added assembler code contributed by Intel in file pngvcrd.c and modified
+    makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, Gilles Vollant)
+  Changed "ln -s -f" to "ln -f -s" in the makefiles to make Solaris happy.
+  Added some aliases for png_set_expand() in pngrtran.c, namely
+    png_set_expand_PLTE(), png_set_expand_depth(), and png_set_expand_tRNS()
+    (Greg Roelofs, in "PNG: The Definitive Guide").
+  Added makefile.beo for BEOS on X86, contributed by Sander Stok.
+version 1.0.3b [August 26, 1999]
+  Replaced 2147483647L several places with PNG_MAX_UINT macro, defined in png.h
+  Changed leading blanks to tabs in all makefiles.
+  Define PNG_USE_PNGVCRD in makefile.w32, to get MMX assembler code.
+  Made alternate versions of  png_set_expand() in pngrtran.c, namely
+    png_set_gray_1_2_4_to_8, png_set_palette_to_rgb, and png_set_tRNS_to_alpha
+    (Greg Roelofs, in "PNG: The Definitive Guide").  Deleted the 1.0.3a aliases.
+  Relocated start of 'extern "C"' block in png.h so it doesn't include pngconf.h
+  Revised calculation of num_blocks in pngmem.c to avoid a potentially
+    negative shift distance, whose results are undefined in the C language.
+  Added a check in pngset.c to prevent writing multiple tIME chunks.
+  Added a check in pngwrite.c to detect invalid small window_bits sizes.
+version 1.0.3d [September 4, 1999]
+  Fixed type casting of igamma in pngrutil.c
+  Added new png_expand functions to scripts/pngdef.pas and pngos2.def
+  Added a demo read_user_transform_fn that examines the row filters in pngtest.c
+version 1.0.4 [September 24, 1999]
+  Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined
+  Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h
+  Made several minor corrections to pngtest.c
+  Renamed the makefiles with longer but more user friendly extensions.
+  Copied the PNG copyright and license to a separate LICENSE file.
+  Revised documentation, png.h, and example.c to remove reference to
+    "viewing_gamma" which no longer appears in the PNG specification.
+  Revised pngvcrd.c to use MMX code for interlacing only on the final pass.
+  Updated pngvcrd.c to use the faster C filter algorithms from libpng-1.0.1a
+  Split makefile.win32vc into two versions, makefile.vcawin32 (uses MMX
+    assembler code) and makefile.vcwin32 (doesn't).
+  Added a CPU timing report to pngtest.c (enabled by defining PNGTEST_TIMING)
+  Added a copy of pngnow.png to the distribution.
+version 1.0.4a [September 25, 1999]
+  Increase max_pixel_depth in pngrutil.c if a user transform needs it.
+  Changed several division operations to right-shifts in pngvcrd.c
+version 1.0.4b [September 30, 1999]
+  Added parentheses in line 3732 of pngvcrd.c
+  Added a comment in makefile.linux warning about buggy -O3 in pgcc 2.95.1
+version 1.0.4c [October 1, 1999]
+  Added a "png_check_version" function in png.c and pngtest.c that will generate
+    a helpful compiler error if an old png.h is found in the search path.
+  Changed type of png_user_transform_depth|channels from int to png_byte.
+version 1.0.4d [October 6, 1999]
+  Changed 0.45 to 0.45455 in png_set_sRGB()
+  Removed unused PLTE entries from pngnow.png
+  Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly.
+version 1.0.4e [October 10, 1999]
+  Fixed sign error in pngvcrd.c (Greg Roelofs)
+  Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P)
+version 1.0.4f [October 15, 1999]
+  Surrounded example.c code with #if 0 .. #endif to prevent people from
+    inadvertently trying to compile it.
+  Changed png_get_header_version() from a function to a macro in png.h
+  Added type casting mostly in pngrtran.c and pngwtran.c
+  Removed some pointless "ptr = NULL" in pngmem.c
+  Added a "contrib" directory containing the source code from Greg's book.
+version 1.0.5 [October 15, 1999]
+  Minor editing of the INSTALL and README files.
+version 1.0.5a [October 23, 1999]
+  Added contrib/pngsuite and contrib/pngminus (Willem van Schaik)
+  Fixed a typo in the png_set_sRGB() function call in example.c (Jan Nijtmans)
+  Further optimization and bugfix of pngvcrd.c
+  Revised pngset.c so that it does not allocate or free memory in the user's
+    text_ptr structure.  Instead, it makes its own copy.
+  Created separate write_end_info_struct in pngtest.c for a more severe test.
+  Added code in pngwrite.c to free info_ptr->text[i].key to stop a memory leak.
+version 1.0.5b [November 23, 1999]
+  Moved PNG_FLAG_HAVE_CHUNK_HEADER, PNG_FLAG_BACKGROUND_IS_GRAY and
+    PNG_FLAG_WROTE_tIME from flags to mode.
+  Added png_write_info_before_PLTE() function.
+  Fixed some typecasting in contrib/gregbook/*.c
+  Updated scripts/makevms.com and added makevms.com to contrib/gregbook
+    and contrib/pngminus (Martin Zinser)
+version 1.0.5c [November 26, 1999]
+  Moved png_get_header_version from png.h to png.c, to accomodate ansi2knr.
+  Removed all global arrays (according to PNG_NO_GLOBAL_ARRAYS macro), to
+    accomodate making DLL's: Moved usr_png_ver from global variable to function
+    png_get_header_ver() in png.c.  Moved png_sig to png_sig_bytes in png.c and
+    eliminated use of png_sig in pngwutil.c.  Moved the various png_CHNK arrays
+    into pngtypes.h.  Eliminated use of global png_pass arrays.  Declared the
+    png_CHNK and png_pass arrays to be "const".  Made the global arrays
+    available to applications (although none are used in libpng itself) when
+    PNG_NO_GLOBAL_ARRAYS is not defined or when PNG_GLOBAL_ARRAYS is defined.
+  Removed some extraneous "-I" from contrib/pngminus/makefile.std
+  Changed the PNG_sRGB_INTENT macros in png.h to be consistent with PNG-1.2.
+  Change PNG_SRGB_INTENT to PNG_sRGB_INTENT in libpng.txt and libpng.3
+version 1.0.5d [November 29, 1999]
+  Add type cast (png_const_charp) two places in png.c
+  Eliminated pngtypes.h; use macros instead to declare PNG_CHNK arrays.
+  Renamed "PNG_GLOBAL_ARRAYS" to "PNG_USE_GLOBAL_ARRAYS" and made available
+    to applications a macro "PNG_USE_LOCAL_ARRAYS".
+  #ifdef out all the new declarations when PNG_USE_GLOBAL_ARRAYS is defined.
+  Added PNG_EXPORT_VAR macro to accommodate making DLL's.
+version 1.0.5e [November 30, 1999]
+  Added iCCP, iTXt, and sPLT support; added "lang" member to the png_text
+    structure; refactored the inflate/deflate support to make adding new chunks
+    with trailing compressed parts easier in the future, and added new functions
+    png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP,
+    png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond).
+  NOTE: Applications that write text chunks MUST define png_text->lang
+    before calling png_set_text(). It must be set to NULL if you want to
+    write tEXt or zTXt chunks.  If you want your application to be able to
+    run with older versions of libpng, use
+
+      #ifdef PNG_iTXt_SUPPORTED
+         png_text[i].lang = NULL;
+      #endif
+
+  Changed png_get_oFFs() and png_set_oFFs() to use signed rather than unsigned
+    offsets (Eric S. Raymond).
+  Combined PNG_READ_cHNK_SUPPORTED and PNG_WRITE_cHNK_SUPPORTED macros into
+    PNG_cHNK_SUPPORTED and combined the three types of PNG_text_SUPPORTED
+    macros, leaving the separate macros also available.
+  Removed comments on #endifs at the end of many short, non-nested #if-blocks.
+version 1.0.5f [December 6, 1999]
+  Changed makefile.solaris to issue a warning about potential problems when
+    the ucb "ld" is in the path ahead of the ccs "ld".
+  Removed "- [date]" from the "synopsis" line in libpng.3 and libpngpf.3.
+  Added sCAL chunk support (Eric S. Raymond).
+version 1.0.5g [December 7, 1999]
+  Fixed "png_free_spallettes" typo in png.h
+  Added code to handle new chunks in pngpread.c
+  Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block
+  Added "translated_key" to png_text structure and png_write_iTXt().
+  Added code in pngwrite.c to work around a newly discovered zlib bug.
+version 1.0.5h [December 10, 1999]
+  NOTE: regarding the note for version 1.0.5e, the following must also
+    be included in your code:
+        png_text[i].translated_key = NULL;
+  Unknown chunk handling is now supported.
+  Option to eliminate all floating point support was added.  Some new
+    fixed-point functions such as png_set_gAMA_fixed() were added.
+  Expanded tabs and removed trailing blanks in source files.
+version 1.0.5i [December 13, 1999]
+  Added some type casts to silence compiler warnings.
+  Renamed "png_free_spalette" to "png_free_spalettes" for consistency.
+  Removed leading blanks from a #define in pngvcrd.c
+  Added some parameters to the new png_set_keep_unknown_chunks() function.
+  Added a test for up->location != 0 in the first instance of writing
+    unknown chunks in pngwrite.c
+  Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to
+    prevent recursion.
+  Added png_free_hIST() function.
+  Various patches to fix bugs in the sCAL and integer cHRM processing,
+    and to add some convenience macros for use with sCAL.
+version 1.0.5j [December 21, 1999]
+  Changed "unit" parameter of png_write_sCAL from png_byte to int, to work
+    around buggy compilers.
+  Added new type "png_fixed_point" for integers that hold float*100000 values
+  Restored backward compatibility of tEXt/zTXt chunk processing:
+    Restored the first four members of png_text to the same order as v.1.0.5d.
+    Added members "lang_key" and "itxt_length" to png_text struct.  Set
+    text_length=0 when "text" contains iTXt data.  Use the "compression"
+    member to distinguish among tEXt/zTXt/iTXt types.  Added
+    PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros.
+    The "Note" above, about backward incompatibility of libpng-1.0.5e, no
+    longer applies.
+  Fixed png_read|write_iTXt() to read|write parameters in the right order,
+    and to write the iTXt chunk after IDAT if it appears in the end_ptr.
+  Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs)
+  Reversed the order of trying to write floating-point and fixed-point gAMA.
+version 1.0.5k [December 27, 1999]
+  Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))"
+  Added png_handle_as_unknown() function (Glenn)
+  Added png_free_chunk_list() function and chunk_list and num_chunk_list members
+    of png_ptr.
+  Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE.
+  Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings
+    about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored)
+  Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR).
+  Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is.
+  Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP().
+version 1.0.5l [January 1, 2000]
+  Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr()
+    for setting a callback function to handle unknown chunks and for
+    retrieving the associated user pointer (Glenn).
+version 1.0.5m [January 7, 2000]
+  Added high-level functions png_read_png(), png_write_png(), png_free_pixels().
+version 1.0.5n [January 9, 2000]
+  Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its
+    own memory for info_ptr->palette.  This makes it safe for the calling
+    application to free its copy of the palette any time after it calls
+    png_set_PLTE().
+version 1.0.5o [January 20, 2000]
+  Cosmetic changes only (removed some trailing blanks and TABs)
+version 1.0.5p [January 31, 2000]
+  Renamed pngdll.mak to makefile.bd32
+  Cosmetic changes in pngtest.c
+version 1.0.5q [February 5, 2000]
+  Relocated the makefile.solaris warning about PATH problems.
+  Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg)
+  Revised makefile.gcmmx
+  Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros
+version 1.0.5r [February 7, 2000]
+  Removed superfluous prototype for png_get_itxt from png.h
+  Fixed a bug in pngrtran.c that improperly expanded the background color.
+  Return *num_text=0 from png_get_text() when appropriate, and fix documentation
+    of png_get_text() in libpng.txt/libpng.3.
+version 1.0.5s [February 18, 2000]
+  Added "png_jmp_env()" macro to pngconf.h, to help people migrate to the
+    new error handler that's planned for the next libpng release, and changed
+    example.c, pngtest.c, and contrib programs to use this macro.
+  Revised some of the DLL-export macros in pngconf.h (Greg Roelofs)
+  Fixed a bug in png_read_png() that caused it to fail to expand some images
+    that it should have expanded.
+  Fixed some mistakes in the unused and undocumented INCH_CONVERSIONS functions
+    in pngget.c
+  Changed the allocation of palette, history, and trans arrays back to
+    the version 1.0.5 method (linking instead of copying) which restores
+    backward compatibility with version 1.0.5.  Added some remarks about
+    that in example.c.  Added "free_me" member to info_ptr and png_ptr
+    and added png_free_data() function.
+  Updated makefile.linux and makefile.gccmmx to make directories conditionally.
+  Made cosmetic changes to pngasmrd.h
+  Added png_set_rows() and png_get_rows(), for use with png_read|write_png().
+  Modified png_read_png() to allocate info_ptr->row_pointers only if it
+    hasn't already been allocated.
+version 1.0.5t [March 4, 2000]
+  Changed png_jmp_env() migration aiding macro to png_jmpbuf().
+  Fixed "interlace" typo (should be "interlaced") in contrib/gregbook/read2-x.c
+  Fixed bug with use of PNG_BEFORE_IHDR bit in png_ptr->mode, introduced when
+    PNG_FLAG_HAVE_CHUNK_HEADER was moved into png_ptr->mode in version 1.0.5b
+  Files in contrib/gregbook were revised to use png_jmpbuf() and to select
+    a 24-bit visual if one is available, and to allow abbreviated options.
+  Files in contrib/pngminus were revised to use the png_jmpbuf() macro.
+  Removed spaces in makefile.linux and makefile.gcmmx, introduced in 1.0.5s
+version 1.0.5u [March 5, 2000]
+  Simplified the code that detects old png.h in png.c and pngtest.c
+  Renamed png_spalette (_p, _pp) to png_sPLT_t (_tp, _tpp)
+  Increased precision of rgb_to_gray calculations from 8 to 15 bits and
+    added png_set_rgb_to_gray_fixed() function.
+  Added makefile.bc32 (32-bit Borland C++, C mode)
+version 1.0.5v [March 11, 2000]
+  Added some parentheses to the png_jmpbuf macro definition.
+  Updated references to the zlib home page, which has moved to freesoftware.com.
+  Corrected bugs in documentation regarding png_read_row() and png_write_row().
+  Updated documentation of png_rgb_to_gray calculations in libpng.3/libpng.txt.
+  Renamed makefile.borland,turboc3 back to makefile.bor,tc3 as in version 1.0.3,
+    revised borland makefiles; added makefile.ibmvac3 and makefile.gcc (Cosmin)
+version 1.0.6 [March 20, 2000]
+  Minor revisions of makefile.bor, libpng.txt, and gregbook/rpng2-win.c
+  Added makefile.sggcc (SGI IRIX with gcc)
+version 1.0.6d [April 7, 2000]
+  Changed sprintf() to strcpy() in png_write_sCAL_s() to work without STDIO
+  Added data_length parameter to png_decompress_chunk() function
+  Revised documentation to remove reference to abandoned png_free_chnk functions
+  Fixed an error in png_rgb_to_gray_fixed()
+  Revised example.c, usage of png_destroy_write_struct().
+  Renamed makefile.ibmvac3 to makefile.ibmc, added libpng.icc IBM project file
+  Added a check for info_ptr->free_me&PNG_FREE_TEXT when freeing text in png.c
+  Simplify png_sig_bytes() function to remove use of non-ISO-C strdup().
+version 1.0.6e [April 9, 2000]
+  Added png_data_freer() function.
+  In the code that checks for over-length tRNS chunks, added check of
+    info_ptr->num_trans as well as png_ptr->num_trans (Matthias Benckmann)
+  Minor revisions of libpng.txt/libpng.3.
+  Check for existing data and free it if the free_me flag is set, in png_set_*()
+    and png_handle_*().
+  Only define PNG_WEIGHTED_FILTERS_SUPPORTED when PNG_FLOATING_POINT_SUPPORTED
+    is defined.
+  Changed several instances of PNG_NO_CONSOLE_ID to PNG_NO_STDIO in pngrutil.c
+    and mentioned the purposes of the two macros in libpng.txt/libpng.3.
+version 1.0.6f [April 14, 2000]
+  Revised png_set_iCCP() and png_set_rows() to avoid prematurely freeing data.
+  Add checks in png_set_text() for NULL members of the input text structure.
+  Revised libpng.txt/libpng.3.
+  Removed superfluous prototype for png_set_itxt from png.h
+  Removed "else" from pngread.c, after png_error(), and changed "0" to "length".
+  Changed several png_errors about malformed ancillary chunks to png_warnings.
+version 1.0.6g [April 24, 2000]
+  Added png_pass-* arrays to pnggccrd.c when PNG_USE_LOCAL_ARRAYS is defined.
+  Relocated paragraph about png_set_background() in libpng.3/libpng.txt
+    and other revisions (Matthias Benckmann)
+  Relocated info_ptr->free_me, png_ptr->free_me, and other info_ptr and
+    png_ptr members to restore binary compatibility with libpng-1.0.5
+    (breaks compatibility with libpng-1.0.6).
+version 1.0.6h [April 24, 2000]
+  Changed shared library so-number pattern from 2.x.y.z to xy.z (this builds
+    libpng.so.10 & libpng.so.10.6h instead of libpng.so.2 & libpng.so.2.1.0.6h)
+    This is a temporary change for test purposes.
+version 1.0.6i [May 2, 2000]
+  Rearranged some members at the end of png_info and png_struct, to put
+    unknown_chunks_num and free_me within the original size of the png_structs
+    and free_me, png_read_user_fn, and png_free_fn within the original png_info,
+    because some old applications allocate the structs directly instead of
+    using png_create_*().
+  Added documentation of user memory functions in libpng.txt/libpng.3
+  Modified png_read_png so that it will use user_allocated row_pointers
+    if present, unless free_me directs that it be freed, and added description
+    of the use of png_set_rows() and png_get_rows() in libpng.txt/libpng.3.
+  Added PNG_LEGACY_SUPPORTED macro, and #ifdef out all new (since version
+    1.00) members of png_struct and png_info, to regain binary compatibility
+    when you define this macro.  Capabilities lost in this event
+    are user transforms (new in version 1.0.0),the user transform pointer
+    (new in version 1.0.2), rgb_to_gray (new in 1.0.5), iCCP, sCAL, sPLT,
+    the high-level interface, and unknown chunks support (all new in 1.0.6).
+    This was necessary because of old applications that allocate the structs
+    directly as authors were instructed to do in libpng-0.88 and earlier,
+    instead of using png_create_*().
+  Added modes PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT which
+    can be used to detect codes that directly allocate the structs, and
+    code to check these modes in png_read_init() and png_write_init() and
+    generate a libpng error if the modes aren't set and PNG_LEGACY_SUPPORTED
+    was not defined.
+  Added makefile.intel and updated makefile.watcom (Pawel Mrochen)
+version 1.0.6j [May 3, 2000]
+  Overloaded png_read_init() and png_write_init() with macros that convert
+    calls to png_read_init_2() or png_write_init_2() that check the version
+    and structure sizes.
+version 1.0.7beta11 [May 7, 2000]
+  Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes
+    which are no longer used.
+  Eliminated the three new members of png_text when PNG_NO_iTXt_SUPPORTED
+    or PNG_LEGACY_SUPPORTED is defined.
+  Made PNG_NO_ITXT_SUPPORTED the default setting, to avoid memory overrun
+    when old applications fill the info_ptr->text structure directly.
+  Added PNGAPI macro, and added it to the definitions of all exported functions.
+  Relocated version macro definitions ahead of the includes of zlib.h and
+    pngconf.h in png.h.
+version 1.0.7beta12 [May 12, 2000]
+  Revised pngset.c to avoid a problem with expanding the png_debug macro.
+  Deleted some extraneous defines from pngconf.h
+  Made PNG_NO_CONSOLE_IO the default condition when PNG_BUILD_DLL is defined.
+  Use MSC _RPTn debugging instead of fprintf if _MSC_VER is defined.
+  Added png_access_version_number() function.
+  Check for mask&PNG_FREE_CHNK (for TEXT, SCAL, PCAL) in png_free_data().
+  Expanded libpng.3/libpng.txt information about png_data_freer().
+version 1.0.7beta14 [May 17, 2000] (beta13 was not published)
+  Changed pnggccrd.c and pngvcrd.c to handle bad adaptive filter types as
+    warnings instead of errors, as pngrutil.c does.
+  Set the PNG_INFO_IDAT valid flag in png_set_rows() so png_write_png()
+    will actually write IDATs.
+  Made the default PNG_USE_LOCAL_ARRAYS depend on PNG_DLL instead of WIN32.
+  Make png_free_data() ignore its final parameter except when freeing data
+    that can have multiple instances (text, sPLT, unknowns).
+  Fixed a new bug in png_set_rows().
+  Removed info_ptr->valid tests from png_free_data(), as in version 1.0.5.
+  Added png_set_invalid() function.
+  Fixed incorrect illustrations of png_destroy_write_struct() in example.c.
+version 1.0.7beta15 [May 30, 2000]
+  Revised the deliberately erroneous Linux setjmp code in pngconf.h to produce
+    fewer error messages.
+  Rearranged checks for Z_OK to check the most likely path first in pngpread.c
+    and pngwutil.c.
+  Added checks in pngtest.c for png_create_*() returning NULL, and mentioned
+    in libpng.txt/libpng.3 the need for applications to check this.
+  Changed names of png_default_*() functions in pngtest to pngtest_*().
+  Changed return type of png_get_x|y_offset_*() from png_uint_32 to png_int_32.
+  Fixed some bugs in the unused PNG_INCH_CONVERSIONS functions in pngget.c
+  Set each pointer to NULL after freeing it in png_free_data().
+  Worked around a problem in pngconf.h; AIX's strings.h defines an "index"
+    macro that conflicts with libpng's png_color_16.index. (Dimitri Papadapoulos)
+  Added "msvc" directory with MSVC++ project files (Simon-Pierre Cadieux).
+version 1.0.7beta16 [June 4, 2000]
+  Revised the workaround of AIX string.h "index" bug.
+  Added a check for overlength PLTE chunk in pngrutil.c.
+  Added PNG_NO_POINTER_INDEXING macro to use array-indexing instead of pointer
+    indexing in pngrutil.c and pngwutil.c to accommodate a buggy compiler.
+  Added a warning in png_decompress_chunk() when it runs out of data, e.g.
+    when it tries to read an erroneous PhotoShop iCCP chunk.
+  Added PNG_USE_DLL macro.
+  Revised the copyright/disclaimer/license notice.
+  Added contrib/msvctest directory
+version 1.0.7rc1 [June 9, 2000]
+  Corrected the definition of PNG_TRANSFORM_INVERT_ALPHA  (0x0400 not 0x0200)
+  Added contrib/visupng directory (Willem van Schaik)
+version 1.0.7beta18 [June 23, 2000]
+  Revised PNGAPI definition, and pngvcrd.c to work with __GCC__
+    and do not redefine PNGAPI if it is passed in via a compiler directive.
+  Revised visupng/PngFile.c to remove returns from within the Try block.
+  Removed leading underscores from "_PNG_H" and "_PNG_SAVE_BSD_SOURCE" macros.
+  Updated contrib/visupng/cexcept.h to version 1.0.0.
+  Fixed bugs in pngwrite.c and pngwutil.c that prevented writing iCCP chunks.
+version 1.0.7rc2 [June 28, 2000]
+  Updated license to include disclaimers required by UCITA.
+  Fixed "DJBPP" typo in pnggccrd.c introduced in beta18.
+version 1.0.7 [July 1, 2000]
+  Revised the definition of "trans_values" in libpng.3/libpng.txt
+version 1.0.8beta1 [July 8, 2000]
+  Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks.
+  Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and
+     pngwutil.c.
+  Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h.
+  Removed unused "#include <assert.h>" from png.c
+  Added WindowsCE support.
+  Revised pnggccrd.c to work with gcc-2.95.2 and in the Cygwin environment.
+version 1.0.8beta2 [July 10, 2000]
+  Added project files to the wince directory and made further revisions
+     of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE.
+version 1.0.8beta3 [July 11, 2000]
+  Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS()
+     for indexed-color input files to avoid potential double-freeing trans array
+     under some unusual conditions; problem was introduced in version 1.0.6f.
+  Further revisions to pngtest.c and files in the wince subdirectory.
+version 1.0.8beta4 [July 14, 2000]
+  Added the files pngbar.png and pngbar.jpg to the distribution.
+  Added makefile.cygwin, and cygwin support in pngconf.h
+  Added PNG_NO_ZALLOC_ZERO macro (makes png_zalloc skip zeroing memory)
+version 1.0.8rc1 [July 16, 2000]
+  Revised png_debug() macros and statements to eliminate compiler warnings.
+version 1.0.8 [July 24, 2000]
+  Added png_flush() in pngwrite.c, after png_write_IEND().
+  Updated makefile.hpux to build a shared library.
+version 1.0.9beta1 [November 10, 2000]
+  Fixed typo in scripts/makefile.hpux
+  Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser)
+  Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser)
+  Changed "cdrom.com" in documentation to "libpng.org"
+  Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg).
+  Changed type of "params" from voidp to png_voidp in png_read|write_png().
+  Make sure PNGAPI and PNG_IMPEXP are defined in pngconf.h.
+  Revised the 3 instances of WRITEFILE in pngtest.c.
+  Relocated "msvc" and "wince" project subdirectories into "dll" subdirectory.
+  Updated png.rc in dll/msvc project
+  Revised makefile.dec to define and use LIBPATH and INCPATH
+  Increased size of global png_libpng_ver[] array from 12 to 18 chars.
+  Made global png_libpng_ver[], png_sig[] and png_pass_*[] arrays const.
+  Removed duplicate png_crc_finish() from png_handle_bKGD() function.
+  Added a warning when application calls png_read_update_info() multiple times.
+  Revised makefile.cygwin
+  Fixed bugs in iCCP support in pngrutil.c and pngwutil.c.
+  Replaced png_set_empty_plte_permitted() with png_permit_mng_features().
+version 1.0.9beta2 [November 19, 2000]
+  Renamed the "dll" subdirectory "projects".
+  Added borland project files to "projects" subdirectory.
+  Set VS_FF_PRERELEASE and VS_FF_PATCHED flags in msvc/png.rc when appropriate.
+  Add error message in png_set_compression_buffer_size() when malloc fails.
+version 1.0.9beta3 [November 23, 2000]
+  Revised PNG_LIBPNG_BUILD_TYPE macro in png.h, used in the msvc project.
+  Removed the png_flush() in pngwrite.c that crashes some applications
+    that don't set png_output_flush_fn.
+  Added makefile.macosx and makefile.aix to scripts directory.
+version 1.0.9beta4 [December 1, 2000]
+  Change png_chunk_warning to png_warning in png_check_keyword().
+  Increased the first part of msg buffer from 16 to 18 in png_chunk_error().
+version 1.0.9beta5 [December 15, 2000]
+  Added support for filter method 64 (for PNG datastreams embedded in MNG).
+version 1.0.9beta6 [December 18, 2000]
+  Revised png_set_filter() to accept filter method 64 when appropriate.
+  Added new PNG_HAVE_PNG_SIGNATURE bit to png_ptr->mode and use it to
+    help prevent applications from using MNG features in PNG datastreams.
+  Added png_permit_mng_features() function.
+  Revised libpng.3/libpng.txt.  Changed "filter type" to "filter method".
+version 1.0.9rc1 [December 23, 2000]
+  Revised test for PNG_HAVE_PNG_SIGNATURE in pngrutil.c
+  Fixed error handling of unknown compression type in png_decompress_chunk().
+  In pngconf.h, define __cdecl when _MSC_VER is defined.
+version 1.0.9beta7 [December 28, 2000]
+  Changed PNG_TEXT_COMPRESSION_zTXt to PNG_COMPRESSION_TYPE_BASE several places.
+  Revised memory management in png_set_hIST and png_handle_hIST in a backward
+    compatible manner.  PLTE and tRNS were revised similarly.
+  Revised the iCCP chunk reader to ignore trailing garbage.
+version 1.0.9beta8 [January 12, 2001]
+  Moved pngasmrd.h into pngconf.h.
+  Improved handling of out-of-spec garbage iCCP chunks generated by PhotoShop.
+version 1.0.9beta9 [January 15, 2001]
+  Added png_set_invalid, png_permit_mng_features, and png_mmx_supported to
+    wince and msvc project module definition files.
+  Minor revision of makefile.cygwin.
+  Fixed bug with progressive reading of narrow interlaced images in pngpread.c
+version 1.0.9beta10 [January 16, 2001]
+  Do not typedef png_FILE_p in pngconf.h when PNG_NO_STDIO is defined.
+  Fixed "png_mmx_supported" typo in project definition files.
+version 1.0.9beta11 [January 19, 2001]
+  Updated makefile.sgi to make shared library.
+  Removed png_mmx_support() function and disabled PNG_MNG_FEATURES_SUPPORTED
+    by default, for the benefit of DLL forward compatibility.  These will
+    be re-enabled in version 1.2.0.
+version 1.0.9rc2 [January 22, 2001]
+  Revised cygwin support.
+version 1.0.9 [January 31, 2001]
+  Added check of cygwin's ALL_STATIC in pngconf.h
+  Added "-nommx" parameter to contrib/gregbook/rpng2-win and rpng2-x demos.
+version 1.0.10beta1 [March 14, 2001]
+  Revised makefile.dec, makefile.sgi, and makefile.sggcc; added makefile.hpgcc.
+  Reformatted libpng.3 to eliminate bad line breaks.
+  Added checks for _mmx_supported in the read_filter_row function of pnggccrd.c
+  Added prototype for png_mmx_support() near the top of pnggccrd.c
+  Moved some error checking from png_handle_IHDR to png_set_IHDR.
+  Added PNG_NO_READ_SUPPORTED and PNG_NO_WRITE_SUPPORTED macros.
+  Revised png_mmx_support() function in pnggccrd.c
+  Restored version 1.0.8 PNG_WRITE_EMPTY_PLTE_SUPPORTED behavior in pngwutil.c
+  Fixed memory leak in contrib/visupng/PngFile.c
+  Fixed bugs in png_combine_row() in pnggccrd.c and pngvcrd.c (C version)
+  Added warnings when retrieving or setting gamma=0.
+  Increased the first part of msg buffer from 16 to 18 in png_chunk_warning().
+version 1.0.10rc1 [March 23, 2001]
+  Changed all instances of memcpy, strcpy, and strlen to png_memcpy, png_strcpy,
+    and png_strlen.
+  Revised png_mmx_supported() function in pnggccrd.c to return proper value.
+  Fixed bug in progressive reading (pngpread.c) with small images (height < 8).
+version 1.0.10 [March 30, 2001]
+  Deleted extraneous space (introduced in 1.0.9) from line 42 of makefile.cygwin
+  Added beos project files (Chris Herborth)
+version 1.0.11beta1 [April 3, 2001]
+  Added type casts on several png_malloc() calls (Dimitri Papadapoulos).
+  Removed a no-longer needed AIX work-around from pngconf.h
+  Changed several "//" single-line comments to C-style in pnggccrd.c
+version 1.0.11beta2 [April 11, 2001]
+  Removed PNGAPI from several functions whose prototypes did not have PNGAPI.
+  Updated scripts/pngos2.def
+version 1.0.11beta3 [April 14, 2001]
+  Added checking the results of many instances of png_malloc() for NULL
+version 1.0.11beta4 [April 20, 2001]
+  Undid the changes from version 1.0.11beta3.  Added a check for NULL return
+    from user's malloc_fn().
+  Removed some useless type casts of the NULL pointer.
+  Added makefile.netbsd
+version 1.0.11 [April 27, 2001]
+  Revised makefile.netbsd
+version 1.0.12beta1 [May 14, 2001]
+  Test for Windows platform in pngconf.h when including malloc.h (Emmanuel Blot)
+  Updated makefile.cygwin and handling of Cygwin's ALL_STATIC in pngconf.h
+  Added some never-to-be-executed code in pnggccrd.c to quiet compiler warnings.
+  Eliminated the png_error about apps using png_read|write_init().  Instead,
+    libpng will reallocate the png_struct and info_struct if they are too small.
+    This retains future binary compatibility for old applications written for
+    libpng-0.88 and earlier.
+version 1.2.0beta1 [May 6, 2001]
+  Bumped DLLNUM to 2.
+  Re-enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED
+    by default.
+  Added runtime selection of MMX features.
+  Added png_set_strip_error_numbers function and related macros.
+version 1.2.0beta2 [May 7, 2001]
+  Finished merging 1.2.0beta1 with version 1.0.11
+  Added a check for attempts to read or write PLTE in grayscale PNG datastreams.
+version 1.2.0beta3 [May 17, 2001]
+  Enabled user memory function by default.
+  Modified png_create_struct so it passes user mem_ptr to user memory allocator.
+  Increased png_mng_features flag from png_byte to png_uint_32.
+  Bumped shared-library (so-number) and dll-number to 3.
+version 1.2.0beta4 [June 23, 2001]
+  Check for missing profile length field in iCCP chunk and free chunk_data
+     in case of truncated iCCP chunk.
+  Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc
+  Bumped dll-number from 2 to 3 in makefile.cygwin
+  Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly
+     if user attempts to run it on an 8-bit display.
+  Updated contrib/gregbook
+  Use png_malloc instead of png_zalloc to allocate palette in pngset.c
+  Updated makefile.ibmc
+  Added some typecasts to eliminate gcc 3.0 warnings.  Changed prototypes
+     of png_write_oFFS width and height from png_uint_32 to png_int_32.
+  Updated example.c
+  Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c
+version 1.2.0beta5 [August 8, 2001]
+  Revised contrib/gregbook
+  Revised makefile.gcmmx
+  Revised pnggccrd.c to conditionally compile some thread-unsafe code only
+     when PNG_THREAD_UNSAFE_OK is defined.
+  Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with
+     value exceeding 2^bit_depth-1
+  Revised makefile.sgi and makefile.sggcc
+  Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c
+  Removed restriction that do_invert_mono only operate on 1-bit opaque files
+version 1.2.0 [September 1, 2001]
+  Changed a png_warning() to png_debug() in pnggccrd.c
+  Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC().
+
+Send comments/corrections/commendations to
+png-implement@ccrc.wustl.edu or to randeg@alum.rpi.edu
+
+Glenn R-P
diff --git a/libraries/libpng-1.2.0/INSTALL b/libraries/libpng-1.2.0/INSTALL
new file mode 100644 (file)
index 0000000..4bac89c
--- /dev/null
@@ -0,0 +1,141 @@
+
+Installing libpng version 1.2.0 - September 1, 2001
+
+Before installing libpng, you must first install zlib.  zlib
+can usually be found wherever you got libpng.  zlib can be
+placed in another directory, at the same level as libpng.
+Note that your system might already have a preinstalled
+zlib, but you will still need to have access to the
+zlib.h and zconf.h include files that correspond to the
+version of zlib that's installed.
+
+You can rename the directories that you downloaded (they
+might be called "libpng-1.2.0" or "lpng109" and "zlib-1.1.3"
+or "zlib113") so that you have directories called "zlib" and "libpng".
+
+Your directory structure should look like this:
+
+   ..       (the parent directory)
+      libpng  (this directory)
+          INSTALL (this file)
+          README
+          *.h
+          *.c
+          contrib
+             gregbook
+             msvctest
+             pngminus
+             pngsuite
+             visupng
+          projects
+             beos
+             borland
+             msvc
+             netware.txt
+             wince.txt
+          scripts
+             makefile.*
+          pngtest.png
+          etc.
+      zlib
+          README
+          *.h
+          *.c
+          contrib
+          etc.
+
+If the line endings in the files look funny, you may wish to get the other
+distribution of libpng.  It is available in both tar.gz (UNIX style line
+endings) and zip (DOS style line endings) formats.
+
+If you are building libpng with MSVC, you can enter the libpng\msvc directory
+and follow the instructions in msvc\README.txt.
+
+You can build libpng for WindowsCE by entering the downloading and installing
+the libpng\wince directory as instructed in the projects\wince.txt file, and
+then following the instructions in the README* files.  Similarly, you can
+build libpng for Netware as instructed in projects\netware.txt.
+
+Else enter the zlib directory and follow the instructions in zlib/README,
+then come back here and choose the appropriate makefile.sys in the scripts
+directory.
+
+The files that are presently available in the scripts directory
+include
+
+ makefile.std      =>  Generic UNIX makefile (cc, creates static libpng.a)
+ makefile.linux    =>  Linux/ELF makefile (gcc, creates libpng.so.2.1.2.0)
+ makefile.gcmmx    =>  Linux/ELF makefile (gcc, creates libpng.so.2.1.2.0,
+                       uses assembler code tuned for Intel MMX platform)
+ makefile.gcc      =>  Generic makefile (gcc, creates static libpng.a)
+ makefile.knr      =>  Archaic UNIX Makefile that converts files with
+                       ansi2knr (Requires ansi2knr.c from
+                       ftp://ftp.cs.wisc.edu/ghost)
+ makefile.aix      =>  AIX makefile
+ makefile.cygwin   =>  Cygwin/gcc makefile
+ makefile.dec      =>  DEC Alpha UNIX makefile
+ makefile.hpgcc    =>  HPUX makefile using gcc
+ makefile.hpux     =>  HPUX (10.20 and 11.00) makefile
+ makefile.ibmc     =>  IBM C/C++ version 3.x for Win32 and OS/2 (static)
+ makefile.intel    =>  Intel C/C++ version 4.0 and later
+ libpng.icc        =>  Project file for IBM VisualAge/C++ version 4.0 or later
+ makefile.macosx   =>  MACOS X Makefile
+ makefile.netbsd   =>  NetBSD/cc makefile, uses PNGGCCRD
+ makefile.sgi      =>  Silicon Graphics IRIX makefile (cc, creates static lib)
+ makefile.sggcc    =>  Silicon Graphics (gcc, creates libpng.so.2.1.2.0)
+ makefile.sunos    =>  Sun makefile
+ makefile.solaris  =>  Solaris 2.X makefile (gcc, creates libpng.so.2.1.2.0)
+ makefile.sco      =>  For SCO OSr5  ELF and Unixware 7 with Native cc
+ makefile.mips     =>  MIPS makefile
+ makefile.acorn    =>  Acorn makefile
+ makefile.amiga    =>  Amiga makefile
+ smakefile.ppc     =>  AMIGA smakefile for SAS C V6.58/7.00 PPC compiler
+                       (Requires SCOPTIONS, copied from scripts/SCOPTIONS.ppc)
+ makefile.atari    =>  Atari makefile
+ makefile.beos     =>  BEOS makefile for X86
+ makefile.bor      =>  Borland makefile (uses bcc)
+ makefile.bc32     =>  32-bit Borland C++ (all modules compiled in C mode)
+ makefile.bd32     =>  To make a png32bd.dll with Borland C++ 4.5
+ makefile.tc3      =>  Turbo C 3.0 makefile
+ makefile.dj2      =>  DJGPP 2 makefile
+ makefile.msc      =>  Microsoft C makefile
+ makefile.vcawin32 =>  makefile for Microsoft Visual C++ 5.0 and later (uses
+                       assembler code tuned for Intel MMX platform)
+ makefile.vcwin32  =>  makefile for Microsoft Visual C++ 4.0 and later (does
+                       not use assembler code)
+ makefile.os2      =>  OS/2 Makefile (gcc and emx, requires pngos2.def)
+ pngos2.def        =>  OS/2 module definition file used by makefile.os2
+ makefile.watcom   =>  Watcom 10a+ Makefile, 32-bit flat memory model
+ makevms.com       =>  VMS build script
+ descrip.mms       =>  VMS makefile for MMS or MMK
+ pngdef.pas        =>  Defines for a png32bd.dll with Borland C++ 4.5
+ SCOPTIONS.ppc     =>  Used with smakefile.ppc
+
+Copy the file (or files) that you need from the
+scripts directory into this directory, for example
+
+   MSDOS example: copy scripts\makefile.msc makefile
+   UNIX example:    cp scripts/makefile.std makefile
+
+Read the makefile to see if you need to change any source or
+target directories to match your preferences.
+
+Then read pngconf.h to see if you want to make any configuration
+changes.
+
+Then just run "make test" which will create the libpng library in
+this directory and run a quick test that reads the "pngtest.png"
+file and writes a "pngout.png" file that should be identical to it.
+Look for "9782 zero samples" in the output of the test.  For more
+confidence, you can run another test by typing "pngtest pngnow.png"
+and looking for "289 zero samples" in the output.  Also, you can
+run "pngtest -m *.png" in the "contrib/pngsuite" directory and compare
+your output with the result shown in contrib/pngsuite/README.
+
+Most of the makefiles will allow you to run "make install" to
+put the library in its final resting place (if you want to
+do that, run "make install" in the zlib directory first if necessary).
+
+Further information can be found in the README and libpng.txt
+files, in the individual makefiles, in png.h, in the README files in
+subdirectories of the LIB directory, and the manual pages libpng.3 and png.5.
diff --git a/libraries/libpng-1.2.0/KNOWNBUG b/libraries/libpng-1.2.0/KNOWNBUG
new file mode 100644 (file)
index 0000000..7b0928c
--- /dev/null
@@ -0,0 +1,8 @@
+
+Known bugs in libpng-1.2.0
+
+1. April 22, 2001: pnggccrd.c has been reported to crash on NetBSD when
+   reading interlaced PNG files, when assembler code is enabled.
+
+   STATUS: Under investigation.
+
diff --git a/libraries/libpng-1.2.0/LICENSE b/libraries/libpng-1.2.0/LICENSE
new file mode 100644 (file)
index 0000000..1f4a8bc
--- /dev/null
@@ -0,0 +1,102 @@
+
+This copy of the libpng notices is provided for your convenience.  In case of
+any discrepancy between this copy and the notices in the file png.h that is
+included in the libpng distribution, the latter shall prevail.
+
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+If you modify libpng you may insert additional notices immediately following
+this sentence.
+
+libpng versions 1.0.7, July 1, 2000, through 1.2.0, September 1, 2001, are
+Copyright (c) 2000 Glenn Randers-Pehrson
+and are distributed according to the same disclaimer and license as libpng-1.0.6
+with the following individuals added to the list of Contributing Authors
+
+   Simon-Pierre Cadieux
+   Eric S. Raymond
+   Gilles Vollant
+
+and with the following additions to the disclaimer:
+
+   There is no warranty against interference with your enjoyment of the
+   library or against infringement.  There is no warranty that our
+   efforts or the library will fulfill any of your particular purposes
+   or needs.  This library is provided with all faults, and the entire
+   risk of satisfactory quality, performance, accuracy, and effort is with
+   the user.
+
+libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are
+distributed according to the same disclaimer and license as libpng-0.96,
+with the following individuals added to the list of Contributing Authors:
+
+   Tom Lane
+   Glenn Randers-Pehrson
+   Willem van Schaik
+
+libpng versions 0.89, June 1996, through 0.96, May 1997, are
+Copyright (c) 1996, 1997 Andreas Dilger
+Distributed according to the same disclaimer and license as libpng-0.88,
+with the following individuals added to the list of Contributing Authors:
+
+   John Bowler
+   Kevin Bracey
+   Sam Bushell
+   Magnus Holmgren
+   Greg Roelofs
+   Tom Tanner
+
+libpng versions 0.5, May 1995, through 0.88, January 1996, are
+Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+
+For the purposes of this copyright and license, "Contributing Authors"
+is defined as the following set of individuals:
+
+   Andreas Dilger
+   Dave Martindale
+   Guy Eric Schalnat
+   Paul Schmidt
+   Tim Wegner
+
+The PNG Reference Library is supplied "AS IS".  The Contributing Authors
+and Group 42, Inc. disclaim all warranties, expressed or implied,
+including, without limitation, the warranties of merchantability and of
+fitness for any purpose.  The Contributing Authors and Group 42, Inc.
+assume no liability for direct, indirect, incidental, special, exemplary,
+or consequential damages, which may result from the use of the PNG
+Reference Library, even if advised of the possibility of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, without fee, subject
+to the following restrictions:
+
+1. The origin of this source code must not be misrepresented.
+
+2. Altered versions must be plainly marked as such and must not
+   be misrepresented as being the original source.
+
+3. This Copyright notice may not be removed or altered from any
+   source or altered source distribution.
+
+The Contributing Authors and Group 42, Inc. specifically permit, without
+fee, and encourage the use of this source code as a component to
+supporting the PNG file format in commercial products.  If you use this
+source code in a product, acknowledgment is not required but would be
+appreciated.
+
+
+A "png_get_copyright" function is available, for convenient use in "about"
+boxes and the like:
+
+   printf("%s",png_get_copyright(NULL));
+
+Also, the PNG logo (in PNG format, of course) is supplied in the
+files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+
+Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is a
+certification mark of the Open Source Initiative.
+
+Glenn Randers-Pehrson
+randeg@alum.rpi.edu
+September 1, 2001
diff --git a/libraries/libpng-1.2.0/Makefile b/libraries/libpng-1.2.0/Makefile
new file mode 100644 (file)
index 0000000..5288f37
--- /dev/null
@@ -0,0 +1,375 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = ../..
+
+prefix = /usr/local/rrdtool-1.1.0
+exec_prefix = ${prefix}
+
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libexecdir = ${exec_prefix}/libexec
+datadir = ${prefix}/share
+sysconfdir = ${prefix}/etc
+sharedstatedir = ${prefix}/com
+localstatedir = ${prefix}/var
+libdir = ${exec_prefix}/lib
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/rrdtool
+pkglibdir = $(libdir)/rrdtool
+pkgincludedir = $(includedir)/rrdtool
+top_builddir = ../..
+
+ACLOCAL = ${SHELL} /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/missing --run aclocal
+AUTOCONF = ${SHELL} /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/missing --run autoconf
+AUTOMAKE = ${SHELL} /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/missing --run automake
+AUTOHEADER = ${SHELL} /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/missing --run autoheader
+
+INSTALL = /usr/sepp/bin/ginstall -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = s,x,x,
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = 
+host_triplet = sparc-sun-solaris2.8
+AMTAR = ${SHELL} /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/missing --run tar
+ART_LIB_DIR = libraries/libart_lgpl-2.3.7
+AS = @AS@
+AWK = gawk
+CC = gcc
+CGI_LIB_DIR = libraries/cgilib-0.4
+COMP_PERL = perl_piped perl_shared
+CPP = gcc -E
+DEPDIR = .deps
+DLLTOOL = @DLLTOOL@
+ECHO = /usr/ucb/echo
+EXEEXT = 
+FREETYPE_LIB_DIR = libraries/freetype-2.0.5
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LN_S = ln -s
+NROFF = /usr/sepp/bin/gnroff
+OBJDUMP = @OBJDUMP@
+OBJEXT = o
+PACKAGE = rrdtool
+PERL = /usr/bin/perl
+PERLFLAGS = 
+PERL_MAKE_OPTIONS = 
+PNG_LIB_DIR = libraries/libpng-1.2.0
+RANLIB = ranlib
+SO_EXT = so
+STRIP = strip
+TCL_LD_SEARCH_FLAGS = 
+TCL_PACKAGE_PATH = 
+TCL_PREFIX = 
+TCL_SHLIB_CFLAGS = 
+TCL_SHLIB_LD = 
+TCL_SHLIB_SUFFIX = 
+TROFF = /usr/sepp/bin/groff
+VERSION = 1.1.0
+ZLIB_CFLAGS = -g -O2 -Wall -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline  -fPIC
+am__include = include
+am__quote = 
+install_sh = /home/oetiker/data/projects/cvs-checkout/rrdtool/program/config/install-sh
+
+ZLIB_LIB_DIR = libraries/zlib-1.1.3
+
+INCLUDES = -I$(top_srcdir)/$(ZLIB_LIB_DIR)
+
+EXTRA_DIST = ANNOUNCE CHANGES INSTALL KNOWNBUG README README.rrdtool \
+            TODO Y2KINFO example.c libpng.3 \
+           libpng.txt libpngpf.3 png.5 png.dsp png.dsw 
+
+
+noinst_LTLIBRARIES = librrd_png.la
+
+librrd_png_la_SOURCES = \
+       png.c           \
+       pngerror.c      \
+       pngget.c        \
+       pngmem.c        \
+       pngpread.c      \
+       pngread.c       \
+       pngrio.c        \
+       pngrtran.c      \
+       pngrutil.c      \
+       pngset.c        \
+       pngtrans.c      \
+       pngwio.c        \
+       pngwrite.c      \
+       pngwtran.c      \
+       pngwutil.c      \
+       png.h      pngconf.h
+
+subdir = libraries/libpng-1.2.0
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+
+librrd_png_la_LDFLAGS =
+librrd_png_la_LIBADD =
+am_librrd_png_la_OBJECTS = png.lo pngerror.lo pngget.lo pngmem.lo \
+       pngpread.lo pngread.lo pngrio.lo pngrtran.lo pngrutil.lo \
+       pngset.lo pngtrans.lo pngwio.lo pngwrite.lo pngwtran.lo \
+       pngwutil.lo
+librrd_png_la_OBJECTS = $(am_librrd_png_la_OBJECTS)
+
+DEFS = -DHAVE_CONFIG_H
+DEFAULT_INCLUDES =  -I. -I$(srcdir) -I$(top_builddir)/config
+CPPFLAGS = 
+LDFLAGS = 
+LIBS = -lm 
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+DEP_FILES = $(DEPDIR)/png.Plo $(DEPDIR)/pngerror.Plo \
+       $(DEPDIR)/pngget.Plo $(DEPDIR)/pngmem.Plo \
+       $(DEPDIR)/pngpread.Plo $(DEPDIR)/pngread.Plo \
+       $(DEPDIR)/pngrio.Plo $(DEPDIR)/pngrtran.Plo \
+       $(DEPDIR)/pngrutil.Plo $(DEPDIR)/pngset.Plo \
+       $(DEPDIR)/pngtrans.Plo $(DEPDIR)/pngwio.Plo \
+       $(DEPDIR)/pngwrite.Plo $(DEPDIR)/pngwtran.Plo \
+       $(DEPDIR)/pngwutil.Plo
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
+       $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CFLAGS = -g -O2 -Wall -pedantic -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline  -fPIC
+DIST_SOURCES = $(librrd_png_la_SOURCES)
+DIST_COMMON = README INSTALL Makefile.am Makefile.in TODO
+SOURCES = $(librrd_png_la_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  libraries/libpng-1.2.0/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) && \
+         CONFIG_HEADERS= CONFIG_LINKS= \
+         CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+librrd_png.la: $(librrd_png_la_OBJECTS) $(librrd_png_la_DEPENDENCIES) 
+       $(LINK)  $(librrd_png_la_LDFLAGS) $(librrd_png_la_OBJECTS) $(librrd_png_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+       -rm -f *.tab.c
+
+include $(DEPDIR)/png.Plo
+include $(DEPDIR)/pngerror.Plo
+include $(DEPDIR)/pngget.Plo
+include $(DEPDIR)/pngmem.Plo
+include $(DEPDIR)/pngpread.Plo
+include $(DEPDIR)/pngread.Plo
+include $(DEPDIR)/pngrio.Plo
+include $(DEPDIR)/pngrtran.Plo
+include $(DEPDIR)/pngrutil.Plo
+include $(DEPDIR)/pngset.Plo
+include $(DEPDIR)/pngtrans.Plo
+include $(DEPDIR)/pngwio.Plo
+include $(DEPDIR)/pngwrite.Plo
+include $(DEPDIR)/pngwtran.Plo
+include $(DEPDIR)/pngwutil.Plo
+
+distclean-depend:
+       -rm -rf $(DEPDIR)
+
+.c.o:
+       source='$<' object='$@' libtool=no \
+       depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \
+       $(CCDEPMODE) $(depcomp) \
+       $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$<
+
+.c.obj:
+       source='$<' object='$@' libtool=no \
+       depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \
+       $(CCDEPMODE) $(depcomp) \
+       $(COMPILE) -c `cygpath -w $<`
+
+.c.lo:
+       source='$<' object='$@' libtool=yes \
+       depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' \
+       $(CCDEPMODE) $(depcomp) \
+       $(LTCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+CCDEPMODE = depmode=gcc
+uninstall-info-am:
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || etags $(ETAGS_ARGS) $$tags  $$unique $(LISP)
+
+GTAGS:
+       here=`CDPATH=: && cd $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           $(mkinstalldirs) "$(distdir)/$$dir"; \
+         fi; \
+         if test -d $$d/$$file; then \
+           cp -pR $$d/$$file $(distdir) \
+           || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+
+installdirs:
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+       mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+       distclean-generic distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+uninstall-am: uninstall-info-am
+
+.PHONY: GTAGS all all-am check check-am clean clean-generic \
+       clean-libtool clean-noinstLTLIBRARIES distclean \
+       distclean-compile distclean-depend distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am info \
+       info-am install install-am install-data install-data-am \
+       install-exec install-exec-am install-info install-info-am \
+       install-man install-strip installcheck installcheck-am \
+       installdirs maintainer-clean maintainer-clean-generic \
+       mostlyclean mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool tags uninstall uninstall-am \
+       uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libraries/libpng-1.2.0/Makefile.am b/libraries/libpng-1.2.0/Makefile.am
new file mode 100644 (file)
index 0000000..457f674
--- /dev/null
@@ -0,0 +1,29 @@
+## Process this file with automake to produce Makefile.in
+
+ZLIB_LIB_DIR = @ZLIB_LIB_DIR@
+
+INCLUDES = -I$(top_srcdir)/$(ZLIB_LIB_DIR)
+
+EXTRA_DIST= ANNOUNCE CHANGES INSTALL KNOWNBUG README README.rrdtool \
+            TODO Y2KINFO example.c libpng.3 \
+           libpng.txt libpngpf.3 png.5 png.dsp png.dsw 
+
+noinst_LTLIBRARIES = librrd_png.la
+
+librrd_png_la_SOURCES =        \
+       png.c           \
+       pngerror.c      \
+       pngget.c        \
+       pngmem.c        \
+       pngpread.c      \
+       pngread.c       \
+       pngrio.c        \
+       pngrtran.c      \
+       pngrutil.c      \
+       pngset.c        \
+       pngtrans.c      \
+       pngwio.c        \
+       pngwrite.c      \
+       pngwtran.c      \
+       pngwutil.c      \
+       png.h      pngconf.h
diff --git a/libraries/libpng-1.2.0/Makefile.in b/libraries/libpng-1.2.0/Makefile.in
new file mode 100644 (file)
index 0000000..5a364b0
--- /dev/null
@@ -0,0 +1,375 @@
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AMTAR = @AMTAR@
+ART_LIB_DIR = @ART_LIB_DIR@
+AS = @AS@
+AWK = @AWK@
+CC = @CC@
+CGI_LIB_DIR = @CGI_LIB_DIR@
+COMP_PERL = @COMP_PERL@
+CPP = @CPP@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+ECHO = @ECHO@
+EXEEXT = @EXEEXT@
+FREETYPE_LIB_DIR = @FREETYPE_LIB_DIR@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+NROFF = @NROFF@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PERL = @PERL@
+PERLFLAGS = @PERLFLAGS@
+PERL_MAKE_OPTIONS = @PERL_MAKE_OPTIONS@
+PNG_LIB_DIR = @PNG_LIB_DIR@
+RANLIB = @RANLIB@
+SO_EXT = @SO_EXT@
+STRIP = @STRIP@
+TCL_LD_SEARCH_FLAGS = @TCL_LD_SEARCH_FLAGS@
+TCL_PACKAGE_PATH = @TCL_PACKAGE_PATH@
+TCL_PREFIX = @TCL_PREFIX@
+TCL_SHLIB_CFLAGS = @TCL_SHLIB_CFLAGS@
+TCL_SHLIB_LD = @TCL_SHLIB_LD@
+TCL_SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@
+TROFF = @TROFF@
+VERSION = @VERSION@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+am__include = @am__include@
+am__quote = @am__quote@
+install_sh = @install_sh@
+
+ZLIB_LIB_DIR = @ZLIB_LIB_DIR@
+
+INCLUDES = -I$(top_srcdir)/$(ZLIB_LIB_DIR)
+
+EXTRA_DIST = ANNOUNCE CHANGES INSTALL KNOWNBUG README README.rrdtool \
+            TODO Y2KINFO example.c libpng.3 \
+           libpng.txt libpngpf.3 png.5 png.dsp png.dsw 
+
+
+noinst_LTLIBRARIES = librrd_png.la
+
+librrd_png_la_SOURCES = \
+       png.c           \
+       pngerror.c      \
+       pngget.c        \
+       pngmem.c        \
+       pngpread.c      \
+       pngread.c       \
+       pngrio.c        \
+       pngrtran.c      \
+       pngrutil.c      \
+       pngset.c        \
+       pngtrans.c      \
+       pngwio.c        \
+       pngwrite.c      \
+       pngwtran.c      \
+       pngwutil.c      \
+       png.h      pngconf.h
+
+subdir = libraries/libpng-1.2.0
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+
+librrd_png_la_LDFLAGS =
+librrd_png_la_LIBADD =
+am_librrd_png_la_OBJECTS = png.lo pngerror.lo pngget.lo pngmem.lo \
+       pngpread.lo pngread.lo pngrio.lo pngrtran.lo pngrutil.lo \
+       pngset.lo pngtrans.lo pngwio.lo pngwrite.lo pngwtran.lo \
+       pngwutil.lo
+librrd_png_la_OBJECTS = $(am_librrd_png_la_OBJECTS)
+
+DEFS = @DEFS@
+DEFAULT_INCLUDES =  -I. -I$(srcdir) -I$(top_builddir)/config
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+@AMDEP_TRUE@DEP_FILES = $(DEPDIR)/png.Plo $(DEPDIR)/pngerror.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/pngget.Plo $(DEPDIR)/pngmem.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/pngpread.Plo $(DEPDIR)/pngread.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/pngrio.Plo $(DEPDIR)/pngrtran.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/pngrutil.Plo $(DEPDIR)/pngset.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/pngtrans.Plo $(DEPDIR)/pngwio.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/pngwrite.Plo $(DEPDIR)/pngwtran.Plo \
+@AMDEP_TRUE@   $(DEPDIR)/pngwutil.Plo
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
+       $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+DIST_SOURCES = $(librrd_png_la_SOURCES)
+DIST_COMMON = README INSTALL Makefile.am Makefile.in TODO
+SOURCES = $(librrd_png_la_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  libraries/libpng-1.2.0/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) && \
+         CONFIG_HEADERS= CONFIG_LINKS= \
+         CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+librrd_png.la: $(librrd_png_la_OBJECTS) $(librrd_png_la_DEPENDENCIES) 
+       $(LINK)  $(librrd_png_la_LDFLAGS) $(librrd_png_la_OBJECTS) $(librrd_png_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/png.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngerror.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngmem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngpread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngrio.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngrtran.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngrutil.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngset.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngtrans.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngwio.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngwrite.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngwtran.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pngwutil.Plo@am__quote@
+
+distclean-depend:
+       -rm -rf $(DEPDIR)
+
+.c.o:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$<
+
+.c.obj:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(COMPILE) -c `cygpath -w $<`
+
+.c.lo:
+@AMDEP_TRUE@   source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@   depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@   $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(LTCOMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+CCDEPMODE = @CCDEPMODE@
+uninstall-info-am:
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || etags $(ETAGS_ARGS) $$tags  $$unique $(LISP)
+
+GTAGS:
+       here=`CDPATH=: && cd $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         if test -f $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           $(mkinstalldirs) "$(distdir)/$$dir"; \
+         fi; \
+         if test -d $$d/$$file; then \
+           cp -pR $$d/$$file $(distdir) \
+           || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+
+installdirs:
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+       mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+       distclean-generic distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+uninstall-am: uninstall-info-am
+
+.PHONY: GTAGS all all-am check check-am clean clean-generic \
+       clean-libtool clean-noinstLTLIBRARIES distclean \
+       distclean-compile distclean-depend distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am info \
+       info-am install install-am install-data install-data-am \
+       install-exec install-exec-am install-info install-info-am \
+       install-man install-strip installcheck installcheck-am \
+       installdirs maintainer-clean maintainer-clean-generic \
+       mostlyclean mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool tags uninstall uninstall-am \
+       uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libraries/libpng-1.2.0/README b/libraries/libpng-1.2.0/README
new file mode 100644 (file)
index 0000000..06f9278
--- /dev/null
@@ -0,0 +1,251 @@
+README for libpng 1.2.0 - September 1, 2001 (shared library 2.1)
+See the note about version numbers near the top of png.h
+
+See INSTALL for instructions on how to install libpng.
+
+Libpng comes in two distribution formats.  Get libpng-*.tar.gz if you
+want UNIX-style line endings in the text files, or lpng*.zip if you want
+DOS-style line endings.
+
+Version 0.89 was the first official release of libpng.  Don't let the
+fact that it's the first release fool you.  The libpng library has been in
+extensive use and testing since mid-1995.  By late 1997 it had
+finally gotten to the stage where there hadn't been significant
+changes to the API in some time, and people have a bad feeling about
+libraries with versions < 1.0.  Version 1.0.0 was released in
+March 1998.
+
+****
+Note that some of the changes to the png_info structure render this
+version of the library binary incompatible with libpng-0.89 or
+earlier versions if you are using a shared library.  The type of the
+"filler" parameter for png_set_filler() has changed from png_byte to
+png_uint_32, which will affect shared-library applications that use
+this function.
+
+To avoid problems with changes to the internals of png_info_struct,
+new APIs have been made available in 0.95 to avoid direct application
+access to info_ptr.  These functions are the png_set_<chunk> and
+png_get_<chunk> functions.  These functions should be used when
+accessing/storing the info_struct data, rather than manipulating it
+directly, to avoid such problems in the future.
+
+It is important to note that the APIs do not make current programs
+that access the info struct directly incompatible with the new
+library.  However, it is strongly suggested that new programs use
+the new APIs (as shown in example.c and pngtest.c), and older programs
+be converted to the new format, to facilitate upgrades in the future.
+****
+
+Additions since 0.90 include the ability to compile libpng as a
+Windows DLL, and new APIs for accessing data in the info struct.
+Experimental functions include the ability to set weighting and cost
+factors for row filter selection, direct reads of integers from buffers
+on big-endian processors that support misaligned data access, faster
+methods of doing alpha composition, and more accurate 16->8 bit color
+conversion.
+
+The additions since 0.89 include the ability to read from a PNG stream
+which has had some (or all) of the signature bytes read by the calling
+application.  This also allows the reading of embedded PNG streams that
+do not have the PNG file signature.  As well, it is now possible to set
+the library action on the detection of chunk CRC errors.  It is possible
+to set different actions based on whether the CRC error occurred in a
+critical or an ancillary chunk.
+
+The changes made to the library, and bugs fixed are based on discussions
+on the PNG implementation mailing list <png-implement@ccrc.wustl.edu>
+and not on material submitted privately to Guy, Andreas, or Glenn.  They will
+forward any good suggestions to the list.
+
+For a detailed description on using libpng, read libpng.txt.  For
+examples of libpng in a program, see example.c and pngtest.c.  For usage
+information and restrictions (what little they are) on libpng, see
+png.h.  For a description on using zlib (the compression library used by
+libpng) and zlib's restrictions, see zlib.h
+
+I have included a general makefile, as well as several machine and
+compiler specific ones, but you may have to modify one for your own needs.
+
+You should use zlib 1.0.4 or later to run this, but it MAY work with
+versions as old as zlib 0.95.  Even so, there are bugs in older zlib
+versions which can cause the output of invalid compression streams for
+some images.  You will definitely need zlib 1.0.4 or later if you are
+taking advantage of the MS-DOS "far" structure allocation for the small
+and medium memory models.  You should also note that zlib is a
+compression library that is useful for more things than just PNG files.
+You can use zlib as a drop-in replacement for fread() and fwrite() if
+you are so inclined.
+
+zlib should be available at the same place that libpng is.
+If not, it should be at ftp.uu.net in /graphics/png
+Eventually, it will be at ftp.uu.net in /pub/archiving/zip/zlib
+
+You may also want a copy of the PNG specification.  It is available
+as an RFC and a W3C Recommendation.  Failing
+these resources you can try ftp.uu.net in the /graphics/png directory.
+
+This code is currently being archived at ftp.uu.net in the
+/graphics/png directory, and on CompuServe, Lib 20 (PNG SUPPORT)
+at GO GRAPHSUP.  If you can't find it in any of those places,
+e-mail me, and I'll help you find it.
+
+If you have any code changes, requests, problems, etc., please e-mail
+them to me.  Also, I'd appreciate any make files or project files,
+and any modifications you needed to make to get libpng to compile,
+along with a #define variable to tell what compiler/system you are on.
+If you needed to add transformations to libpng, or wish libpng would
+provide the image in a different way, drop me a note (and code, if
+possible), so I can consider supporting the transformation.
+Finally, if you get any warning messages when compiling libpng
+(note: not zlib), and they are easy to fix, I'd appreciate the
+fix.  Please mention "libpng" somewhere in the subject line.  Thanks.
+
+This release was created and will be supported by myself (of course
+based in a large way on Guy's and Andreas' earlier work), and the PNG group.
+
+randeg@alum.rpi.edu
+png-implement@ccrc.wustl.edu
+
+You can't reach Guy, the original libpng author, at the addresses
+given in previous versions of this document.  He and Andreas will read mail
+addressed to the png-implement list, however.
+
+Please do not send general questions about PNG.  Send them to
+the address in the specification (png-group@w3.org).  At the same
+time, please do not send libpng questions to that address, send them to me
+or to png-implement@ccrc.wustl.edu.  I'll
+get them in the end anyway.  If you have a question about something
+in the PNG specification that is related to using libpng, send it
+to me.  Send me any questions that start with "I was using libpng,
+and ...".  If in doubt, send questions to me.  I'll bounce them
+to others, if necessary.
+
+Please do not send suggestions on how to change PNG.  We have
+been discussing PNG for three years now, and it is official and
+finished.  If you have suggestions for libpng, however, I'll
+gladly listen.  Even if your suggestion is not used for version
+1.0, it may be used later.
+
+Files in this distribution:
+
+      ANNOUNCE      =>  Announcement of this version, with recent changes
+      CHANGES       =>  Description of changes between libpng versions
+      KNOWNBUG      =>  List of known bugs and deficiencies
+      LICENSE       =>  License to use and redistribute libpng
+      README        =>  This file
+      TODO          =>  Things not implemented in the current library
+      Y2KINFO       =>  Statement of Y2K compliance
+      example.c     =>  Example code for using libpng functions
+      libpng.3      =>  manual page for libpng (includes libpng.txt)
+      libpng.txt    =>  Description of libpng and its functions
+      libpngpf.3    =>  manual page for libpng's private functions
+      png.5         =>  manual page for the PNG format
+      png.c         =>  Basic interface functions common to library
+      png.h         =>  Library function and interface declarations
+      pngconf.h     =>  System specific library configuration
+      pngasmrd.h    =>  Header file for assembler-coded functions
+      pngerror.c    =>  Error/warning message I/O functions
+      pngget.c      =>  Functions for retrieving info from struct
+      pngmem.c      =>  Memory handling functions
+      pngbar.png    =>  PNG logo, 88x31
+      pngnow.png    =>  PNG logo, 98x31
+      pngpread.c    =>  Progressive reading functions
+      pngread.c     =>  Read data/helper high-level functions
+      pngrio.c      =>  Lowest-level data read I/O functions
+      pngrtran.c    =>  Read data transformation functions
+      pngrutil.c    =>  Read data utility functions
+      pngset.c      =>  Functions for storing data into the info_struct
+      pngtest.c     =>  Library test program
+      pngtest.png   =>  Library test sample image
+      pngtrans.c    =>  Common data transformation functions
+      pngwio.c      =>  Lowest-level write I/O functions
+      pngwrite.c    =>  High-level write functions
+      pngwtran.c    =>  Write data transformations
+      pngwutil.c    =>  Write utility functions
+      contrib       =>  Contributions
+       gregbook         =>  source code for PNG reading and writing, from
+                            Greg Roelofs' "PNG: The Definitive Guide",
+                            O'Reilly, 1999
+       msvctest     =>  Builds and runs pngtest using a MSVC workspace
+       pngminus     =>  Simple pnm2png and png2pnm programs
+       pngsuite     =>  Test images
+       visupng      =>  Contains a MSVC workspace for VisualPng
+      projects      =>  Contains project files and workspaces for building DLL
+       beos             =>  Contains a Beos workspace for building libpng
+       borland          =>  Contains a Borland workspace for building libpng
+                            and zlib
+       msvc             =>  Contains a Microsoft Visual C++ (MSVC) workspace
+                            for building libpng and zlib
+       netware.txt      =>  Contains instructions for downloading a set of
+                            project files for building libpng and zlib on
+                            Netware.
+       wince.txt        =>  Contains instructions for downloading a Microsoft
+                            Visual C++ (Windows CD Toolkit) workspace for
+                            building libpng and zlib on WindowsCE
+      scripts       =>  Directory containing scripts for building libpng:
+       descrip.mms      =>  VMS makefile for MMS or MMK
+       makefile.std     =>  Generic UNIX makefile (cc, creates static libpng.a)
+       makefile.linux   =>  Linux/ELF makefile
+                            (gcc, creates libpng.so.2.1.2.0)
+       makefile.gcmmx   =>  Linux/ELF makefile (gcc, creates
+                            libpng.so.2.1.2.0, uses assembler code
+                            tuned for Intel MMX platform)
+       makefile.gcc     =>  Generic makefile (gcc, creates static libpng.a)
+       makefile.knr     =>  Archaic UNIX Makefile that converts files with
+                            ansi2knr (Requires ansi2knr.c from
+                            ftp://ftp.cs.wisc.edu/ghost)
+       makefile.aix     =>  AIX makefile
+       makefile.cygwin  =>  Cygwin/gcc makefile
+       makefile.dec     =>  DEC Alpha UNIX makefile
+       makefile.hpgcc   =>  HPUX makefile using gcc
+       makefile.hpux    =>  HPUX (10.20 and 11.00) makefile
+       makefile.ibmc    =>  IBM C/C++ version 3.x for Win32 and OS/2 (static)
+       makefile.intel   =>  Intel C/C++ version 4.0 and later
+       libpng.icc       =>  Project file, IBM VisualAge/C++ 4.0 or later
+       makefile.macosx  =>  MACOS X Makefile
+       makefile.netbsd  =>  NetBSD/cc makefile, uses PNGGCCRD
+       makefile.sgi     =>  Silicon Graphics IRIX (cc, creates static lib)
+       makefile.sggcc   =>  Silicon Graphics (gcc, creates libpng.so.2.1.2.0)
+       makefile.sunos   =>  Sun makefile
+       makefile.solaris =>  Solaris 2.X makefile
+                            (gcc, creates libpng.so.2.1.2.0)
+       makefile.sco     =>  For SCO OSr5  ELF and Unixware 7 with Native cc
+       makefile.mips    =>  MIPS makefile
+       makefile.acorn   =>  Acorn makefile
+       makefile.amiga   =>  Amiga makefile
+       smakefile.ppc    =>  AMIGA smakefile for SAS C V6.58/7.00 PPC
+                            compiler (Requires SCOPTIONS, copied from
+                            scripts/SCOPTIONS.ppc)
+       makefile.atari   =>  Atari makefile
+       makefile.beos    =>  BEOS makefile for X86
+       makefile.bor     =>  Borland makefile (uses bcc)
+       makefile.bc32    =>  32-bit Borland C++ (all modules compiled in C mode)
+       makefile.bd32    =>  To make a png32bd.dll with Borland C++ 4.5
+       makefile.tc3     =>  Turbo C 3.0 makefile
+       makefile.dj2     =>  DJGPP 2 makefile
+       makefile.msc     =>  Microsoft C makefile
+       makefile.vcawin32 => makefile for Microsoft Visual C++ 5.0 and
+                            later (uses assembler code tuned for Intel MMX
+                            platform)
+       makefile.vcwin32 =>  makefile for Microsoft Visual C++ 4.0 and
+                            later (does not use assembler code)
+       makefile.os2     =>  OS/2 Makefile (gcc and emx, requires pngos2.def)
+       pngos2.def       =>  OS/2 module definition file used by makefile.os2
+       makefile.watcom  =>  Watcom 10a+ Makefile, 32-bit flat memory model
+       makevms.com      =>  VMS build script
+       pngdef.pas       =>  Defines for a png32bd.dll with Borland C++ 4.5
+       SCOPTIONS.ppc    =>  Used with smakefile.ppc
+
+Good luck, and happy coding.
+
+-Glenn Randers-Pehrson
+ Internet: randeg@alum.rpi.edu
+
+-Andreas Eric Dilger
+ Internet: adilger@enel.ucalgary.ca
+ Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/
+
+-Guy Eric Schalnat
+ (formerly of Group 42, Inc)
+ Internet: gschal@infinet.com
diff --git a/libraries/libpng-1.2.0/TODO b/libraries/libpng-1.2.0/TODO
new file mode 100644 (file)
index 0000000..a5f6395
--- /dev/null
@@ -0,0 +1,24 @@
+TODO - list of things to do for libpng:
+
+Final bug fixes.
+Improve API by hiding the png_struct and png_info structs.
+Finish work on the no-floating-point version (including gamma compensation)
+Better C++ wrapper/full C++ implementation?
+Fix problem with C++ and EXTERN "C".
+cHRM transformation.
+Improve setjmp/longjmp usage or remove it in favor of returning error codes.
+Add "grayscale->palette" transformation and "palette->grayscale" detection.
+Improved dithering.
+Multi-lingual error and warning message support.
+Complete sRGB transformation (presently it simply uses gamma=0.45455).
+Man pages for function calls.
+Better documentation.
+Better filter selection
+   (counting huffman bits/precompression?  filter inertia?  filter costs?).
+Histogram creation.
+Text conversion between different code pages (Latin-1 -> Mac and DOS).
+Should we always malloc 2^bit_depth PLTE/tRNS/hIST entries for safety?
+Build gamma tables using fixed point (and do away with floating point entirely).
+Use greater precision when changing to linear gamma for compositing against
+  background and doing rgb-to-gray transformation.
+Investigate pre-incremented loop counters and other loop constructions.
diff --git a/libraries/libpng-1.2.0/Y2KINFO b/libraries/libpng-1.2.0/Y2KINFO
new file mode 100644 (file)
index 0000000..e3f9108
--- /dev/null
@@ -0,0 +1,55 @@
+   Y2K compliance in libpng:
+   =========================
+
+      September 1, 2001
+
+      Since the PNG Development group is an ad-hoc body, we can't make
+      an official declaration.
+
+      This is your unofficial assurance that libpng from version 0.71 and
+      upward through 1.2.0 are Y2K compliant.  It is my belief that earlier
+      versions were also Y2K compliant.
+
+      Libpng only has three year fields.  One is a 2-byte unsigned integer
+      that will hold years up to 65535.  The other two hold the date in text
+      format, and will hold years up to 9999.
+
+      The integer is
+          "png_uint_16 year" in png_time_struct.
+
+      The strings are
+          "png_charp time_buffer" in png_struct and
+          "near_time_buffer", which is a local character string in png.c.
+
+      There are seven time-related functions:
+
+          png_convert_to_rfc_1123() in png.c
+            (formerly png_convert_to_rfc_1152() in error)
+          png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
+          png_convert_from_time_t() in pngwrite.c
+          png_get_tIME() in pngget.c
+          png_handle_tIME() in pngrutil.c, called in pngread.c
+          png_set_tIME() in pngset.c
+          png_write_tIME() in pngwutil.c, called in pngwrite.c
+
+      All appear to handle dates properly in a Y2K environment.  The
+      png_convert_from_time_t() function calls gmtime() to convert from system
+      clock time, which returns (year - 1900), which we properly convert to
+      the full 4-digit year.  There is a possibility that applications using
+      libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+      function, or that they are incorrectly passing only a 2-digit year
+      instead of "year - 1900" into the png_convert_from_struct_tm() function,
+      but this is not under our control.  The libpng documentation has always
+      stated that it works with 4-digit years, and the APIs have been
+      documented as such.
+
+      The tIME chunk itself is also Y2K compliant.  It uses a 2-byte unsigned
+      integer to hold the year, and can hold years as large as 65535.
+
+      zlib, upon which libpng depends, is also Y2K compliant.  It contains
+      no date-related code.
+
+
+         Glenn Randers-Pehrson
+         libpng maintainer
+         PNG Development Group
diff --git a/libraries/libpng-1.2.0/example.c b/libraries/libpng-1.2.0/example.c
new file mode 100644 (file)
index 0000000..0f0ad5f
--- /dev/null
@@ -0,0 +1,776 @@
+
+#if 0 /* in case someone actually tries to compile this */
+
+/* example.c - an example of using libpng */
+
+/* This is an example of how to use libpng to read and write PNG files.
+ * The file libpng.txt is much more verbose then this.  If you have not
+ * read it, do so first.  This was designed to be a starting point of an
+ * implementation.  This is not officially part of libpng, is hereby placed
+ * in the public domain, and therefore does not require a copyright notice.
+ *
+ * This file does not currently compile, because it is missing certain
+ * parts, like allocating memory to hold an image.  You will have to
+ * supply these parts to get it to compile.  For an example of a minimal
+ * working PNG reader/writer, see pngtest.c, included in this distribution;
+ * see also the programs in the contrib directory.
+ */
+
+#include "png.h"
+
+ /* The png_jmpbuf() macro, used in error handling, became available in
+  * libpng version 1.0.6.  If you want to be able to run your code with older
+  * versions of libpng, you must define the macro yourself (but only if it
+  * is not already defined by libpng!).
+  */
+
+#ifndef png_jmpbuf
+#  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#endif
+
+/* Check to see if a file is a PNG file using png_sig_cmp().  png_sig_cmp()
+ * returns zero if the image is a PNG and nonzero if it isn't a PNG.
+ *
+ * The function check_if_png() shown here, but not used, returns nonzero (true)
+ * if the file can be opened and is a PNG, 0 (false) otherwise.
+ *
+ * If this call is successful, and you are going to keep the file open,
+ * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once
+ * you have created the png_ptr, so that libpng knows your application
+ * has read that many bytes from the start of the file.  Make sure you
+ * don't call png_set_sig_bytes() with more than 8 bytes read or give it
+ * an incorrect number of bytes read, or you will either have read too
+ * many bytes (your fault), or you are telling libpng to read the wrong
+ * number of magic bytes (also your fault).
+ *
+ * Many applications already read the first 2 or 4 bytes from the start
+ * of the image to determine the file type, so it would be easiest just
+ * to pass the bytes to png_sig_cmp() or even skip that if you know
+ * you have a PNG file, and call png_set_sig_bytes().
+ */
+#define PNG_BYTES_TO_CHECK 4
+int check_if_png(char *file_name, FILE **fp)
+{
+   char buf[PNG_BYTES_TO_CHECK];
+
+   /* Open the prospective PNG file. */
+   if ((*fp = fopen(file_name, "rb")) == NULL)
+      return 0;
+
+   /* Read in some of the signature bytes */
+   if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
+      return 0;
+
+   /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
+      Return nonzero (true) if they match */
+
+   return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
+}
+
+/* Read a PNG file.  You may want to return an error code if the read
+ * fails (depending upon the failure).  There are two "prototypes" given
+ * here - one where we are given the filename, and we need to open the
+ * file, and the other where we are given an open file (possibly with
+ * some or all of the magic bytes read - see comments above).
+ */
+#ifdef open_file /* prototype 1 */
+void read_png(char *file_name)  /* We need to open the file */
+{
+   png_structp png_ptr;
+   png_infop info_ptr;
+   unsigned int sig_read = 0;
+   png_uint_32 width, height;
+   int bit_depth, color_type, interlace_type;
+   FILE *fp;
+
+   if ((fp = fopen(file_name, "rb")) == NULL)
+      return (ERROR);
+#else no_open_file /* prototype 2 */
+void read_png(FILE *fp, unsigned int sig_read)  /* file is already open */
+{
+   png_structp png_ptr;
+   png_infop info_ptr;
+   png_uint_32 width, height;
+   int bit_depth, color_type, interlace_type;
+#endif no_open_file /* only use one prototype! */
+
+   /* Create and initialize the png_struct with the desired error handler
+    * functions.  If you want to use the default stderr and longjump method,
+    * you can supply NULL for the last three parameters.  We also supply the
+    * the compiler header file version, so that we know if the application
+    * was compiled with a compatible version of the library.  REQUIRED
+    */
+   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+      png_voidp user_error_ptr, user_error_fn, user_warning_fn);
+
+   if (png_ptr == NULL)
+   {
+      fclose(fp);
+      return (ERROR);
+   }
+
+   /* Allocate/initialize the memory for image information.  REQUIRED. */
+   info_ptr = png_create_info_struct(png_ptr);
+   if (info_ptr == NULL)
+   {
+      fclose(fp);
+      png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+      return (ERROR);
+   }
+
+   /* Set error handling if you are using the setjmp/longjmp method (this is
+    * the normal method of doing things with libpng).  REQUIRED unless you
+    * set up your own error handlers in the png_create_read_struct() earlier.
+    */
+
+   if (setjmp(png_jmpbuf(png_ptr)))
+   {
+      /* Free all of the memory associated with the png_ptr and info_ptr */
+      png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+      fclose(fp);
+      /* If we get here, we had a problem reading the file */
+      return (ERROR);
+   }
+
+   /* One of the following I/O initialization methods is REQUIRED */
+#ifdef streams /* PNG file I/O method 1 */
+   /* Set up the input control if you are using standard C streams */
+   png_init_io(png_ptr, fp);
+
+#else no_streams /* PNG file I/O method 2 */
+   /* If you are using replacement read functions, instead of calling
+    * png_init_io() here you would call:
+    */
+   png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
+   /* where user_io_ptr is a structure you want available to the callbacks */
+#endif no_streams /* Use only one I/O method! */
+
+   /* If we have already read some of the signature */
+   png_set_sig_bytes(png_ptr, sig_read);
+
+#ifdef hilevel
+   /*
+    * If you have enough memory to read in the entire image at once,
+    * and you need to specify only transforms that can be controlled
+    * with one of the PNG_TRANSFORM_* bits (this presently excludes
+    * dithering, filling, setting background, and doing gamma
+    * adjustment), then you can read the entire image (including
+    * pixels) into the info structure with this call:
+    */
+   png_read_png(png_ptr, info_ptr, png_transforms, NULL);
+#else
+   /* OK, you're doing it the hard way, with the lower-level functions */
+
+   /* The call to png_read_info() gives us all of the information from the
+    * PNG file before the first IDAT (image data chunk).  REQUIRED
+    */
+   png_read_info(png_ptr, info_ptr);
+
+   png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+       &interlace_type, NULL, NULL);
+
+/**** Set up the data transformations you want.  Note that these are all
+ **** optional.  Only call them if you want/need them.  Many of the
+ **** transformations only work on specific types of images, and many
+ **** are mutually exclusive.
+ ****/
+
+   /* tell libpng to strip 16 bit/color files down to 8 bits/color */
+   png_set_strip_16(png_ptr);
+
+   /* Strip alpha bytes from the input data without combining with the
+    * background (not recommended).
+    */
+   png_set_strip_alpha(png_ptr);
+
+   /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
+    * byte into separate bytes (useful for paletted and grayscale images).
+    */
+   png_set_packing(png_ptr);
+
+   /* Change the order of packed pixels to least significant bit first
+    * (not useful if you are using png_set_packing). */
+   png_set_packswap(png_ptr);
+
+   /* Expand paletted colors into true RGB triplets */
+   if (color_type == PNG_COLOR_TYPE_PALETTE)
+      png_set_palette_rgb(png_ptr);
+
+   /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
+   if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+      png_set_gray_1_2_4_to_8(png_ptr);
+
+   /* Expand paletted or RGB images with transparency to full alpha channels
+    * so the data will be available as RGBA quartets.
+    */
+   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+      png_set_tRNS_to_alpha(png_ptr);
+
+   /* Set the background color to draw transparent and alpha images over.
+    * It is possible to set the red, green, and blue components directly
+    * for paletted images instead of supplying a palette index.  Note that
+    * even if the PNG file supplies a background, you are not required to
+    * use it - you should use the (solid) application background if it has one.
+    */
+
+   png_color_16 my_background, *image_background;
+
+   if (png_get_bKGD(png_ptr, info_ptr, &image_background))
+      png_set_background(png_ptr, image_background,
+                         PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+   else
+      png_set_background(png_ptr, &my_background,
+                         PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+
+   /* Some suggestions as to how to get a screen gamma value */
+
+   /* Note that screen gamma is the display_exponent, which includes
+    * the CRT_exponent and any correction for viewing conditions */
+   if (/* We have a user-defined screen gamma value */)
+   {
+      screen_gamma = user-defined screen_gamma;
+   }
+   /* This is one way that applications share the same screen gamma value */
+   else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
+   {
+      screen_gamma = atof(gamma_str);
+   }
+   /* If we don't have another value */
+   else
+   {
+      screen_gamma = 2.2;  /* A good guess for a PC monitors in a dimly
+                              lit room */
+      screen_gamma = 1.7 or 1.0;  /* A good guess for Mac systems */
+   }
+
+   /* Tell libpng to handle the gamma conversion for you.  The final call
+    * is a good guess for PC generated images, but it should be configurable
+    * by the user at run time by the user.  It is strongly suggested that
+    * your application support gamma correction.
+    */
+
+   int intent;
+
+   if (png_get_sRGB(png_ptr, info_ptr, &intent))
+      png_set_gamma(png_ptr, screen_gamma, 0.45455);
+   else
+   {
+      double image_gamma;
+      if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
+         png_set_gamma(png_ptr, screen_gamma, image_gamma);
+      else
+         png_set_gamma(png_ptr, screen_gamma, 0.45455);
+   }
+
+   /* Dither RGB files down to 8 bit palette or reduce palettes
+    * to the number of colors available on your screen.
+    */
+   if (color_type & PNG_COLOR_MASK_COLOR)
+   {
+      int num_palette;
+      png_colorp palette;
+
+      /* This reduces the image to the application supplied palette */
+      if (/* we have our own palette */)
+      {
+         /* An array of colors to which the image should be dithered */
+         png_color std_color_cube[MAX_SCREEN_COLORS];
+
+         png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
+            MAX_SCREEN_COLORS, NULL, 0);
+      }
+      /* This reduces the image to the palette supplied in the file */
+      else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette))
+      {
+         png_uint_16p histogram;
+
+         png_get_hIST(png_ptr, info_ptr, &histogram);
+
+         png_set_dither(png_ptr, palette, num_palette,
+                        max_screen_colors, histogram, 0);
+      }
+   }
+
+   /* invert monochrome files to have 0 as white and 1 as black */
+   png_set_invert_mono(png_ptr);
+
+   /* If you want to shift the pixel values from the range [0,255] or
+    * [0,65535] to the original [0,7] or [0,31], or whatever range the
+    * colors were originally in:
+    */
+   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
+   {
+      png_color_8p sig_bit;
+
+      png_get_sBIT(png_ptr, info_ptr, &sig_bit);
+      png_set_shift(png_ptr, sig_bit);
+   }
+
+   /* flip the RGB pixels to BGR (or RGBA to BGRA) */
+   if (color_type & PNG_COLOR_MASK_COLOR)
+      png_set_bgr(png_ptr);
+
+   /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
+   png_set_swap_alpha(png_ptr);
+
+   /* swap bytes of 16 bit files to least significant byte first */
+   png_set_swap(png_ptr);
+
+   /* Add filler (or alpha) byte (before/after each RGB triplet) */
+   png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+   /* Turn on interlace handling.  REQUIRED if you are not using
+    * png_read_image().  To see how to handle interlacing passes,
+    * see the png_read_row() method below:
+    */
+   number_passes = png_set_interlace_handling(png_ptr);
+
+   /* Optional call to gamma correct and add the background to the palette
+    * and update info structure.  REQUIRED if you are expecting libpng to
+    * update the palette for you (ie you selected such a transform above).
+    */
+   png_read_update_info(png_ptr, info_ptr);
+
+   /* Allocate the memory to hold the image using the fields of info_ptr. */
+
+   /* The easiest way to read the image: */
+   png_bytep row_pointers[height];
+
+   for (row = 0; row < height; row++)
+   {
+      row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr,
+         info_ptr));
+   }
+
+   /* Now it's time to read the image.  One of these methods is REQUIRED */
+#ifdef entire /* Read the entire image in one go */
+   png_read_image(png_ptr, row_pointers);
+
+#else no_entire /* Read the image one or more scanlines at a time */
+   /* The other way to read images - deal with interlacing: */
+
+   for (pass = 0; pass < number_passes; pass++)
+   {
+#ifdef single /* Read the image a single row at a time */
+      for (y = 0; y < height; y++)
+      {
+         png_read_rows(png_ptr, &row_pointers[y], NULL, 1);
+      }
+
+#else no_single /* Read the image several rows at a time */
+      for (y = 0; y < height; y += number_of_rows)
+      {
+#ifdef sparkle /* Read the image using the "sparkle" effect. */
+         png_read_rows(png_ptr, &row_pointers[y], NULL, number_of_rows);
+#else no_sparkle /* Read the image using the "rectangle" effect */
+         png_read_rows(png_ptr, NULL, &row_pointers[y], number_of_rows);
+#endif no_sparkle /* use only one of these two methods */
+      }
+
+      /* if you want to display the image after every pass, do
+         so here */
+#endif no_single /* use only one of these two methods */
+   }
+#endif no_entire /* use only one of these two methods */
+
+   /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
+   png_read_end(png_ptr, info_ptr);
+#endif hilevel
+
+   /* At this point you have read the entire image */
+
+   /* clean up after the read, and free any memory allocated - REQUIRED */
+   png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+
+   /* close the file */
+   fclose(fp);
+
+   /* that's it */
+   return (OK);
+}
+
+/* progressively read a file */
+
+int
+initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
+{
+   /* Create and initialize the png_struct with the desired error handler
+    * functions.  If you want to use the default stderr and longjump method,
+    * you can supply NULL for the last three parameters.  We also check that
+    * the library version is compatible in case we are using dynamically
+    * linked libraries.
+    */
+   *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+       png_voidp user_error_ptr, user_error_fn, user_warning_fn);
+
+   if (*png_ptr == NULL)
+   {
+      *info_ptr = NULL;
+      return (ERROR);
+   }
+
+   *info_ptr = png_create_info_struct(png_ptr);
+
+   if (*info_ptr == NULL)
+   {
+      png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
+      return (ERROR);
+   }
+
+   if (setjmp(png_jmpbuf((*png_ptr))))
+   {
+      png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
+      return (ERROR);
+   }
+
+   /* This one's new.  You will need to provide all three
+    * function callbacks, even if you aren't using them all.
+    * If you aren't using all functions, you can specify NULL
+    * parameters.  Even when all three functions are NULL,
+    * you need to call png_set_progressive_read_fn().
+    * These functions shouldn't be dependent on global or
+    * static variables if you are decoding several images
+    * simultaneously.  You should store stream specific data
+    * in a separate struct, given as the second parameter,
+    * and retrieve the pointer from inside the callbacks using
+    * the function png_get_progressive_ptr(png_ptr).
+    */
+   png_set_progressive_read_fn(*png_ptr, (void *)stream_data,
+      info_callback, row_callback, end_callback);
+
+   return (OK);
+}
+
+int
+process_data(png_structp *png_ptr, png_infop *info_ptr,
+   png_bytep buffer, png_uint_32 length)
+{
+   if (setjmp(png_jmpbuf((*png_ptr))))
+   {
+      /* Free the png_ptr and info_ptr memory on error */
+      png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
+      return (ERROR);
+   }
+
+   /* This one's new also.  Simply give it chunks of data as
+    * they arrive from the data stream (in order, of course).
+    * On Segmented machines, don't give it any more than 64K.
+    * The library seems to run fine with sizes of 4K, although
+    * you can give it much less if necessary (I assume you can
+    * give it chunks of 1 byte, but I haven't tried with less
+    * than 256 bytes yet).  When this function returns, you may
+    * want to display any rows that were generated in the row
+    * callback, if you aren't already displaying them there.
+    */
+   png_process_data(*png_ptr, *info_ptr, buffer, length);
+   return (OK);
+}
+
+info_callback(png_structp png_ptr, png_infop info)
+{
+/* do any setup here, including setting any of the transformations
+ * mentioned in the Reading PNG files section.  For now, you _must_
+ * call either png_start_read_image() or png_read_update_info()
+ * after all the transformations are set (even if you don't set
+ * any).  You may start getting rows before png_process_data()
+ * returns, so this is your last chance to prepare for that.
+ */
+}
+
+row_callback(png_structp png_ptr, png_bytep new_row,
+   png_uint_32 row_num, int pass)
+{
+/* this function is called for every row in the image.  If the
+ * image is interlacing, and you turned on the interlace handler,
+ * this function will be called for every row in every pass.
+ * Some of these rows will not be changed from the previous pass.
+ * When the row is not changed, the new_row variable will be NULL.
+ * The rows and passes are called in order, so you don't really
+ * need the row_num and pass, but I'm supplying them because it
+ * may make your life easier.
+ *
+ * For the non-NULL rows of interlaced images, you must call
+ * png_progressive_combine_row() passing in the row and the
+ * old row.  You can call this function for NULL rows (it will
+ * just return) and for non-interlaced images (it just does the
+ * png_memcpy for you) if it will make the code easier.  Thus, you
+ * can just do this for all cases:
+ */
+
+   png_progressive_combine_row(png_ptr, old_row, new_row);
+
+/* where old_row is what was displayed for previous rows.  Note
+ * that the first pass (pass == 0 really) will completely cover
+ * the old row, so the rows do not have to be initialized.  After
+ * the first pass (and only for interlaced images), you will have
+ * to pass the current row, and the function will combine the
+ * old row and the new row.
+ */
+}
+
+end_callback(png_structp png_ptr, png_infop info)
+{
+/* this function is called when the whole image has been read,
+ * including any chunks after the image (up to and including
+ * the IEND).  You will usually have the same info chunk as you
+ * had in the header, although some data may have been added
+ * to the comments and time fields.
+ *
+ * Most people won't do much here, perhaps setting a flag that
+ * marks the image as finished.
+ */
+}
+
+/* write a png file */
+void write_png(char *file_name /* , ... other image information ... */)
+{
+   FILE *fp;
+   png_structp png_ptr;
+   png_infop info_ptr;
+   png_colorp palette;
+
+   /* open the file */
+   fp = fopen(file_name, "wb");
+   if (fp == NULL)
+      return (ERROR);
+
+   /* Create and initialize the png_struct with the desired error handler
+    * functions.  If you want to use the default stderr and longjump method,
+    * you can supply NULL for the last three parameters.  We also check that
+    * the library version is compatible with the one used at compile time,
+    * in case we are using dynamically linked libraries.  REQUIRED.
+    */
+   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+      png_voidp user_error_ptr, user_error_fn, user_warning_fn);
+
+   if (png_ptr == NULL)
+   {
+      fclose(fp);
+      return (ERROR);
+   }
+
+   /* Allocate/initialize the image information data.  REQUIRED */
+   info_ptr = png_create_info_struct(png_ptr);
+   if (info_ptr == NULL)
+   {
+      fclose(fp);
+      png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
+      return (ERROR);
+   }
+
+   /* Set error handling.  REQUIRED if you aren't supplying your own
+    * error handling functions in the png_create_write_struct() call.
+    */
+   if (setjmp(png_jmpbuf(png_ptr)))
+   {
+      /* If we get here, we had a problem reading the file */
+      fclose(fp);
+      png_destroy_write_struct(&png_ptr, &info_ptr);
+      return (ERROR);
+   }
+
+   /* One of the following I/O initialization functions is REQUIRED */
+#ifdef streams /* I/O initialization method 1 */
+   /* set up the output control if you are using standard C streams */
+   png_init_io(png_ptr, fp);
+#else no_streams /* I/O initialization method 2 */
+   /* If you are using replacement read functions, instead of calling
+    * png_init_io() here you would call */
+   png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn,
+      user_IO_flush_function);
+   /* where user_io_ptr is a structure you want available to the callbacks */
+#endif no_streams /* only use one initialization method */
+
+#ifdef hilevel
+   /* This is the easy way.  Use it if you already have all the
+    * image info living info in the structure.  You could "|" many
+    * PNG_TRANSFORM flags into the png_transforms integer here.
+    */
+   png_write_png(png_ptr, info_ptr, png_transforms, NULL);
+#else
+   /* This is the hard way */
+
+   /* Set the image information here.  Width and height are up to 2^31,
+    * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
+    * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
+    * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+    * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
+    * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+    * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
+    */
+   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???,
+      PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+   /* set the palette if there is one.  REQUIRED for indexed-color images */
+   palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH
+             * sizeof (png_color));
+   /* ... set palette colors ... */
+   png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
+   /* You must not free palette here, because png_set_PLTE only makes a link to
+      the palette that you malloced.  Wait until you are about to destroy
+      the png structure. */
+
+   /* optional significant bit chunk */
+   /* if we are dealing with a grayscale image then */
+   sig_bit.gray = true_bit_depth;
+   /* otherwise, if we are dealing with a color image then */
+   sig_bit.red = true_red_bit_depth;
+   sig_bit.green = true_green_bit_depth;
+   sig_bit.blue = true_blue_bit_depth;
+   /* if the image has an alpha channel then */
+   sig_bit.alpha = true_alpha_bit_depth;
+   png_set_sBIT(png_ptr, info_ptr, sig_bit);
+
+
+   /* Optional gamma chunk is strongly suggested if you have any guess
+    * as to the correct gamma of the image.
+    */
+   png_set_gAMA(png_ptr, info_ptr, gamma);
+
+   /* Optionally write comments into the image */
+   text_ptr[0].key = "Title";
+   text_ptr[0].text = "Mona Lisa";
+   text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
+   text_ptr[1].key = "Author";
+   text_ptr[1].text = "Leonardo DaVinci";
+   text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
+   text_ptr[2].key = "Description";
+   text_ptr[2].text = "<long text>";
+   text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
+#ifdef PNG_iTXt_SUPPORTED
+   text_ptr[0].lang = NULL;
+   text_ptr[1].lang = NULL;
+   text_ptr[2].lang = NULL;
+#endif
+   png_set_text(png_ptr, info_ptr, text_ptr, 3);
+
+   /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
+   /* note that if sRGB is present the gAMA and cHRM chunks must be ignored
+    * on read and must be written in accordance with the sRGB profile */
+
+   /* Write the file header information.  REQUIRED */
+   png_write_info(png_ptr, info_ptr);
+
+   /* If you want, you can write the info in two steps, in case you need to
+    * write your private chunk ahead of PLTE:
+    *
+    *   png_write_info_before_PLTE(write_ptr, write_info_ptr);
+    *   write_my_chunk();
+    *   png_write_info(png_ptr, info_ptr);
+    *
+    * However, given the level of known- and unknown-chunk support in 1.1.0
+    * and up, this should no longer be necessary.
+    */
+
+   /* Once we write out the header, the compression type on the text
+    * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
+    * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
+    * at the end.
+    */
+
+   /* set up the transformations you want.  Note that these are
+    * all optional.  Only call them if you want them.
+    */
+
+   /* invert monochrome pixels */
+   png_set_invert_mono(png_ptr);
+
+   /* Shift the pixels up to a legal bit depth and fill in
+    * as appropriate to correctly scale the image.
+    */
+   png_set_shift(png_ptr, &sig_bit);
+
+   /* pack pixels into bytes */
+   png_set_packing(png_ptr);
+
+   /* swap location of alpha bytes from ARGB to RGBA */
+   png_set_swap_alpha(png_ptr);
+
+   /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
+    * RGB (4 channels -> 3 channels). The second parameter is not used.
+    */
+   png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+
+   /* flip BGR pixels to RGB */
+   png_set_bgr(png_ptr);
+
+   /* swap bytes of 16-bit files to most significant byte first */
+   png_set_swap(png_ptr);
+
+   /* swap bits of 1, 2, 4 bit packed pixel formats */
+   png_set_packswap(png_ptr);
+
+   /* turn on interlace handling if you are not using png_write_image() */
+   if (interlacing)
+      number_passes = png_set_interlace_handling(png_ptr);
+   else
+      number_passes = 1;
+
+   /* The easiest way to write the image (you may have a different memory
+    * layout, however, so choose what fits your needs best).  You need to
+    * use the first method if you aren't handling interlacing yourself.
+    */
+   png_uint_32 k, height, width;
+   png_byte image[height][width*bytes_per_pixel];
+   png_bytep row_pointers[height];
+   for (k = 0; k < height; k++)
+     row_pointers[k] = image + k*width*bytes_per_pixel;
+
+   /* One of the following output methods is REQUIRED */
+#ifdef entire /* write out the entire image data in one call */
+   png_write_image(png_ptr, row_pointers);
+
+   /* the other way to write the image - deal with interlacing */
+
+#else no_entire /* write out the image data by one or more scanlines */
+   /* The number of passes is either 1 for non-interlaced images,
+    * or 7 for interlaced images.
+    */
+   for (pass = 0; pass < number_passes; pass++)
+   {
+      /* Write a few rows at a time. */
+      png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows);
+
+      /* If you are only writing one row at a time, this works */
+      for (y = 0; y < height; y++)
+      {
+         png_write_rows(png_ptr, &row_pointers[y], 1);
+      }
+   }
+#endif no_entire /* use only one output method */
+
+   /* You can write optional chunks like tEXt, zTXt, and tIME at the end
+    * as well.  Shouldn't be necessary in 1.1.0 and up as all the public
+    * chunks are supported and you can use png_set_unknown_chunks() to
+    * register unknown chunks into the info structure to be written out.
+    */
+
+   /* It is REQUIRED to call this to finish writing the rest of the file */
+   png_write_end(png_ptr, info_ptr);
+#endif hilevel
+
+   /* If you png_malloced a palette, free it here (don't free info_ptr->palette,
+      as recommended in versions 1.0.5m and earlier of this example; if
+      libpng mallocs info_ptr->palette, libpng will free it).  If you
+      allocated it with malloc() instead of png_malloc(), use free() instead
+      of png_free(). */
+   png_free(png_ptr, palette);
+   palette=NULL;
+
+   /* Similarly, if you png_malloced any data that you passed in with
+      png_set_something(), such as a hist or trans array, free it here,
+      when you can be sure that libpng is through with it. */
+   png_free(png_ptr, trans);
+   trans=NULL;
+
+   /* clean up after the write, and free any memory allocated */
+   png_destroy_write_struct(&png_ptr, &info_ptr);
+
+   /* close the file */
+   fclose(fp);
+
+   /* that's it */
+   return (OK);
+}
+
+#endif /* if 0 */
diff --git a/libraries/libpng-1.2.0/libpng.3 b/libraries/libpng-1.2.0/libpng.3
new file mode 100644 (file)
index 0000000..8fed9c6
--- /dev/null
@@ -0,0 +1,3931 @@
+.TH LIBPNG 3 "September 1, 2001"
+.SH NAME
+libpng \- Portable Network Graphics (PNG) Reference Library 1.2.0
+.SH SYNOPSIS
+\fI\fB
+
+\fB#include <png.h>\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_access_version_number \fI(void\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_check_sig (png_bytep \fP\fIsig\fP\fB, int \fInum\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_chunk_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_chunk_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_convert_from_struct_tm (png_timep \fP\fIptime\fP\fB, struct tm FAR * \fIttime\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_convert_from_time_t (png_timep \fP\fIptime\fP\fB, time_t \fIttime\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_charp png_convert_to_rfc1123 (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fIptime\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_infop png_create_info_struct (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_structp png_create_read_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_structp png_create_read_struct_2(png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_structp png_create_write_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_structp png_create_write_struct_2(png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_debug(int \fP\fIlevel\fP\fB, png_const_charp \fImessage\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_debug1(int \fP\fIlevel\fP\fB, png_const_charp \fP\fImessage\fP\fB, \fIp1\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_debug2(int \fP\fIlevel\fP\fB, png_const_charp \fP\fImessage\fP\fB, \fP\fIp1\fP\fB, \fIp2\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_destroy_info_struct (png_structp \fP\fIpng_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_destroy_read_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fP\fIinfo_ptr_ptr\fP\fB, png_infopp \fIend_info_ptr_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_destroy_write_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_free (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_free_chunk_list (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_free_default(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_free_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_asm_flags (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_bit_depth (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fI*background\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_channels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*white_x\fP\fB, double \fP\fI*white_y\fP\fB, double \fP\fI*red_x\fP\fB, double \fP\fI*red_y\fP\fB, double \fP\fI*green_x\fP\fB, double \fP\fI*green_y\fP\fB, double \fP\fI*blue_x\fP\fB, double \fI*blue_y\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*white_x\fP\fB, png_uint_32 \fP\fI*white_y\fP\fB, png_uint_32 \fP\fI*red_x\fP\fB, png_uint_32 \fP\fI*red_y\fP\fB, png_uint_32 \fP\fI*green_x\fP\fB, png_uint_32 \fP\fI*green_y\fP\fB, png_uint_32 \fP\fI*blue_x\fP\fB, png_uint_32 \fI*blue_y\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_color_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_compression_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_copyright (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_error_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_filter_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fI*file_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fI*int_file_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_header_ver (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_header_version (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_charpp \fP\fIprofile\fP\fB, png_uint_32 \fI*proflen\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*width\fP\fB, png_uint_32 \fP\fI*height\fP\fB, int \fP\fI*bit_depth\fP\fB, int \fP\fI*color_type\fP\fB, int \fP\fI*interlace_type\fP\fB, int \fP\fI*compression_type\fP\fB, int \fI*filter_type\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_image_height (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_image_width (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_interlace_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_io_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_libpng_ver (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_mem_ptr(png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_mmx_bitdepth_threshold (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_mmx_flagmask (int \fP\fIflag_select\fP\fB, int \fI*compilerID\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_mmx_rowbytes_threshold (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*offset_x\fP\fB, png_uint_32 \fP\fI*offset_y\fP\fB, int \fI*unit_type\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fI*purpose\fP\fB, png_int_32 \fP\fI*X0\fP\fB, png_int_32 \fP\fI*X1\fP\fB, int \fP\fI*type\fP\fB, int \fP\fI*nparams\fP\fB, png_charp \fP\fI*units\fP\fB, png_charpp \fI*params\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP
+
+\fI\fB
+
+\fBfloat png_get_pixel_aspect_ratio (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_progressive_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fI*palette\fP\fB, int \fI*num_palette\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_rgb_to_gray_status (png_structp \fIpng_ptr)
+
+\fBpng_uint_32 png_get_rowbytes (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_bytepp png_get_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fI*sig_bit\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_bytep png_get_signature (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fI*splt_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fI*intent\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fI*text_ptr\fP\fB, int \fI*num_text\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fI*mod_time\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fI*trans\fP\fB, int \fP\fI*num_trans\fP\fB, png_color_16p \fI*trans_values\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkpp \fIunknowns\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_user_chunk_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_user_transform_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_valid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIflag\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_int_32 png_get_x_offset_microns (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_int_32 png_get_x_offset_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_x_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_int_32 png_get_y_offset_microns (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_int_32 png_get_y_offset_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_y_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_compression_buffer_size (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_info_init (png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_info_init_2 (png_infopp \fP\fIptr_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_malloc (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_malloc_default(png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBvoidp png_memcpy (png_voidp \fP\fIs1\fP\fB, png_voidp \fP\fIs2\fP\fB, png_size_t \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_memcpy_check (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIs1\fP\fB, png_voidp \fP\fIs2\fP\fB, png_uint_32 \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBvoidp png_memset (png_voidp \fP\fIs1\fP\fB, int \fP\fIvalue\fP\fB, png_size_t \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_memset_check (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIs1\fP\fB, int \fP\fIvalue\fP\fB, png_uint_32 \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_mmx_support \fI(void\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_permit_empty_plte (png_structp \fP\fIpng_ptr\fP\fB, int \fIempty_plte_permitted\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_process_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_size\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_progressive_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIold_row\fP\fB, png_bytep \fInew_row\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_destroy (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_infop \fIend_info_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_read_init (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_read_init_2 (png_structpp \fP\fIptr_ptr\fP\fB, png_const_charp \fP\fIuser_png_ver\fP\fB, png_size_t \fP\fIpng_struct_size\fP\fB, png_size_t \fIpng_info_size\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fIdisplay_row\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_bytepp \fP\fIdisplay_row\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_update_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_set_asm_flags (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIasm_flags\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_background (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIbackground_color\fP\fB, int \fP\fIbackground_gamma_code\fP\fB, int \fP\fIneed_expand\fP\fB, double \fIbackground_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_bgr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fIbackground\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_method (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_crc_action (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcrit_action\fP\fB, int \fIancil_action\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_dither (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fP\fInum_palette\fP\fB, int \fP\fImaximum_colors\fP\fB, png_uint_16p \fP\fIhistogram\fP\fB, int \fIfull_dither\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_error_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarning_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_expand (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_filler (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_filter (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImethod\fP\fB, int \fIfilters\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_filter_heuristics (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_doublep \fP\fIfilter_weights\fP\fB, png_doublep \fIfilter_costs\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_flush (png_structp \fP\fIpng_ptr\fP\fB, int \fInrows\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_gamma (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIscreen_gamma\fP\fB, double \fIdefault_file_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIfile_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_gray_1_2_4_to_8(png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_gray_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fIhist\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, png_uint_32 \fIproflen\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_set_interlace_handling (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_invalid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fImask\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_invert_alpha (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_invert_mono (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIinterlace_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fIfilter_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_keep_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIkeep\fP\fB, png_bytep \fP\fIchunk_list\fP\fB, int \fInum_chunks\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_mem_fn(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_set_mmx_thresholds (png_structp \fP\fIpng_ptr\fP\fB, png_byte \fP\fImmx_bitdepth_threshold\fP\fB, png_uint_32 \fImmx_rowbytes_threshold\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIoffset_x\fP\fB, png_uint_32 \fP\fIoffset_y\fP\fB, int \fIunit_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_packing (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_packswap (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_palette_to_rgb(png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIres_x\fP\fB, png_uint_32 \fP\fIres_y\fP\fB, int \fIunit_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_progressive_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIprogressive_ptr\fP\fB, png_progressive_info_ptr \fP\fIinfo_fn\fP\fB, png_progressive_row_ptr \fP\fIrow_fn\fP\fB, png_progressive_end_ptr \fIend_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fIread_data_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_read_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_read_status_ptr \fIread_row_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_read_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIread_user_transform_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_rgb_to_gray (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIerror_action\fP\fB, double \fP\fIred\fP\fB, double \fIgreen\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_rgb_to_gray_fixed (png_structp \fP\fIpng_ptr\fP\fB, int error_action png_fixed_point \fP\fIred\fP\fB, png_fixed_point \fIgreen\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytepp \fIrow_pointers\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fIsig_bit\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_shift (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fItrue_bits\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sig_bytes (png_structp \fP\fIpng_ptr\fP\fB, int \fInum_bytes\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fP\fIsplt_ptr\fP\fB, int \fInum_spalettes\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIintent\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sRGB_gAMA_and_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIintent\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_strip_16 (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_strip_alpha (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_strip_error_numbers (png_structp \fIpng_ptr,
+
+\fBpng_uint_32 \fIstrip_mode\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_swap (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_swap_alpha (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fItrans\fP\fB, int \fP\fInum_trans\fP\fB, png_color_16p \fItrans_values\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_tRNS_to_alpha(png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_set_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkp \fP\fIunknowns\fP\fB, int \fP\fInum\fP\fB, int \fIlocation\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_unknown_chunk_location(png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIchunk\fP\fB, int \fIlocation\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_read_user_chunk_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_chunk_ptr\fP\fB, png_user_chunk_ptr \fIread_user_chunk_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_user_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_transform_ptr\fP\fB, int \fP\fIuser_transform_depth\fP\fB, int \fIuser_transform_channels\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_write_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fP\fIwrite_data_fn\fP\fB, png_flush_ptr \fIoutput_flush_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_write_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_write_status_ptr \fIwrite_row_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_write_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIwrite_user_transform_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_buffer_size(png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_sig_cmp (png_bytep \fP\fIsig\fP\fB, png_size_t \fP\fIstart\fP\fB, png_size_t \fInum_to_check\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_start_read_image (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_chunk_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_chunk_end (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_chunk_start (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_destroy (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_destroy_info (png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_flush (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_write_init (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_write_init_2 (png_structpp \fP\fIptr_ptr\fP\fB, png_const_charp \fP\fIuser_png_ver\fP\fB, png_size_t \fP\fIpng_struct_size\fP\fB, png_size_t \fIpng_info_size\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_info_before_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP
+
+\fI\fB
+
+.SH DESCRIPTION
+The
+.I libpng
+library supports encoding, decoding, and various manipulations of
+the Portable Network Graphics (PNG) format image files.  It uses the
+.IR zlib(3)
+compression library.
+Following is a copy of the libpng.txt file that accompanies libpng.
+.SH LIBPNG.TXT
+libpng.txt - A description on how to use and modify libpng
+
+ libpng version 1.2.0 - September 1, 2001
+ Updated and distributed by Glenn Randers-Pehrson
+ <randeg@alum.rpi.edu>
+ Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ For conditions of distribution and use, see copyright
+ notice in png.h.
+
+ based on:
+
+ libpng 1.0 beta 6  version 0.96 May 28, 1997
+ Updated and distributed by Andreas Dilger
+ Copyright (c) 1996, 1997 Andreas Dilger
+
+ libpng 1.0 beta 2 - version 0.88  January 26, 1996
+ For conditions of distribution and use, see copyright
+ notice in png.h. Copyright (c) 1995, 1996 Guy Eric
+ Schalnat, Group 42, Inc.
+
+ Updated/rewritten per request in the libpng FAQ
+ Copyright (c) 1995, 1996 Frank J. T. Wojcik
+ December 18, 1995 & January 20, 1996
+
+.SH I. Introduction
+
+This file describes how to use and modify the PNG reference library
+(known as libpng) for your own use.  There are five sections to this
+file: introduction, structures, reading, writing, and modification and
+configuration notes for various special platforms.  In addition to this
+file, example.c is a good starting point for using the library, as
+it is heavily commented and should include everything most people
+will need.  We assume that libpng is already installed; see the
+INSTALL file for instructions on how to install libpng.
+
+Libpng was written as a companion to the PNG specification, as a way
+of reducing the amount of time and effort it takes to support the PNG
+file format in application programs.
+
+The PNG-1.2 specification is available at <http://www.libpng.org/pub/png>
+and at <ftp://ftp.uu.net/graphics/png/documents/>.
+
+The PNG-1.0 specification is available
+as RFC 2083 <ftp://ftp.uu.net/graphics/png/documents/> and as a
+W3C Recommendation <http://www.w3.org/TR/REC.png.html>. Some
+additional chunks are described in the special-purpose public chunks
+documents at <ftp://ftp.uu.net/graphics/png/documents/>.
+
+Other information
+about PNG, and the latest version of libpng, can be found at the PNG home
+page, <http://www.libpng.org/pub/png/>
+and at <ftp://ftp.uu.net/graphics/png/>.
+
+Most users will not have to modify the library significantly; advanced
+users may want to modify it more.  All attempts were made to make it as
+complete as possible, while keeping the code easy to understand.
+Currently, this library only supports C.  Support for other languages
+is being considered.
+
+Libpng has been designed to handle multiple sessions at one time,
+to be easily modifiable, to be portable to the vast majority of
+machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy
+to use.  The ultimate goal of libpng is to promote the acceptance of
+the PNG file format in whatever way possible.  While there is still
+work to be done (see the TODO file), libpng should cover the
+majority of the needs of its users.
+
+Libpng uses zlib for its compression and decompression of PNG files.
+Further information about zlib, and the latest version of zlib, can
+be found at the zlib home page, <http://www.info-zip.org/pub/infozip/zlib/>.
+The zlib compression utility is a general purpose utility that is
+useful for more than PNG files, and can be used without libpng.
+See the documentation delivered with zlib for more details.
+You can usually find the source files for the zlib utility wherever you
+find the libpng source files.
+
+Libpng is thread safe, provided the threads are using different
+instances of the structures.  Each thread should have its own
+png_struct and png_info instances, and thus its own image.
+Libpng does not protect itself against two threads using the
+same instance of a structure.  Note: thread safety may be defeated
+by use of some of the MMX assembler code in pnggccrd.c, which is only
+compiled when the user defines PNG_THREAD_UNSAFE_OK.
+
+
+.SH II. Structures
+
+There are two main structures that are important to libpng, png_struct
+and png_info.  The first, png_struct, is an internal structure that
+will not, for the most part, be used by a user except as the first
+variable passed to every libpng function call.
+
+The png_info structure is designed to provide information about the
+PNG file.  At one time, the fields of png_info were intended to be
+directly accessible to the user.  However, this tended to cause problems
+with applications using dynamically loaded libraries, and as a result
+a set of interface functions for png_info (the png_get_*() and png_set_*()
+functions) was developed.  The fields of png_info are still available for
+older applications, but it is suggested that applications use the new
+interfaces if at all possible.
+
+Applications that do make direct access to the members of png_struct (except
+for png_ptr->jmpbuf) must be recompiled whenever the library is updated,
+and applications that make direct access to the members of png_info must
+be recompiled if they were compiled or loaded with libpng version 1.0.6,
+in which the members were in a different order.  In version 1.0.7, the
+members of the png_info structure reverted to the old order, as they were
+in versions 0.97c through 1.0.5.  Starting with version 2.0.0, both
+structures are going to be hidden, and the contents of the structures will
+only be accessible through the png_get/png_set functions.
+
+The png.h header file is an invaluable reference for programming with libpng.
+And while I'm on the topic, make sure you include the libpng header file:
+
+#include <png.h>
+
+.SH III. Reading
+
+We'll now walk you through the possible functions to call when reading
+in a PNG file sequentially, briefly explaining the syntax and purpose
+of each one.  See example.c and png.h for more detail.  While
+progressive reading is covered in the next section, you will still
+need some of the functions discussed in this section to read a PNG
+file.
+
+.SS Setup
+
+You will want to do the I/O initialization(*) before you get into libpng,
+so if it doesn't work, you don't have much to undo.  Of course, you
+will also want to insure that you are, in fact, dealing with a PNG
+file.  Libpng provides a simple check to see if a file is a PNG file.
+To use it, pass in the first 1 to 8 bytes of the file to the function
+png_sig_cmp(), and it will return 0 if the bytes match the corresponding
+bytes of the PNG signature, or nonzero otherwise.  Of course, the more bytes
+you pass in, the greater the accuracy of the prediction.
+
+If you are intending to keep the file pointer open for use in libpng,
+you must ensure you don't read more than 8 bytes from the beginning
+of the file, and you also have to make a call to png_set_sig_bytes_read()
+with the number of bytes you read from the beginning.  Libpng will
+then only check the bytes (if any) that your program didn't read.
+
+(*): If you are not using the standard I/O functions, you will need
+to replace them with custom functions.  See the discussion under
+Customizing libpng.
+
+
+    FILE *fp = fopen(file_name, "rb");
+    if (!fp)
+    {
+        return (ERROR);
+    }
+    fread(header, 1, number, fp);
+    is_png = !png_sig_cmp(header, 0, number);
+    if (!is_png)
+    {
+        return (NOT_PNG);
+    }
+
+
+Next, png_struct and png_info need to be allocated and initialized.  In
+order to ensure that the size of these structures is correct even with a
+dynamically linked libpng, there are functions to initialize and
+allocate the structures.  We also pass the library version, optional
+pointers to error handling functions, and a pointer to a data struct for
+use by the error functions, if necessary (the pointer and functions can
+be NULL if the default error handlers are to be used).  See the section
+on Changes to Libpng below regarding the old initialization functions.
+The structure allocation functions quietly return NULL if they fail to
+create the structure, so your application should check for that.
+
+    png_structp png_ptr = png_create_read_struct
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+        user_error_fn, user_warning_fn);
+    if (!png_ptr)
+        return (ERROR);
+
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr)
+    {
+        png_destroy_read_struct(&png_ptr,
+           (png_infopp)NULL, (png_infopp)NULL);
+        return (ERROR);
+    }
+
+    png_infop end_info = png_create_info_struct(png_ptr);
+    if (!end_info)
+    {
+        png_destroy_read_struct(&png_ptr, &info_ptr,
+          (png_infopp)NULL);
+        return (ERROR);
+    }
+
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_read_struct_2() instead of png_create_read_struct():
+
+    png_structp png_ptr = png_create_read_struct_2
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+        user_error_fn, user_warning_fn, (png_voidp)
+        user_mem_ptr, user_malloc_fn, user_free_fn);
+
+The error handling routines passed to png_create_read_struct()
+and the memory alloc/free routines passed to png_create_struct_2()
+are only necessary if you are not using the libpng supplied error
+handling and memory alloc/free functions.
+
+When libpng encounters an error, it expects to longjmp back
+to your routine.  Therefore, you will need to call setjmp and pass
+your png_jmpbuf(png_ptr).  If you read the file from different
+routines, you will need to update the jmpbuf field every time you enter
+a new routine that will call a png_*() function.
+
+See your documentation of setjmp/longjmp for your compiler for more
+information on setjmp/longjmp.  See the discussion on libpng error
+handling in the Customizing Libpng section below for more information
+on the libpng error handling.  If an error occurs, and libpng longjmp's
+back to your setjmp, you will want to call png_destroy_read_struct() to
+free any memory.
+
+    if (setjmp(png_jmpbuf(png_ptr)))
+    {
+        png_destroy_read_struct(&png_ptr, &info_ptr,
+           &end_info);
+        fclose(fp);
+        return (ERROR);
+    }
+
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
+Now you need to set up the input code.  The default for libpng is to
+use the C function fread().  If you use this, you will need to pass a
+valid FILE * in the function png_init_io().  Be sure that the file is
+opened in binary mode.  If you wish to handle reading data in another
+way, you need not call the png_init_io() function, but you must then
+implement the libpng I/O methods discussed in the Customizing Libpng
+section below.
+
+    png_init_io(png_ptr, fp);
+
+If you had previously opened the file and read any of the signature from
+the beginning in order to see if this was a PNG file, you need to let
+libpng know that there are some bytes missing from the start of the file.
+
+    png_set_sig_bytes(png_ptr, number);
+
+.SS Setting up callback code
+
+You can set up a callback function to handle any unknown chunks in the
+input stream. You must supply the function
+
+    read_chunk_callback(png_ptr ptr,
+         png_unknown_chunkp chunk);
+    {
+       /* The unknown chunk structure contains your
+          chunk data: */
+           png_byte name[5];
+           png_byte *data;
+           png_size_t size;
+       /* Note that libpng has already taken care of
+          the CRC handling */
+
+       /* put your code here.  Return one of the
+          following: */
+
+       return (-n); /* chunk had an error */
+       return (0); /* did not recognize */
+       return (n); /* success */
+    }
+
+(You can give your function another name that you like instead of
+"read_chunk_callback")
+
+To inform libpng about your function, use
+
+    png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr,
+        read_chunk_callback);
+
+This names not only the callback function, but also a user pointer that
+you can retrieve with
+
+    png_get_user_chunk_ptr(png_ptr);
+
+At this point, you can set up a callback function that will be
+called after each row has been read, which you can use to control
+a progress meter or the like.  It's demonstrated in pngtest.c.
+You must supply a function
+
+    void read_row_callback(png_ptr ptr, png_uint_32 row,
+       int pass);
+    {
+      /* put your code here */
+    }
+
+(You can give it another name that you like instead of "read_row_callback")
+
+To inform libpng about your function, use
+
+    png_set_read_status_fn(png_ptr, read_row_callback);
+
+.SS Unknown-chunk handling
+
+Now you get to set the way the library processes unknown chunks in the
+input PNG stream. Both known and unknown chunks will be read.  Normal
+behavior is that known chunks will be parsed into information in
+various info_ptr members; unknown chunks will be discarded. To change
+this, you can call:
+
+    png_set_keep_unknown_chunks(png_ptr, info_ptr, keep,
+        chunk_list, num_chunks);
+    keep       - 0: do not keep
+                 1: keep only if safe-to-copy
+                 2: keep even if unsafe-to-copy
+    chunk_list - list of chunks affected (a byte string,
+                 five bytes per chunk, NULL or '\0' if
+                 num_chunks is 0)
+    num_chunks - number of chunks affected; if 0, all
+                 unknown chunks are affected
+
+Unknown chunks declared in this way will be saved as raw data onto a
+list of png_unknown_chunk structures.  If a chunk that is normally
+known to libpng is named in the list, it will be handled as unknown,
+according to the "keep" directive.  If a chunk is named in successive
+instances of png_set_keep_unknown_chunks(), the final instance will
+take precedence.
+
+.SS The high-level read interface
+
+At this point there are two ways to proceed; through the high-level
+read interface, or through a sequence of low-level read operations.
+You can use the high-level interface if (a) you are willing to read
+the entire image into memory, and (b) the input transformations
+you want to do are limited to the following set:
+
+    PNG_TRANSFORM_IDENTITY      No transformation
+    PNG_TRANSFORM_STRIP_16      Strip 16-bit samples to
+                                8 bits
+    PNG_TRANSFORM_STRIP_ALPHA   Discard the alpha channel
+    PNG_TRANSFORM_PACKING       Expand 1, 2 and 4-bit
+                                samples to bytes
+    PNG_TRANSFORM_PACKSWAP      Change order of packed
+                                pixels to LSB first
+    PNG_TRANSFORM_EXPAND        Perform set_expand()
+    PNG_TRANSFORM_INVERT_MONO   Invert monochrome images
+    PNG_TRANSFORM_SHIFT         Normalize pixels to the
+                                sBIT depth
+    PNG_TRANSFORM_BGR           Flip RGB to BGR, RGBA
+                                to BGRA
+    PNG_TRANSFORM_SWAP_ALPHA    Flip RGBA to ARGB or GA
+                                to AG
+    PNG_TRANSFORM_INVERT_ALPHA  Change alpha from opacity
+                                to transparency
+    PNG_TRANSFORM_SWAP_ENDIAN   Byte-swap 16-bit samples
+
+(This excludes setting a background color, doing gamma transformation,
+dithering, and setting filler.)  If this is the case, simply do this:
+
+    png_read_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the logical OR of
+some set of transformation flags.  This call is equivalent to png_read_info(),
+followed the set of transformations indicated by the transform mask,
+then png_read_image(), and finally png_read_end().
+
+(The final parameter of this call is not yet used.  Someday it might point
+to transformation parameters required by some future input transform.)
+
+After you have called png_read_png(), you can retrieve the image data
+with
+
+   row_pointers = png_get_rows(png_ptr, info_ptr);
+
+where row_pointers is an array of pointers to the pixel data for each row:
+
+   png_bytep row_pointers[height];
+
+If you know your image size and pixel size ahead of time, you can allocate
+row_pointers prior to calling png_read_png() with
+
+   row_pointers = png_malloc(png_ptr,
+      height*sizeof(png_bytep));
+   for (int i=0; i<height, i++)
+      row_pointers[i]=png_malloc(png_ptr,
+         width*pixel_size);
+   png_set_rows(png_ptr, info_ptr, &row_pointers);
+
+Alternatively you could allocate your image in one big block and define
+row_pointers[i] to point into the proper places in your block.
+
+If you use png_set_rows(), the application is responsible for freeing
+row_pointers (and row_pointers[i], if they were separately allocated).
+
+If you don't allocate row_pointers ahead of time, png_read_png() will
+do it, and it'll be free'ed when you call png_destroy_*().
+
+.SS The low-level read interface
+
+If you are going the low-level route, you are now ready to read all
+the file information up to the actual image data.  You do this with a
+call to png_read_info().
+
+    png_read_info(png_ptr, info_ptr);
+
+This will process all chunks up to but not including the image data.
+
+.SS Querying the info structure
+
+Functions are used to get the information from the info_ptr once it
+has been read.  Note that these fields may not be completely filled
+in until png_read_end() has read the chunk data following the image.
+
+    png_get_IHDR(png_ptr, info_ptr, &width, &height,
+       &bit_depth, &color_type, &interlace_type,
+       &compression_type, &filter_method);
+
+    width          - holds the width of the image
+                     in pixels (up to 2^31).
+    height         - holds the height of the image
+                     in pixels (up to 2^31).
+    bit_depth      - holds the bit depth of one of the
+                     image channels.  (valid values are
+                     1, 2, 4, 8, 16 and depend also on
+                     the color_type.  See also
+                     significant bits (sBIT) below).
+    color_type     - describes which color/alpha channels
+                         are present.
+                     PNG_COLOR_TYPE_GRAY
+                        (bit depths 1, 2, 4, 8, 16)
+                     PNG_COLOR_TYPE_GRAY_ALPHA
+                        (bit depths 8, 16)
+                     PNG_COLOR_TYPE_PALETTE
+                        (bit depths 1, 2, 4, 8)
+                     PNG_COLOR_TYPE_RGB
+                        (bit_depths 8, 16)
+                     PNG_COLOR_TYPE_RGB_ALPHA
+                        (bit_depths 8, 16)
+
+                     PNG_COLOR_MASK_PALETTE
+                     PNG_COLOR_MASK_COLOR
+                     PNG_COLOR_MASK_ALPHA
+
+    filter_method  - (must be PNG_FILTER_TYPE_BASE
+                     for PNG 1.0, and can also be
+                     PNG_INTRAPIXEL_DIFFERENCING if
+                     the PNG datastream is embedded in
+                     a MNG-1.0 datastream)
+    compression_type - (must be PNG_COMPRESSION_TYPE_BASE
+                     for PNG 1.0)
+    interlace_type - (PNG_INTERLACE_NONE or
+                     PNG_INTERLACE_ADAM7)
+    Any or all of interlace_type, compression_type, of
+    filter_method can be NULL if you are
+    not interested in their values.
+
+    channels = png_get_channels(png_ptr, info_ptr);
+    channels       - number of channels of info for the
+                     color type (valid values are 1 (GRAY,
+                     PALETTE), 2 (GRAY_ALPHA), 3 (RGB),
+                     4 (RGB_ALPHA or RGB + filler byte))
+    rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+    rowbytes       - number of bytes needed to hold a row
+
+    signature = png_get_signature(png_ptr, info_ptr);
+    signature      - holds the signature read from the
+                     file (if any).  The data is kept in
+                     the same offset it would be if the
+                     whole signature were read (i.e. if an
+                     application had already read in 4
+                     bytes of signature before starting
+                     libpng, the remaining 4 bytes would
+                     be in signature[4] through signature[7]
+                     (see png_set_sig_bytes())).
+
+
+    width            = png_get_image_width(png_ptr,
+                         info_ptr);
+    height           = png_get_image_height(png_ptr,
+                         info_ptr);
+    bit_depth        = png_get_bit_depth(png_ptr,
+                         info_ptr);
+    color_type       = png_get_color_type(png_ptr,
+                         info_ptr);
+    filter_method    = png_get_filter_type(png_ptr,
+                         info_ptr);
+    compression_type = png_get_compression_type(png_ptr,
+                         info_ptr);
+    interlace_type   = png_get_interlace_type(png_ptr,
+                         info_ptr);
+
+
+These are also important, but their validity depends on whether the chunk
+has been read.  The png_get_valid(png_ptr, info_ptr, PNG_INFO_<chunk>) and
+png_get_<chunk>(png_ptr, info_ptr, ...) functions return non-zero if the
+data has been read, or zero if it is missing.  The parameters to the
+png_get_<chunk> are set directly if they are simple data types, or a pointer
+into the info_ptr is returned for any complex types.
+
+    png_get_PLTE(png_ptr, info_ptr, &palette,
+                     &num_palette);
+    palette        - the palette for the file
+                     (array of png_color)
+    num_palette    - number of entries in the palette
+
+    png_get_gAMA(png_ptr, info_ptr, &gamma);
+    gamma          - the gamma the file is written
+                     at (PNG_INFO_gAMA)
+
+    png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
+    srgb_intent    - the rendering intent (PNG_INFO_sRGB)
+                     The presence of the sRGB chunk
+                     means that the pixel data is in the
+                     sRGB color space.  This chunk also
+                     implies specific values of gAMA and
+                     cHRM.
+
+    png_get_iCCP(png_ptr, info_ptr, &name,
+       &compression_type, &profile, &proflen);
+    name            - The profile name.
+    compression     - The compression type; always
+                      PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
+                      You may give NULL to this argument to
+                      ignore it.
+    profile         - International Color Consortium color
+                      profile data. May contain NULs.
+    proflen         - length of profile data in bytes.
+
+    png_get_sBIT(png_ptr, info_ptr, &sig_bit);
+    sig_bit        - the number of significant bits for
+                     (PNG_INFO_sBIT) each of the gray,
+                     red, green, and blue channels,
+                     whichever are appropriate for the
+                     given color type (png_color_16)
+
+    png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans,
+                     &trans_values);
+    trans          - array of transparent entries for
+                     palette (PNG_INFO_tRNS)
+    trans_values   - graylevel or color sample values of
+                     the single transparent color for
+                     non-paletted images (PNG_INFO_tRNS)
+    num_trans      - number of transparent entries
+                     (PNG_INFO_tRNS)
+
+    png_get_hIST(png_ptr, info_ptr, &hist);
+                     (PNG_INFO_hIST)
+    hist           - histogram of palette (array of
+                     png_uint_16)
+
+    png_get_tIME(png_ptr, info_ptr, &mod_time);
+    mod_time       - time image was last modified
+                    (PNG_VALID_tIME)
+
+    png_get_bKGD(png_ptr, info_ptr, &background);
+    background     - background color (PNG_VALID_bKGD)
+                     valid 16-bit red, green and blue
+                     values, regardless of color_type
+
+    num_comments   = png_get_text(png_ptr, info_ptr,
+                     &text_ptr, &num_text);
+    num_comments   - number of comments
+    text_ptr       - array of png_text holding image
+                     comments
+    text_ptr[i].compression - type of compression used
+                 on "text" PNG_TEXT_COMPRESSION_NONE
+                           PNG_TEXT_COMPRESSION_zTXt
+                           PNG_ITXT_COMPRESSION_NONE
+                           PNG_ITXT_COMPRESSION_zTXt
+    text_ptr[i].key   - keyword for comment.  Must contain
+                         1-79 characters.
+    text_ptr[i].text  - text comments for current
+                         keyword.  Can be empty.
+    text_ptr[i].text_length - length of text string,
+                 after decompression, 0 for iTXt
+    text_ptr[i].itxt_length - length of itxt string,
+                 after decompression, 0 for tEXt/zTXt
+    text_ptr[i].lang  - language of comment (empty
+                         string for unknown).
+    text_ptr[i].translated_keyword  - keyword in UTF-8
+                         (empty string for unknown).
+    num_text       - number of comments (same as
+                     num_comments; you can put NULL here
+                     to avoid the duplication)
+    Note while png_set_text() will accept text, language,
+    and translated keywords that can be NULL pointers, the
+    structure returned by png_get_text will always contain
+    regular zero-terminated C strings.  They might be
+    empty strings but they will never be NULL pointers.
+
+    num_spalettes = png_get_sPLT(png_ptr, info_ptr,
+       &palette_ptr);
+    palette_ptr    - array of palette structures holding
+                     contents of one or more sPLT chunks
+                     read.
+    num_spalettes  - number of sPLT chunks read.
+
+    png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y,
+       &unit_type);
+    offset_x       - positive offset from the left edge
+                     of the screen
+    offset_y       - positive offset from the top edge
+                     of the screen
+    unit_type      - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
+
+    png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y,
+       &unit_type);
+    res_x          - pixels/unit physical resolution in
+                     x direction
+    res_y          - pixels/unit physical resolution in
+                     x direction
+    unit_type      - PNG_RESOLUTION_UNKNOWN,
+                     PNG_RESOLUTION_METER
+
+    png_get_sCAL(png_ptr, info_ptr, &unit, &width,
+       &height)
+    unit        - physical scale units (an integer)
+    width       - width of a pixel in physical scale units
+    height      - height of a pixel in physical scale units
+                 (width and height are doubles)
+
+    png_get_sCAL_s(png_ptr, info_ptr, &unit, &width,
+       &height)
+    unit        - physical scale units (an integer)
+    width       - width of a pixel in physical scale units
+    height      - height of a pixel in physical scale units
+                 (width and height are strings like "2.54")
+
+    num_unknown_chunks = png_get_unknown_chunks(png_ptr,
+       info_ptr, &unknowns)
+    unknowns          - array of png_unknown_chunk
+                        structures holding unknown chunks
+    unknowns[i].name  - name of unknown chunk
+    unknowns[i].data  - data of unknown chunk
+    unknowns[i].size  - size of unknown chunk's data
+    unknowns[i].location - position of chunk in file
+
+    The value of "i" corresponds to the order in which the
+    chunks were read from the PNG file or inserted with the
+    png_set_unknown_chunks() function.
+
+The data from the pHYs chunk can be retrieved in several convenient
+forms:
+
+    res_x = png_get_x_pixels_per_meter(png_ptr,
+       info_ptr)
+    res_y = png_get_y_pixels_per_meter(png_ptr,
+       info_ptr)
+    res_x_and_y = png_get_pixels_per_meter(png_ptr,
+       info_ptr)
+    res_x = png_get_x_pixels_per_inch(png_ptr,
+       info_ptr)
+    res_y = png_get_y_pixels_per_inch(png_ptr,
+       info_ptr)
+    res_x_and_y = png_get_pixels_per_inch(png_ptr,
+       info_ptr)
+    aspect_ratio = png_get_pixel_aspect_ratio(png_ptr,
+       info_ptr)
+
+   (Each of these returns 0 [signifying "unknown"] if
+       the data is not present or if res_x is 0;
+       res_x_and_y is 0 if res_x != res_y)
+
+The data from the oFFs chunk can be retrieved in several convenient
+forms:
+
+    x_offset = png_get_x_offset_microns(png_ptr, info_ptr);
+    y_offset = png_get_y_offset_microns(png_ptr, info_ptr);
+    x_offset = png_get_x_offset_inches(png_ptr, info_ptr);
+    y_offset = png_get_y_offset_inches(png_ptr, info_ptr);
+
+   (Each of these returns 0 [signifying "unknown" if both
+       x and y are 0] if the data is not present or if the
+       chunk is present but the unit is the pixel)
+
+For more information, see the png_info definition in png.h and the
+PNG specification for chunk contents.  Be careful with trusting
+rowbytes, as some of the transformations could increase the space
+needed to hold a row (expand, filler, gray_to_rgb, etc.).
+See png_read_update_info(), below.
+
+A quick word about text_ptr and num_text.  PNG stores comments in
+keyword/text pairs, one pair per chunk, with no limit on the number
+of text chunks, and a 2^31 byte limit on their size.  While there are
+suggested keywords, there is no requirement to restrict the use to these
+strings.  It is strongly suggested that keywords and text be sensible
+to humans (that's the point), so don't use abbreviations.  Non-printing
+symbols are not allowed.  See the PNG specification for more details.
+There is also no requirement to have text after the keyword.
+
+Keywords should be limited to 79 Latin-1 characters without leading or
+trailing spaces, but non-consecutive spaces are allowed within the
+keyword.  It is possible to have the same keyword any number of times.
+The text_ptr is an array of png_text structures, each holding a
+pointer to a language string, a pointer to a keyword and a pointer to
+a text string.  The text string, language code, and translated
+keyword may be empty or NULL pointers.  The keyword/text
+pairs are put into the array in the order that they are received.
+However, some or all of the text chunks may be after the image, so, to
+make sure you have read all the text chunks, don't mess with these
+until after you read the stuff after the image.  This will be
+mentioned again below in the discussion that goes with png_read_end().
+
+.SS Input transformations
+
+After you've read the header information, you can set up the library
+to handle any special transformations of the image data.  The various
+ways to transform the data will be described in the order that they
+should occur.  This is important, as some of these change the color
+type and/or bit depth of the data, and some others only work on
+certain color types and bit depths.  Even though each transformation
+checks to see if it has data that it can do something with, you should
+make sure to only enable a transformation if it will be valid for the
+data.  For example, don't swap red and blue on grayscale data.
+
+The colors used for the background and transparency values should be
+supplied in the same format/depth as the current image data.  They
+are stored in the same format/depth as the image data in a bKGD or tRNS
+chunk, so this is what libpng expects for this data.  The colors are
+transformed to keep in sync with the image data when an application
+calls the png_read_update_info() routine (see below).
+
+Data will be decoded into the supplied row buffers packed into bytes
+unless the library has been told to transform it into another format.
+For example, 4 bit/pixel paletted or grayscale data will be returned
+2 pixels/byte with the leftmost pixel in the high-order bits of the
+byte, unless png_set_packing() is called.  8-bit RGB data will be stored
+in RGB RGB RGB format unless png_set_filler() is called to insert filler
+bytes, either before or after each RGB triplet.  16-bit RGB data will
+be returned RRGGBB RRGGBB, with the most significant byte of the color
+value first, unless png_set_strip_16() is called to transform it to
+regular RGB RGB triplets, or png_set_filler() is called to insert
+filler bytes, either before or after each RRGGBB triplet.  Similarly,
+8-bit or 16-bit grayscale data can be modified with png_set_filler()
+or png_set_strip_16().
+
+The following code transforms grayscale images of less than 8 to 8 bits,
+changes paletted images to RGB, and adds a full alpha channel if there is
+transparency information in a tRNS chunk.  This is most useful on
+grayscale images with bit depths of 2 or 4 or if there is a multiple-image
+viewing application that wishes to treat all images in the same way.
+
+    if (color_type == PNG_COLOR_TYPE_PALETTE)
+        png_set_palette_to_rgb(png_ptr);
+
+    if (color_type == PNG_COLOR_TYPE_GRAY &&
+        bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);
+
+    if (png_get_valid(png_ptr, info_ptr,
+        PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
+
+These three functions are actually aliases for png_set_expand(), added
+in libpng version 1.0.4, with the function names expanded to improve code
+readability.  In some future version they may actually do different
+things.
+
+PNG can have files with 16 bits per channel.  If you only can handle
+8 bits per channel, this will strip the pixels down to 8 bit.
+
+    if (bit_depth == 16)
+        png_set_strip_16(png_ptr);
+
+If, for some reason, you don't need the alpha channel on an image,
+and you want to remove it rather than combining it with the background
+(but the image author certainly had in mind that you *would* combine
+it with the background, so that's what you should probably do):
+
+    if (color_type & PNG_COLOR_MASK_ALPHA)
+        png_set_strip_alpha(png_ptr);
+
+In PNG files, the alpha channel in an image
+is the level of opacity.  If you need the alpha channel in an image to
+be the level of transparency instead of opacity, you can invert the
+alpha channel (or the tRNS chunk data) after it's read, so that 0 is
+fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit
+images) is fully transparent, with
+
+    png_set_invert_alpha(png_ptr);
+
+PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
+they can, resulting in, for example, 8 pixels per byte for 1 bit
+files.  This code expands to 1 pixel per byte without changing the
+values of the pixels:
+
+    if (bit_depth < 8)
+        png_set_packing(png_ptr);
+
+PNG files have possible bit depths of 1, 2, 4, 8, and 16.  All pixels
+stored in a PNG image have been "scaled" or "shifted" up to the next
+higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] to
+8 bits/sample in the range [0, 255]).  However, it is also possible to
+convert the PNG pixel data back to the original bit depth of the image.
+This call reduces the pixels back down to the original bit depth:
+
+    png_color_8p sig_bit;
+
+    if (png_get_sBIT(png_ptr, info_ptr, &sig_bit))
+        png_set_shift(png_ptr, sig_bit);
+
+PNG files store 3-color pixels in red, green, blue order.  This code
+changes the storage of the pixels to blue, green, red:
+
+    if (color_type == PNG_COLOR_TYPE_RGB ||
+        color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+        png_set_bgr(png_ptr);
+
+PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them
+into 4 or 8 bytes for windowing systems that need them in this format:
+
+    if (color_type == PNG_COLOR_TYPE_RGB)
+        png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE);
+
+where "filler" is the 8 or 16-bit number to fill with, and the location is
+either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether
+you want the filler before the RGB or after.  This transformation
+does not affect images that already have full alpha channels.  To add an
+opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which
+will generate RGBA pixels.
+
+If you are reading an image with an alpha channel, and you need the
+data as ARGB instead of the normal PNG format RGBA:
+
+    if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+        png_set_swap_alpha(png_ptr);
+
+For some uses, you may want a grayscale image to be represented as
+RGB.  This code will do that conversion:
+
+    if (color_type == PNG_COLOR_TYPE_GRAY ||
+        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+          png_set_gray_to_rgb(png_ptr);
+
+Conversely, you can convert an RGB or RGBA image to grayscale or grayscale
+with alpha.
+
+    if (color_type == PNG_COLOR_TYPE_RGB ||
+        color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+          png_set_rgb_to_gray_fixed(png_ptr, error_action,
+             int red_weight, int green_weight);
+
+    error_action = 1: silently do the conversion
+    error_action = 2: issue a warning if the original
+                      image has any pixel where
+                      red != green or red != blue
+    error_action = 3: issue an error and abort the
+                      conversion if the original
+                      image has any pixel where
+                      red != green or red != blue
+
+    red_weight:       weight of red component times 100000
+    green_weight:     weight of green component times 100000
+                      If either weight is negative, default
+                      weights (21268, 71514) are used.
+
+If you have set error_action = 1 or 2, you can
+later check whether the image really was gray, after processing
+the image rows, with the png_get_rgb_to_gray_status(png_ptr) function.
+It will return a png_byte that is zero if the image was gray or
+1 if there were any non-gray pixels.  bKGD and sBIT data
+will be silently converted to grayscale, using the green channel
+data, regardless of the error_action setting.
+
+With red_weight+green_weight<=100000,
+the normalized graylevel is computed:
+
+    int rw = red_weight * 65536;
+    int gw = green_weight * 65536;
+    int bw = 65536 - (rw + gw);
+    gray = (rw*red + gw*green + bw*blue)/65536;
+
+The default values approximate those recommended in the Charles
+Poynton's Color FAQ, <http://www.inforamp.net/~poynton/>
+Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
+
+    Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+
+Libpng approximates this with
+
+    Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
+
+which can be expressed with integers as
+
+    Y = (6969 * R + 23434 * G + 2365 * B)/32768
+
+The calculation is done in a linear colorspace, if the image gamma
+is known.
+
+If you have a grayscale and you are using png_set_expand_depth() or
+png_set_expand() to change to
+a higher bit-depth, you must either supply the background color as a gray
+value at the original file bit-depth (need_expand = 1) or else supply the
+background color as an RGB triplet at the final, expanded bit depth
+(need_expand = 0).  Similarly, if you are reading a paletted image, you
+must either supply the background color as a palette index (need_expand = 1)
+or as an RGB triplet that may or may not be in the palette (need_expand = 0).
+
+    png_color_16 my_background;
+    png_color_16p image_background;
+
+    if (png_get_bKGD(png_ptr, info_ptr, &image_background))
+        png_set_background(png_ptr, image_background,
+          PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+    else
+        png_set_background(png_ptr, &my_background,
+          PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+
+The png_set_background() function tells libpng to composite images
+with alpha or simple transparency against the supplied background
+color.  If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid),
+you may use this color, or supply another color more suitable for
+the current display (e.g., the background color from a web page).  You
+need to tell libpng whether the color is in the gamma space of the
+display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file
+(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one
+that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't
+know why anyone would use this, but it's here).
+
+To properly display PNG images on any kind of system, the application needs
+to know what the display gamma is.  Ideally, the user will know this, and
+the application will allow them to set it.  One method of allowing the user
+to set the display gamma separately for each system is to check for a
+SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be
+correctly set.
+
+Note that display_gamma is the overall gamma correction required to produce
+pleasing results, which depends on the lighting conditions in the surrounding
+environment.  In a dim or brightly lit room, no compensation other than
+the physical gamma exponent of the monitor is needed, while in a dark room
+a slightly smaller exponent is better.
+
+   double gamma, screen_gamma;
+
+   if (/* We have a user-defined screen
+       gamma value */)
+   {
+      screen_gamma = user_defined_screen_gamma;
+   }
+   /* One way that applications can share the same
+      screen gamma value */
+   else if ((gamma_str = getenv("SCREEN_GAMMA"))
+      != NULL)
+   {
+      screen_gamma = (double)atof(gamma_str);
+   }
+   /* If we don't have another value */
+   else
+   {
+      screen_gamma = 2.2; /* A good guess for a
+           PC monitor in a bright office or a dim room */
+      screen_gamma = 2.0; /* A good guess for a
+           PC monitor in a dark room */
+      screen_gamma = 1.7 or 1.0;  /* A good
+           guess for Mac systems */
+   }
+
+The png_set_gamma() function handles gamma transformations of the data.
+Pass both the file gamma and the current screen_gamma.  If the file does
+not have a gamma value, you can pass one anyway if you have an idea what
+it is (usually 0.45455 is a good guess for GIF images on PCs).  Note
+that file gammas are inverted from screen gammas.  See the discussions
+on gamma in the PNG specification for an excellent description of what
+gamma is, and why all applications should support it.  It is strongly
+recommended that PNG viewers support gamma correction.
+
+   if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+      png_set_gamma(png_ptr, screen_gamma, gamma);
+   else
+      png_set_gamma(png_ptr, screen_gamma, 0.45455);
+
+If you need to reduce an RGB file to a paletted file, or if a paletted
+file has more entries then will fit on your screen, png_set_dither()
+will do that.  Note that this is a simple match dither that merely
+finds the closest color available.  This should work fairly well with
+optimized palettes, and fairly badly with linear color cubes.  If you
+pass a palette that is larger then maximum_colors, the file will
+reduce the number of colors in the palette so it will fit into
+maximum_colors.  If there is a histogram, it will use it to make
+more intelligent choices when reducing the palette.  If there is no
+histogram, it may not do as good a job.
+
+   if (color_type & PNG_COLOR_MASK_COLOR)
+   {
+      if (png_get_valid(png_ptr, info_ptr,
+         PNG_INFO_PLTE))
+      {
+         png_uint_16p histogram;
+
+         png_get_hIST(png_ptr, info_ptr,
+            &histogram);
+         png_set_dither(png_ptr, palette, num_palette,
+            max_screen_colors, histogram, 1);
+      }
+      else
+      {
+         png_color std_color_cube[MAX_SCREEN_COLORS] =
+            { ... colors ... };
+
+         png_set_dither(png_ptr, std_color_cube,
+            MAX_SCREEN_COLORS, MAX_SCREEN_COLORS,
+            NULL,0);
+      }
+   }
+
+PNG files describe monochrome as black being zero and white being one.
+The following code will reverse this (make black be one and white be
+zero):
+
+   if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY)
+      png_set_invert_mono(png_ptr);
+
+This function can also be used to invert grayscale and gray-alpha images:
+
+   if (color_type == PNG_COLOR_TYPE_GRAY ||
+        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      png_set_invert_mono(png_ptr);
+
+PNG files store 16 bit pixels in network byte order (big-endian,
+ie. most significant bits first).  This code changes the storage to the
+other way (little-endian, i.e. least significant bits first, the
+way PCs store them):
+
+    if (bit_depth == 16)
+        png_set_swap(png_ptr);
+
+If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
+need to change the order the pixels are packed into bytes, you can use:
+
+    if (bit_depth < 8)
+       png_set_packswap(png_ptr);
+
+Finally, you can write your own transformation function if none of
+the existing ones meets your needs.  This is done by setting a callback
+with
+
+    png_set_read_user_transform_fn(png_ptr,
+       read_transform_fn);
+
+You must supply the function
+
+    void read_transform_fn(png_ptr ptr, row_info_ptr
+       row_info, png_bytep data)
+
+See pngtest.c for a working example.  Your function will be called
+after all of the other transformations have been processed.
+
+You can also set up a pointer to a user structure for use by your
+callback function, and you can inform libpng that your transform
+function will change the number of channels or bit depth with the
+function
+
+    png_set_user_transform_info(png_ptr, user_ptr,
+       user_depth, user_channels);
+
+The user's application, not libpng, is responsible for allocating and
+freeing any memory required for the user structure.
+
+You can retrieve the pointer via the function
+png_get_user_transform_ptr().  For example:
+
+    voidp read_user_transform_ptr =
+       png_get_user_transform_ptr(png_ptr);
+
+The last thing to handle is interlacing; this is covered in detail below,
+but you must call the function here if you want libpng to handle expansion
+of the interlaced image.
+
+    number_of_passes = png_set_interlace_handling(png_ptr);
+
+After setting the transformations, libpng can update your png_info
+structure to reflect any transformations you've requested with this
+call.  This is most useful to update the info structure's rowbytes
+field so you can use it to allocate your image memory.  This function
+will also update your palette with the correct screen_gamma and
+background if these have been given with the calls above.
+
+    png_read_update_info(png_ptr, info_ptr);
+
+After you call png_read_update_info(), you can allocate any
+memory you need to hold the image.  The row data is simply
+raw byte data for all forms of images.  As the actual allocation
+varies among applications, no example will be given.  If you
+are allocating one large chunk, you will need to build an
+array of pointers to each row, as it will be needed for some
+of the functions below.
+
+.SS Reading image data
+
+After you've allocated memory, you can read the image data.
+The simplest way to do this is in one function call.  If you are
+allocating enough memory to hold the whole image, you can just
+call png_read_image() and libpng will read in all the image data
+and put it in the memory area supplied.  You will need to pass in
+an array of pointers to each row.
+
+This function automatically handles interlacing, so you don't need
+to call png_set_interlace_handling() or call this function multiple
+times, or any of that other stuff necessary with png_read_rows().
+
+   png_read_image(png_ptr, row_pointers);
+
+where row_pointers is:
+
+   png_bytep row_pointers[height];
+
+You can point to void or char or whatever you use for pixels.
+
+If you don't want to read in the whole image at once, you can
+use png_read_rows() instead.  If there is no interlacing (check
+interlace_type == PNG_INTERLACE_NONE), this is simple:
+
+    png_read_rows(png_ptr, row_pointers, NULL,
+       number_of_rows);
+
+where row_pointers is the same as in the png_read_image() call.
+
+If you are doing this just one row at a time, you can do this with
+a single row_pointer instead of an array of row_pointers:
+
+    png_bytep row_pointer = row;
+    png_read_row(png_ptr, row_pointer, NULL);
+
+If the file is interlaced (interlace_type != 0 in the IHDR chunk), things
+get somewhat harder.  The only current (PNG Specification version 1.2)
+interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7)
+is a somewhat complicated 2D interlace scheme, known as Adam7, that
+breaks down an image into seven smaller images of varying size, based
+on an 8x8 grid.
+
+libpng can fill out those images or it can give them to you "as is".
+If you want them filled out, there are two ways to do that.  The one
+mentioned in the PNG specification is to expand each pixel to cover
+those pixels that have not been read yet (the "rectangle" method).
+This results in a blocky image for the first pass, which gradually
+smooths out as more pixels are read.  The other method is the "sparkle"
+method, where pixels are drawn only in their final locations, with the
+rest of the image remaining whatever colors they were initialized to
+before the start of the read.  The first method usually looks better,
+but tends to be slower, as there are more pixels to put in the rows.
+
+If you don't want libpng to handle the interlacing details, just call
+png_read_rows() seven times to read in all seven images.  Each of the
+images is a valid image by itself, or they can all be combined on an
+8x8 grid to form a single image (although if you intend to combine them
+you would be far better off using the libpng interlace handling).
+
+The first pass will return an image 1/8 as wide as the entire image
+(every 8th column starting in column 0) and 1/8 as high as the original
+(every 8th row starting in row 0), the second will be 1/8 as wide
+(starting in column 4) and 1/8 as high (also starting in row 0).  The
+third pass will be 1/4 as wide (every 4th pixel starting in column 0) and
+1/8 as high (every 8th row starting in row 4), and the fourth pass will
+be 1/4 as wide and 1/4 as high (every 4th column starting in column 2,
+and every 4th row starting in row 0).  The fifth pass will return an
+image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2),
+while the sixth pass will be 1/2 as wide and 1/2 as high as the original
+(starting in column 1 and row 0).  The seventh and final pass will be as
+wide as the original, and 1/2 as high, containing all of the odd
+numbered scanlines.  Phew!
+
+If you want libpng to expand the images, call this before calling
+png_start_read_image() or png_read_update_info():
+
+    if (interlace_type == PNG_INTERLACE_ADAM7)
+        number_of_passes
+           = png_set_interlace_handling(png_ptr);
+
+This will return the number of passes needed.  Currently, this
+is seven, but may change if another interlace type is added.
+This function can be called even if the file is not interlaced,
+where it will return one pass.
+
+If you are not going to display the image after each pass, but are
+going to wait until the entire image is read in, use the sparkle
+effect.  This effect is faster and the end result of either method
+is exactly the same.  If you are planning on displaying the image
+after each pass, the "rectangle" effect is generally considered the
+better looking one.
+
+If you only want the "sparkle" effect, just call png_read_rows() as
+normal, with the third parameter NULL.  Make sure you make pass over
+the image number_of_passes times, and you don't change the data in the
+rows between calls.  You can change the locations of the data, just
+not the data.  Each pass only writes the pixels appropriate for that
+pass, and assumes the data from previous passes is still valid.
+
+    png_read_rows(png_ptr, row_pointers, NULL,
+       number_of_rows);
+
+If you only want the first effect (the rectangles), do the same as
+before except pass the row buffer in the third parameter, and leave
+the second parameter NULL.
+
+    png_read_rows(png_ptr, NULL, row_pointers,
+       number_of_rows);
+
+.SS Finishing a sequential read
+
+After you are finished reading the image through either the high- or
+low-level interfaces, you can finish reading the file.  If you are
+interested in comments or time, which may be stored either before or
+after the image data, you should pass the separate png_info struct if
+you want to keep the comments from before and after the image
+separate.  If you are not interested, you can pass NULL.
+
+   png_read_end(png_ptr, end_info);
+
+When you are done, you can free all memory allocated by libpng like this:
+
+   png_destroy_read_struct(&png_ptr, &info_ptr,
+       &end_info);
+
+It is also possible to individually free the info_ptr members that
+point to libpng-allocated storage with the following function:
+
+    png_free_data(png_ptr, info_ptr, mask, seq)
+    mask - identifies data to be freed, a mask
+           containing the logical OR of one or
+           more of
+             PNG_FREE_PLTE, PNG_FREE_TRNS,
+             PNG_FREE_HIST, PNG_FREE_ICCP,
+             PNG_FREE_PCAL, PNG_FREE_ROWS,
+             PNG_FREE_SCAL, PNG_FREE_SPLT,
+             PNG_FREE_TEXT, PNG_FREE_UNKN,
+           or simply PNG_FREE_ALL
+    seq  - sequence number of item to be freed
+           (-1 for all items)
+
+This function may be safely called when the relevant storage has
+already been freed, or has not yet been allocated, or was allocated
+by the user and not by libpng,  and will in those
+cases do nothing.  The "seq" parameter is ignored if only one item
+of the selected data type, such as PLTE, is allowed.  If "seq" is not
+-1, and multiple items are allowed for the data type identified in
+the mask, such as text or sPLT, only the n'th item in the structure
+is freed, where n is "seq".
+
+The default behavior is only to free data that was allocated internally
+by libpng.  This can be changed, so that libpng will not free the data,
+or so that it will free data that was allocated by the user with png_malloc()
+or png_zalloc() and passed in via a png_set_*() function, with
+
+    png_data_freer(png_ptr, info_ptr, freer, mask)
+    mask   - which data elements are affected
+             same choices as in png_free_data()
+    freer  - one of
+               PNG_DESTROY_WILL_FREE_DATA
+               PNG_SET_WILL_FREE_DATA
+               PNG_USER_WILL_FREE_DATA
+
+This function only affects data that has already been allocated.
+You can call this function after reading the PNG data but before calling
+any png_set_*() functions, to control whether the user or the png_set_*()
+function is responsible for freeing any existing data that might be present,
+and again after the png_set_*() functions to control whether the user
+or png_destroy_*() is supposed to free the data.  When the user assumes
+responsibility for libpng-allocated data, the application must use
+png_free() to free it, and when the user transfers responsibility to libpng
+for data that the user has allocated, the user must have used png_malloc()
+or png_zalloc() to allocate it.
+
+If you allocated your row_pointers in a single block, as suggested above in
+the description of the high level read interface, you must not transfer
+responsibility for freeing it to the png_set_rows or png_read_destroy function,
+because they would also try to free the individual row_pointers[i].
+
+If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
+separately, do not transfer responsibility for freeing text_ptr to libpng,
+because when libpng fills a png_text structure it combines these members with
+the key member, and png_free_data() will free only text_ptr.key.  Similarly,
+if you transfer responsibility for free'ing text_ptr from libpng to your
+application, your application must not separately free those members.
+
+The png_free_data() function will turn off the "valid" flag for anything
+it frees.  If you need to turn the flag off for a chunk that was freed by your
+application instead of by libpng, you can use
+
+    png_set_invalid(png_ptr, info_ptr, mask);
+    mask - identifies the chunks to be made invalid,
+           containing the logical OR of one or
+           more of
+             PNG_INFO_gAMA, PNG_INFO_sBIT,
+             PNG_INFO_cHRM, PNG_INFO_PLTE,
+             PNG_INFO_tRNS, PNG_INFO_bKGD,
+             PNG_INFO_hIST, PNG_INFO_pHYs,
+             PNG_INFO_oFFs, PNG_INFO_tIME,
+             PNG_INFO_pCAL, PNG_INFO_sRGB,
+             PNG_INFO_iCCP, PNG_INFO_sPLT,
+             PNG_INFO_sCAL, PNG_INFO_IDAT
+
+For a more compact example of reading a PNG image, see the file example.c.
+
+.SS Reading PNG files progressively
+
+The progressive reader is slightly different then the non-progressive
+reader.  Instead of calling png_read_info(), png_read_rows(), and
+png_read_end(), you make one call to png_process_data(), which calls
+callbacks when it has the info, a row, or the end of the image.  You
+set up these callbacks with png_set_progressive_read_fn().  You don't
+have to worry about the input/output functions of libpng, as you are
+giving the library the data directly in png_process_data().  I will
+assume that you have read the section on reading PNG files above,
+so I will only highlight the differences (although I will show
+all of the code).
+
+png_structp png_ptr;
+png_infop info_ptr;
+
+ /*  An example code fragment of how you would
+     initialize the progressive reader in your
+     application. */
+ int
+ initialize_png_reader()
+ {
+    png_ptr = png_create_read_struct
+        (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+         user_error_fn, user_warning_fn);
+    if (!png_ptr)
+        return (ERROR);
+    info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr)
+    {
+        png_destroy_read_struct(&png_ptr, (png_infopp)NULL,
+           (png_infopp)NULL);
+        return (ERROR);
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr)))
+    {
+        png_destroy_read_struct(&png_ptr, &info_ptr,
+           (png_infopp)NULL);
+        return (ERROR);
+    }
+
+    /* This one's new.  You can provide functions
+       to be called when the header info is valid,
+       when each row is completed, and when the image
+       is finished.  If you aren't using all functions,
+       you can specify NULL parameters.  Even when all
+       three functions are NULL, you need to call
+       png_set_progressive_read_fn().  You can use
+       any struct as the user_ptr (cast to a void pointer
+       for the function call), and retrieve the pointer
+       from inside the callbacks using the function
+
+          png_get_progressive_ptr(png_ptr);
+
+       which will return a void pointer, which you have
+       to cast appropriately.
+     */
+    png_set_progressive_read_fn(png_ptr, (void *)user_ptr,
+        info_callback, row_callback, end_callback);
+
+    return 0;
+ }
+
+ /* A code fragment that you call as you receive blocks
+   of data */
+ int
+ process_data(png_bytep buffer, png_uint_32 length)
+ {
+    if (setjmp(png_jmpbuf(png_ptr)))
+    {
+        png_destroy_read_struct(&png_ptr, &info_ptr,
+           (png_infopp)NULL);
+        return (ERROR);
+    }
+
+    /* This one's new also.  Simply give it a chunk
+       of data from the file stream (in order, of
+       course).  On machines with segmented memory
+       models machines, don't give it any more than
+       64K.  The library seems to run fine with sizes
+       of 4K. Although you can give it much less if
+       necessary (I assume you can give it chunks of
+       1 byte, I haven't tried less then 256 bytes
+       yet).  When this function returns, you may
+       want to display any rows that were generated
+       in the row callback if you don't already do
+       so there.
+     */
+    png_process_data(png_ptr, info_ptr, buffer, length);
+    return 0;
+ }
+
+ /* This function is called (as set by
+    png_set_progressive_read_fn() above) when enough data
+    has been supplied so all of the header has been
+    read.
+ */
+ void
+ info_callback(png_structp png_ptr, png_infop info)
+ {
+    /* Do any setup here, including setting any of
+       the transformations mentioned in the Reading
+       PNG files section.  For now, you _must_ call
+       either png_start_read_image() or
+       png_read_update_info() after all the
+       transformations are set (even if you don't set
+       any).  You may start getting rows before
+       png_process_data() returns, so this is your
+       last chance to prepare for that.
+     */
+ }
+
+ /* This function is called when each row of image
+    data is complete */
+ void
+ row_callback(png_structp png_ptr, png_bytep new_row,
+    png_uint_32 row_num, int pass)
+ {
+    /* If the image is interlaced, and you turned
+       on the interlace handler, this function will
+       be called for every row in every pass.  Some
+       of these rows will not be changed from the
+       previous pass.  When the row is not changed,
+       the new_row variable will be NULL.  The rows
+       and passes are called in order, so you don't
+       really need the row_num and pass, but I'm
+       supplying them because it may make your life
+       easier.
+
+       For the non-NULL rows of interlaced images,
+       you must call png_progressive_combine_row()
+       passing in the row and the old row.  You can
+       call this function for NULL rows (it will just
+       return) and for non-interlaced images (it just
+       does the memcpy for you) if it will make the
+       code easier.  Thus, you can just do this for
+       all cases:
+     */
+
+        png_progressive_combine_row(png_ptr, old_row,
+          new_row);
+
+    /* where old_row is what was displayed for
+       previously for the row.  Note that the first
+       pass (pass == 0, really) will completely cover
+       the old row, so the rows do not have to be
+       initialized.  After the first pass (and only
+       for interlaced images), you will have to pass
+       the current row, and the function will combine
+       the old row and the new row.
+    */
+ }
+
+ void
+ end_callback(png_structp png_ptr, png_infop info)
+ {
+    /* This function is called after the whole image
+       has been read, including any chunks after the
+       image (up to and including the IEND).  You
+       will usually have the same info chunk as you
+       had in the header, although some data may have
+       been added to the comments and time fields.
+
+       Most people won't do much here, perhaps setting
+       a flag that marks the image as finished.
+     */
+ }
+
+
+
+.SH IV. Writing
+
+Much of this is very similar to reading.  However, everything of
+importance is repeated here, so you won't have to constantly look
+back up in the reading section to understand writing.
+
+.SS Setup
+
+You will want to do the I/O initialization before you get into libpng,
+so if it doesn't work, you don't have anything to undo. If you are not
+using the standard I/O functions, you will need to replace them with
+custom writing functions.  See the discussion under Customizing libpng.
+
+    FILE *fp = fopen(file_name, "wb");
+    if (!fp)
+    {
+       return (ERROR);
+    }
+
+Next, png_struct and png_info need to be allocated and initialized.
+As these can be both relatively large, you may not want to store these
+on the stack, unless you have stack space to spare.  Of course, you
+will want to check if they return NULL.  If you are also reading,
+you won't want to name your read structure and your write structure
+both "png_ptr"; you can call them anything you like, such as
+"read_ptr" and "write_ptr".  Look at pngtest.c, for example.
+
+    png_structp png_ptr = png_create_write_struct
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+        user_error_fn, user_warning_fn);
+    if (!png_ptr)
+       return (ERROR);
+
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr)
+    {
+       png_destroy_write_struct(&png_ptr,
+         (png_infopp)NULL);
+       return (ERROR);
+    }
+
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_write_struct_2() instead of png_create_write_struct():
+
+    png_structp png_ptr = png_create_write_struct_2
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+        user_error_fn, user_warning_fn, (png_voidp)
+        user_mem_ptr, user_malloc_fn, user_free_fn);
+
+After you have these structures, you will need to set up the
+error handling.  When libpng encounters an error, it expects to
+longjmp() back to your routine.  Therefore, you will need to call
+setjmp() and pass the png_jmpbuf(png_ptr).  If you
+write the file from different routines, you will need to update
+the png_jmpbuf(png_ptr) every time you enter a new routine that will
+call a png_*() function.  See your documentation of setjmp/longjmp
+for your compiler for more information on setjmp/longjmp.  See
+the discussion on libpng error handling in the Customizing Libpng
+section below for more information on the libpng error handling.
+
+    if (setjmp(png_jmpbuf(png_ptr)))
+    {
+       png_destroy_write_struct(&png_ptr, &info_ptr);
+       fclose(fp);
+       return (ERROR);
+    }
+    ...
+    return;
+
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
+Now you need to set up the output code.  The default for libpng is to
+use the C function fwrite().  If you use this, you will need to pass a
+valid FILE * in the function png_init_io().  Be sure that the file is
+opened in binary mode.  Again, if you wish to handle writing data in
+another way, see the discussion on libpng I/O handling in the Customizing
+Libpng section below.
+
+    png_init_io(png_ptr, fp);
+
+.SS Write callbacks
+
+At this point, you can set up a callback function that will be
+called after each row has been written, which you can use to control
+a progress meter or the like.  It's demonstrated in pngtest.c.
+You must supply a function
+
+    void write_row_callback(png_ptr, png_uint_32 row,
+       int pass);
+    {
+      /* put your code here */
+    }
+
+(You can give it another name that you like instead of "write_row_callback")
+
+To inform libpng about your function, use
+
+    png_set_write_status_fn(png_ptr, write_row_callback);
+
+You now have the option of modifying how the compression library will
+run.  The following functions are mainly for testing, but may be useful
+in some cases, like if you need to write PNG files extremely fast and
+are willing to give up some compression, or if you want to get the
+maximum possible compression at the expense of slower writing.  If you
+have no special needs in this area, let the library do what it wants by
+not calling this function at all, as it has been tuned to deliver a good
+speed/compression ratio. The second parameter to png_set_filter() is
+the filter method, for which the only valid values are 0 (as of the
+July 1999 PNG specification, version 1.2) or 64 (if you are writing
+a PNG datastream that is to be embedded in a MNG datastream).  The third
+parameter is a flag that indicates which filter type(s) are to be tested
+for each scanline.  See the PNG specification for details on the specific filter
+types.
+
+
+    /* turn on or off filtering, and/or choose
+       specific filters.  You can use either a single
+       PNG_FILTER_VALUE_NAME or the logical OR of one
+       or more PNG_FILTER_NAME masks. */
+    png_set_filter(png_ptr, 0,
+       PNG_FILTER_NONE  | PNG_FILTER_VALUE_NONE |
+       PNG_FILTER_SUB   | PNG_FILTER_VALUE_SUB  |
+       PNG_FILTER_UP    | PNG_FILTER_VALUE_UP   |
+       PNG_FILTER_AVE   | PNG_FILTER_VALUE_AVE  |
+       PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
+       PNG_ALL_FILTERS);
+
+If an application
+wants to start and stop using particular filters during compression,
+it should start out with all of the filters (to ensure that the previous
+row of pixels will be stored in case it's needed later), and then add
+and remove them after the start of compression.
+
+If you are writing a PNG datastream that is to be embedded in a MNG
+datastream, the second parameter can be either 0 or 64.
+
+The png_set_compression_*() functions interface to the zlib compression
+library, and should mostly be ignored unless you really know what you are
+doing.  The only generally useful call is png_set_compression_level()
+which changes how much time zlib spends on trying to compress the image
+data.  See the Compression Library (zlib.h and algorithm.txt, distributed
+with zlib) for details on the compression levels.
+
+    /* set the zlib compression level */
+    png_set_compression_level(png_ptr,
+        Z_BEST_COMPRESSION);
+
+    /* set other zlib parameters */
+    png_set_compression_mem_level(png_ptr, 8);
+    png_set_compression_strategy(png_ptr,
+        Z_DEFAULT_STRATEGY);
+    png_set_compression_window_bits(png_ptr, 15);
+    png_set_compression_method(png_ptr, 8);
+    png_set_compression_buffer_size(png_ptr, 8192)
+
+extern PNG_EXPORT(void,png_set_zbuf_size)
+
+.SS Setting the contents of info for output
+
+You now need to fill in the png_info structure with all the data you
+wish to write before the actual image.  Note that the only thing you
+are allowed to write after the image is the text chunks and the time
+chunk (as of PNG Specification 1.2, anyway).  See png_write_end() and
+the latest PNG specification for more information on that.  If you
+wish to write them before the image, fill them in now, and flag that
+data as being valid.  If you want to wait until after the data, don't
+fill them until png_write_end().  For all the fields in png_info and
+their data types, see png.h.  For explanations of what the fields
+contain, see the PNG specification.
+
+Some of the more important parts of the png_info are:
+
+    png_set_IHDR(png_ptr, info_ptr, width, height,
+       bit_depth, color_type, interlace_type,
+       compression_type, filter_method)
+    width          - holds the width of the image
+                     in pixels (up to 2^31).
+    height         - holds the height of the image
+                     in pixels (up to 2^31).
+    bit_depth      - holds the bit depth of one of the
+                     image channels.
+                     (valid values are 1, 2, 4, 8, 16
+                     and depend also on the
+                     color_type.  See also significant
+                     bits (sBIT) below).
+    color_type     - describes which color/alpha
+                     channels are present.
+                     PNG_COLOR_TYPE_GRAY
+                        (bit depths 1, 2, 4, 8, 16)
+                     PNG_COLOR_TYPE_GRAY_ALPHA
+                        (bit depths 8, 16)
+                     PNG_COLOR_TYPE_PALETTE
+                        (bit depths 1, 2, 4, 8)
+                     PNG_COLOR_TYPE_RGB
+                        (bit_depths 8, 16)
+                     PNG_COLOR_TYPE_RGB_ALPHA
+                        (bit_depths 8, 16)
+
+                     PNG_COLOR_MASK_PALETTE
+                     PNG_COLOR_MASK_COLOR
+                     PNG_COLOR_MASK_ALPHA
+
+    interlace_type - PNG_INTERLACE_NONE or
+                     PNG_INTERLACE_ADAM7
+    compression_type - (must be
+                     PNG_COMPRESSION_TYPE_DEFAULT)
+    filter_method  - (must be PNG_FILTER_TYPE_DEFAULT
+                     or, if you are writing a PNG to
+                     be embedded in a MNG datastream,
+                     can also be
+                     PNG_INTRAPIXEL_DIFFERENCING)
+
+    png_set_PLTE(png_ptr, info_ptr, palette,
+       num_palette);
+    palette        - the palette for the file
+                     (array of png_color)
+    num_palette    - number of entries in the palette
+
+    png_set_gAMA(png_ptr, info_ptr, gamma);
+    gamma          - the gamma the image was created
+                     at (PNG_INFO_gAMA)
+
+    png_set_sRGB(png_ptr, info_ptr, srgb_intent);
+    srgb_intent    - the rendering intent
+                     (PNG_INFO_sRGB) The presence of
+                     the sRGB chunk means that the pixel
+                     data is in the sRGB color space.
+                     This chunk also implies specific
+                     values of gAMA and cHRM.  Rendering
+                     intent is the CSS-1 property that
+                     has been defined by the International
+                     Color Consortium
+                     (http://www.color.org).
+                     It can be one of
+                     PNG_sRGB_INTENT_SATURATION,
+                     PNG_sRGB_INTENT_PERCEPTUAL,
+                     PNG_sRGB_INTENT_ABSOLUTE, or
+                     PNG_sRGB_INTENT_RELATIVE.
+
+
+    png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr,
+       srgb_intent);
+    srgb_intent    - the rendering intent
+                     (PNG_INFO_sRGB) The presence of the
+                     sRGB chunk means that the pixel
+                     data is in the sRGB color space.
+                     This function also causes gAMA and
+                     cHRM chunks with the specific values
+                     that are consistent with sRGB to be
+                     written.
+
+    png_set_iCCP(png_ptr, info_ptr, name, compression_type,
+                      profile, proflen);
+    name            - The profile name.
+    compression     - The compression type; always
+                      PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
+                      You may give NULL to this argument to
+                      ignore it.
+    profile         - International Color Consortium color
+                      profile data. May contain NULs.
+    proflen         - length of profile data in bytes.
+
+    png_set_sBIT(png_ptr, info_ptr, sig_bit);
+    sig_bit        - the number of significant bits for
+                     (PNG_INFO_sBIT) each of the gray, red,
+                     green, and blue channels, whichever are
+                     appropriate for the given color type
+                     (png_color_16)
+
+    png_set_tRNS(png_ptr, info_ptr, trans, num_trans,
+       trans_values);
+    trans          - array of transparent entries for
+                     palette (PNG_INFO_tRNS)
+    trans_values   - graylevel or color sample values of
+                     the single transparent color for
+                     non-paletted images (PNG_INFO_tRNS)
+    num_trans      - number of transparent entries
+                     (PNG_INFO_tRNS)
+
+    png_set_hIST(png_ptr, info_ptr, hist);
+                    (PNG_INFO_hIST)
+    hist           - histogram of palette (array of
+                     png_uint_16)
+
+    png_set_tIME(png_ptr, info_ptr, mod_time);
+    mod_time       - time image was last modified
+                     (PNG_VALID_tIME)
+
+    png_set_bKGD(png_ptr, info_ptr, background);
+    background     - background color (PNG_VALID_bKGD)
+
+    png_set_text(png_ptr, info_ptr, text_ptr, num_text);
+    text_ptr       - array of png_text holding image
+                     comments
+    text_ptr[i].compression - type of compression used
+                 on "text" PNG_TEXT_COMPRESSION_NONE
+                           PNG_TEXT_COMPRESSION_zTXt
+                           PNG_ITXT_COMPRESSION_NONE
+                           PNG_ITXT_COMPRESSION_zTXt
+    text_ptr[i].key   - keyword for comment.  Must contain
+                 1-79 characters.
+    text_ptr[i].text  - text comments for current
+                         keyword.  Can be NULL or empty.
+    text_ptr[i].text_length - length of text string,
+                 after decompression, 0 for iTXt
+    text_ptr[i].itxt_length - length of itxt string,
+                 after decompression, 0 for tEXt/zTXt
+    text_ptr[i].lang  - language of comment (NULL or
+                         empty for unknown).
+    text_ptr[i].translated_keyword  - keyword in UTF-8 (NULL
+                         or empty for unknown).
+    num_text       - number of comments
+
+    png_set_sPLT(png_ptr, info_ptr, &palette_ptr,
+       num_spalettes);
+    palette_ptr    - array of png_sPLT_struct structures
+                     to be added to the list of palettes
+                     in the info structure.
+    num_spalettes  - number of palette structures to be
+                     added.
+
+    png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y,
+        unit_type);
+    offset_x  - positive offset from the left
+                     edge of the screen
+    offset_y  - positive offset from the top
+                     edge of the screen
+    unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
+
+    png_set_pHYs(png_ptr, info_ptr, res_x, res_y,
+        unit_type);
+    res_x       - pixels/unit physical resolution
+                  in x direction
+    res_y       - pixels/unit physical resolution
+                  in y direction
+    unit_type   - PNG_RESOLUTION_UNKNOWN,
+                  PNG_RESOLUTION_METER
+
+    png_set_sCAL(png_ptr, info_ptr, unit, width, height)
+    unit        - physical scale units (an integer)
+    width       - width of a pixel in physical scale units
+    height      - height of a pixel in physical scale units
+                  (width and height are doubles)
+
+    png_set_sCAL_s(png_ptr, info_ptr, unit, width, height)
+    unit        - physical scale units (an integer)
+    width       - width of a pixel in physical scale units
+    height      - height of a pixel in physical scale units
+                 (width and height are strings like "2.54")
+
+    png_set_unknown_chunks(png_ptr, info_ptr, &unknowns,
+       num_unknowns)
+    unknowns          - array of png_unknown_chunk
+                        structures holding unknown chunks
+    unknowns[i].name  - name of unknown chunk
+    unknowns[i].data  - data of unknown chunk
+    unknowns[i].size  - size of unknown chunk's data
+    unknowns[i].location - position to write chunk in file
+                           0: do not write chunk
+                           PNG_HAVE_IHDR: before PLTE
+                           PNG_HAVE_PLTE: before IDAT
+                           PNG_AFTER_IDAT: after IDAT
+
+The "location" member is set automatically according to
+what part of the output file has already been written.
+You can change its value after calling png_set_unknown_chunks()
+as demonstrated in pngtest.c.  Within each of the "locations",
+the chunks are sequenced according to their position in the
+structure (that is, the value of "i", which is the order in which
+the chunk was either read from the input file or defined with
+png_set_unknown_chunks).
+
+A quick word about text and num_text.  text is an array of png_text
+structures.  num_text is the number of valid structures in the array.
+Each png_text structure holds a language code, a keyword, a text value,
+and a compression type.
+
+The compression types have the same valid numbers as the compression
+types of the image data.  Currently, the only valid number is zero.
+However, you can store text either compressed or uncompressed, unlike
+images, which always have to be compressed.  So if you don't want the
+text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE.
+Because tEXt and zTXt chunks don't have a language field, if you
+specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt
+any language code or translated keyword will not be written out.
+
+Until text gets around 1000 bytes, it is not worth compressing it.
+After the text has been written out to the file, the compression type
+is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR,
+so that it isn't written out again at the end (in case you are calling
+png_write_end() with the same struct.
+
+The keywords that are given in the PNG Specification are:
+
+    Title            Short (one line) title or
+                     caption for image
+    Author           Name of image's creator
+    Description      Description of image (possibly long)
+    Copyright        Copyright notice
+    Creation Time    Time of original image creation
+                     (usually RFC 1123 format, see below)
+    Software         Software used to create the image
+    Disclaimer       Legal disclaimer
+    Warning          Warning of nature of content
+    Source           Device used to create the image
+    Comment          Miscellaneous comment; conversion
+                     from other image format
+
+The keyword-text pairs work like this.  Keywords should be short
+simple descriptions of what the comment is about.  Some typical
+keywords are found in the PNG specification, as is some recommendations
+on keywords.  You can repeat keywords in a file.  You can even write
+some text before the image and some after.  For example, you may want
+to put a description of the image before the image, but leave the
+disclaimer until after, so viewers working over modem connections
+don't have to wait for the disclaimer to go over the modem before
+they start seeing the image.  Finally, keywords should be full
+words, not abbreviations.  Keywords and text are in the ISO 8859-1
+(Latin-1) character set (a superset of regular ASCII) and can not
+contain NUL characters, and should not contain control or other
+unprintable characters.  To make the comments widely readable, stick
+with basic ASCII, and avoid machine specific character set extensions
+like the IBM-PC character set.  The keyword must be present, but
+you can leave off the text string on non-compressed pairs.
+Compressed pairs must have a text string, as only the text string
+is compressed anyway, so the compression would be meaningless.
+
+PNG supports modification time via the png_time structure.  Two
+conversion routines are provided, png_convert_from_time_t() for
+time_t and png_convert_from_struct_tm() for struct tm.  The
+time_t routine uses gmtime().  You don't have to use either of
+these, but if you wish to fill in the png_time structure directly,
+you should provide the time in universal time (GMT) if possible
+instead of your local time.  Note that the year number is the full
+year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and
+that months start with 1.
+
+If you want to store the time of the original image creation, you should
+use a plain tEXt chunk with the "Creation Time" keyword.  This is
+necessary because the "creation time" of a PNG image is somewhat vague,
+depending on whether you mean the PNG file, the time the image was
+created in a non-PNG format, a still photo from which the image was
+scanned, or possibly the subject matter itself.  In order to facilitate
+machine-readable dates, it is recommended that the "Creation Time"
+tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"),
+although this isn't a requirement.  Unlike the tIME chunk, the
+"Creation Time" tEXt chunk is not expected to be automatically changed
+by the software.  To facilitate the use of RFC 1123 dates, a function
+png_convert_to_rfc1123(png_timep) is provided to convert from PNG
+time to an RFC 1123 format string.
+
+.SS Writing unknown chunks
+
+You can use the png_set_unknown_chunks function to queue up chunks
+for writing.  You give it a chunk name, raw data, and a size; that's
+all there is to it.  The chunks will be written by the next following
+png_write_info_before_PLTE, png_write_info, or png_write_end function.
+Any chunks previously read into the info structure's unknown-chunk
+list will also be written out in a sequence that satisfies the PNG
+specification's ordering rules.
+
+.SS The high-level write interface
+
+At this point there are two ways to proceed; through the high-level
+write interface, or through a sequence of low-level write operations.
+You can use the high-level interface if your image data is present
+in the info structure.  All defined output
+transformations are permitted, enabled by the following masks.
+
+    PNG_TRANSFORM_IDENTITY      No transformation
+    PNG_TRANSFORM_PACKING       Pack 1, 2 and 4-bit samples
+    PNG_TRANSFORM_PACKSWAP      Change order of packed
+                                pixels to LSB first
+    PNG_TRANSFORM_INVERT_MONO   Invert monochrome images
+    PNG_TRANSFORM_SHIFT         Normalize pixels to the
+                                sBIT depth
+    PNG_TRANSFORM_BGR           Flip RGB to BGR, RGBA
+                                to BGRA
+    PNG_TRANSFORM_SWAP_ALPHA    Flip RGBA to ARGB or GA
+                                to AG
+    PNG_TRANSFORM_INVERT_ALPHA  Change alpha from opacity
+                                to transparency
+    PNG_TRANSFORM_SWAP_ENDIAN   Byte-swap 16-bit samples
+    PNG_TRANSFORM_STRIP_FILLER  Strip out filler bytes.
+
+If you have valid image data in the info structure (you can use
+png_set_rows() to put image data in the info structure), simply do this:
+
+    png_write_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the logical OR of some set of
+transformation flags.  This call is equivalent to png_write_info(),
+followed the set of transformations indicated by the transform mask,
+then png_write_image(), and finally png_write_end().
+
+(The final parameter of this call is not yet used.  Someday it might point
+to transformation parameters required by some future output transform.)
+
+.SS The low-level write interface
+
+If you are going the low-level route instead, you are now ready to
+write all the file information up to the actual image data.  You do
+this with a call to png_write_info().
+
+    png_write_info(png_ptr, info_ptr);
+
+Note that there is one transformation you may need to do before
+png_write_info().  In PNG files, the alpha channel in an image is the
+level of opacity.  If your data is supplied as a level of
+transparency, you can invert the alpha channel before you write it, so
+that 0 is fully transparent and 255 (in 8-bit or paletted images) or
+65535 (in 16-bit images) is fully opaque, with
+
+    png_set_invert_alpha(png_ptr);
+
+This must appear before png_write_info() instead of later with the
+other transformations because in the case of paletted images the tRNS
+chunk data has to be inverted before the tRNS chunk is written.  If
+your image is not a paletted image, the tRNS data (which in such cases
+represents a single color to be rendered as transparent) won't need to
+be changed, and you can safely do this transformation after your
+png_write_info() call.
+
+If you need to write a private chunk that you want to appear before
+the PLTE chunk when PLTE is present, you can write the PNG info in
+two steps, and insert code to write your own chunk between them:
+
+    png_write_info_before_PLTE(png_ptr, info_ptr);
+    png_set_unknown_chunks(png_ptr, info_ptr, ...);
+    png_write_info(png_ptr, info_ptr);
+
+After you've written the file information, you can set up the library
+to handle any special transformations of the image data.  The various
+ways to transform the data will be described in the order that they
+should occur.  This is important, as some of these change the color
+type and/or bit depth of the data, and some others only work on
+certain color types and bit depths.  Even though each transformation
+checks to see if it has data that it can do something with, you should
+make sure to only enable a transformation if it will be valid for the
+data.  For example, don't swap red and blue on grayscale data.
+
+PNG files store RGB pixels packed into 3 or 6 bytes.  This code tells
+the library to strip input data that has 4 or 8 bytes per pixel down
+to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2
+bytes per pixel).
+
+    png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+
+where the 0 is unused, and the location is either PNG_FILLER_BEFORE or
+PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel
+is stored XRGB or RGBX.
+
+PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
+they can, resulting in, for example, 8 pixels per byte for 1 bit files.
+If the data is supplied at 1 pixel per byte, use this code, which will
+correctly pack the pixels into a single byte:
+
+    png_set_packing(png_ptr);
+
+PNG files reduce possible bit depths to 1, 2, 4, 8, and 16.  If your
+data is of another bit depth, you can write an sBIT chunk into the
+file so that decoders can recover the original data if desired.
+
+    /* Set the true bit depth of the image data */
+    if (color_type & PNG_COLOR_MASK_COLOR)
+    {
+        sig_bit.red = true_bit_depth;
+        sig_bit.green = true_bit_depth;
+        sig_bit.blue = true_bit_depth;
+    }
+    else
+    {
+        sig_bit.gray = true_bit_depth;
+    }
+    if (color_type & PNG_COLOR_MASK_ALPHA)
+    {
+        sig_bit.alpha = true_bit_depth;
+    }
+
+    png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+If the data is stored in the row buffer in a bit depth other than
+one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG),
+this will scale the values to appear to be the correct bit depth as
+is required by PNG.
+
+    png_set_shift(png_ptr, &sig_bit);
+
+PNG files store 16 bit pixels in network byte order (big-endian,
+ie. most significant bits first).  This code would be used if they are
+supplied the other way (little-endian, i.e. least significant bits
+first, the way PCs store them):
+
+    if (bit_depth > 8)
+       png_set_swap(png_ptr);
+
+If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
+need to change the order the pixels are packed into bytes, you can use:
+
+    if (bit_depth < 8)
+       png_set_packswap(png_ptr);
+
+PNG files store 3 color pixels in red, green, blue order.  This code
+would be used if they are supplied as blue, green, red:
+
+    png_set_bgr(png_ptr);
+
+PNG files describe monochrome as black being zero and white being
+one. This code would be used if the pixels are supplied with this reversed
+(black being one and white being zero):
+
+    png_set_invert_mono(png_ptr);
+
+Finally, you can write your own transformation function if none of
+the existing ones meets your needs.  This is done by setting a callback
+with
+
+    png_set_write_user_transform_fn(png_ptr,
+       write_transform_fn);
+
+You must supply the function
+
+    void write_transform_fn(png_ptr ptr, row_info_ptr
+       row_info, png_bytep data)
+
+See pngtest.c for a working example.  Your function will be called
+before any of the other transformations are processed.
+
+You can also set up a pointer to a user structure for use by your
+callback function.
+
+    png_set_user_transform_info(png_ptr, user_ptr, 0, 0);
+
+The user_channels and user_depth parameters of this function are ignored
+when writing; you can set them to zero as shown.
+
+You can retrieve the pointer via the function png_get_user_transform_ptr().
+For example:
+
+    voidp write_user_transform_ptr =
+       png_get_user_transform_ptr(png_ptr);
+
+It is possible to have libpng flush any pending output, either manually,
+or automatically after a certain number of lines have been written.  To
+flush the output stream a single time call:
+
+    png_write_flush(png_ptr);
+
+and to have libpng flush the output stream periodically after a certain
+number of scanlines have been written, call:
+
+    png_set_flush(png_ptr, nrows);
+
+Note that the distance between rows is from the last time png_write_flush()
+was called, or the first row of the image if it has never been called.
+So if you write 50 lines, and then png_set_flush 25, it will flush the
+output on the next scanline, and every 25 lines thereafter, unless
+png_write_flush() is called before 25 more lines have been written.
+If nrows is too small (less than about 10 lines for a 640 pixel wide
+RGB image) the image compression may decrease noticeably (although this
+may be acceptable for real-time applications).  Infrequent flushing will
+only degrade the compression performance by a few percent over images
+that do not use flushing.
+
+.SS Writing the image data
+
+That's it for the transformations.  Now you can write the image data.
+The simplest way to do this is in one function call.  If you have the
+whole image in memory, you can just call png_write_image() and libpng
+will write the image.  You will need to pass in an array of pointers to
+each row.  This function automatically handles interlacing, so you don't
+need to call png_set_interlace_handling() or call this function multiple
+times, or any of that other stuff necessary with png_write_rows().
+
+    png_write_image(png_ptr, row_pointers);
+
+where row_pointers is:
+
+    png_byte *row_pointers[height];
+
+You can point to void or char or whatever you use for pixels.
+
+If you don't want to write the whole image at once, you can
+use png_write_rows() instead.  If the file is not interlaced,
+this is simple:
+
+    png_write_rows(png_ptr, row_pointers,
+       number_of_rows);
+
+row_pointers is the same as in the png_write_image() call.
+
+If you are just writing one row at a time, you can do this with
+a single row_pointer instead of an array of row_pointers:
+
+    png_bytep row_pointer = row;
+
+    png_write_row(png_ptr, row_pointer);
+
+When the file is interlaced, things can get a good deal more
+complicated.  The only currently (as of the PNG Specification
+version 1.2, dated July 1999) defined interlacing scheme for PNG files
+is the "Adam7" interlace scheme, that breaks down an
+image into seven smaller images of varying size.  libpng will build
+these images for you, or you can do them yourself.  If you want to
+build them yourself, see the PNG specification for details of which
+pixels to write when.
+
+If you don't want libpng to handle the interlacing details, just
+use png_set_interlace_handling() and call png_write_rows() the
+correct number of times to write all seven sub-images.
+
+If you want libpng to build the sub-images, call this before you start
+writing any rows:
+
+    number_of_passes =
+       png_set_interlace_handling(png_ptr);
+
+This will return the number of passes needed.  Currently, this
+is seven, but may change if another interlace type is added.
+
+Then write the complete image number_of_passes times.
+
+    png_write_rows(png_ptr, row_pointers,
+       number_of_rows);
+
+As some of these rows are not used, and thus return immediately,
+you may want to read about interlacing in the PNG specification,
+and only update the rows that are actually used.
+
+.SS Finishing a sequential write
+
+After you are finished writing the image, you should finish writing
+the file.  If you are interested in writing comments or time, you should
+pass an appropriately filled png_info pointer.  If you are not interested,
+you can pass NULL.
+
+    png_write_end(png_ptr, info_ptr);
+
+When you are done, you can free all memory used by libpng like this:
+
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+
+It is also possible to individually free the info_ptr members that
+point to libpng-allocated storage with the following function:
+
+    png_free_data(png_ptr, info_ptr, mask, seq)
+    mask  - identifies data to be freed, a mask
+            containing the logical OR of one or
+            more of
+              PNG_FREE_PLTE, PNG_FREE_TRNS,
+              PNG_FREE_HIST, PNG_FREE_ICCP,
+              PNG_FREE_PCAL, PNG_FREE_ROWS,
+              PNG_FREE_SCAL, PNG_FREE_SPLT,
+              PNG_FREE_TEXT, PNG_FREE_UNKN,
+            or simply PNG_FREE_ALL
+    seq   - sequence number of item to be freed
+            (-1 for all items)
+
+This function may be safely called when the relevant storage has
+already been freed, or has not yet been allocated, or was allocated
+by the user  and not by libpng,  and will in those
+cases do nothing.  The "seq" parameter is ignored if only one item
+of the selected data type, such as PLTE, is allowed.  If "seq" is not
+-1, and multiple items are allowed for the data type identified in
+the mask, such as text or sPLT, only the n'th item in the structure
+is freed, where n is "seq".
+
+If you allocated data such as a palette that you passed
+in to libpng with png_set_*, you must not free it until just before the call to
+png_destroy_write_struct().
+
+The default behavior is only to free data that was allocated internally
+by libpng.  This can be changed, so that libpng will not free the data,
+or so that it will free data that was allocated by the user with png_malloc()
+or png_zalloc() and passed in via a png_set_*() function, with
+
+    png_data_freer(png_ptr, info_ptr, freer, mask)
+    mask   - which data elements are affected
+             same choices as in png_free_data()
+    freer  - one of
+               PNG_DESTROY_WILL_FREE_DATA
+               PNG_SET_WILL_FREE_DATA
+               PNG_USER_WILL_FREE_DATA
+
+For example, to transfer responsibility for some data from a read structure
+to a write structure, you could use
+
+    png_data_freer(read_ptr, read_info_ptr,
+       PNG_USER_WILL_FREE_DATA,
+       PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST)
+    png_data_freer(write_ptr, write_info_ptr,
+       PNG_DESTROY_WILL_FREE_DATA,
+       PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST)
+
+thereby briefly reassigning responsibility for freeing to the user but
+immediately afterwards reassigning it once more to the write_destroy
+function.  Having done this, it would then be safe to destroy the read
+structure and continue to use the PLTE, tRNS, and hIST data in the write
+structure.
+
+This function only affects data that has already been allocated.
+You can call this function before calling after the png_set_*() functions
+to control whether the user or png_destroy_*() is supposed to free the data.
+When the user assumes responsibility for libpng-allocated data, the
+application must use
+png_free() to free it, and when the user transfers responsibility to libpng
+for data that the user has allocated, the user must have used png_malloc()
+or png_zalloc() to allocate it.
+
+If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
+separately, do not transfer responsibility for freeing text_ptr to libpng,
+because when libpng fills a png_text structure it combines these members with
+the key member, and png_free_data() will free only text_ptr.key.  Similarly,
+if you transfer responsibility for free'ing text_ptr from libpng to your
+application, your application must not separately free those members.
+For a more compact example of writing a PNG image, see the file example.c.
+
+.SH V. Modifying/Customizing libpng:
+
+There are three issues here.  The first is changing how libpng does
+standard things like memory allocation, input/output, and error handling.
+The second deals with more complicated things like adding new chunks,
+adding new transformations, and generally changing how libpng works.
+Both of those are compile-time issues; that is, they are generally
+determined at the time the code is written, and there is rarely a need
+to provide the user with a means of changing them.  The third is a
+run-time issue:  choosing between and/or tuning one or more alternate
+versions of computationally intensive routines; specifically, optimized
+assembly-language (and therefore compiler- and platform-dependent)
+versions.
+
+Memory allocation, input/output, and error handling
+
+All of the memory allocation, input/output, and error handling in libpng
+goes through callbacks that are user-settable.  The default routines are
+in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively.  To change
+these functions, call the appropriate png_set_*_fn() function.
+
+Memory allocation is done through the functions png_malloc(), png_zalloc(),
+and png_free().  These currently just call the standard C functions.  If
+your pointers can't access more then 64K at a time, you will want to set
+MAXSEG_64K in zlib.h.  Since it is unlikely that the method of handling
+memory allocation on a platform will change between applications, these
+functions must be modified in the library at compile time.  If you prefer
+to use a different method of allocating and freeing data, you can use
+
+    png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr,
+       png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+
+This function also provides a void pointer that can be retrieved via
+
+    mem_ptr=png_get_mem_ptr(png_ptr);
+
+Your replacement memory functions must have prototypes as follows:
+
+    png_voidp malloc_fn(png_structp png_ptr,
+       png_uint_32 size);
+    void free_fn(png_structp png_ptr, png_voidp ptr);
+
+Your malloc_fn() can return NULL in case of failure.  The png_malloc()
+function will call png_error() if it receives a NULL from the system
+memory allocator or from your replacement malloc_fn().
+
+Input/Output in libpng is done through png_read() and png_write(),
+which currently just call fread() and fwrite().  The FILE * is stored in
+png_struct and is initialized via png_init_io().  If you wish to change
+the method of I/O, the library supplies callbacks that you can set
+through the function png_set_read_fn() and png_set_write_fn() at run
+time, instead of calling the png_init_io() function.  These functions
+also provide a void pointer that can be retrieved via the function
+png_get_io_ptr().  For example:
+
+    png_set_read_fn(png_structp read_ptr,
+        voidp read_io_ptr, png_rw_ptr read_data_fn)
+
+    png_set_write_fn(png_structp write_ptr,
+        voidp write_io_ptr, png_rw_ptr write_data_fn,
+        png_flush_ptr output_flush_fn);
+
+    voidp read_io_ptr = png_get_io_ptr(read_ptr);
+    voidp write_io_ptr = png_get_io_ptr(write_ptr);
+
+The replacement I/O functions must have prototypes as follows:
+
+    void user_read_data(png_structp png_ptr,
+        png_bytep data, png_uint_32 length);
+    void user_write_data(png_structp png_ptr,
+        png_bytep data, png_uint_32 length);
+    void user_flush_data(png_structp png_ptr);
+
+Supplying NULL for the read, write, or flush functions sets them back
+to using the default C stream functions.  It is an error to read from
+a write stream, and vice versa.
+
+Error handling in libpng is done through png_error() and png_warning().
+Errors handled through png_error() are fatal, meaning that png_error()
+should never return to its caller.  Currently, this is handled via
+setjmp() and longjmp() (unless you have compiled libpng with
+PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()),
+but you could change this to do things like exit() if you should wish.
+
+On non-fatal errors, png_warning() is called
+to print a warning message, and then control returns to the calling code.
+By default png_error() and png_warning() print a message on stderr via
+fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined
+(because you don't want the messages) or PNG_NO_STDIO defined (because
+fprintf() isn't available).  If you wish to change the behavior of the error
+functions, you will need to set up your own message callbacks.  These
+functions are normally supplied at the time that the png_struct is created.
+It is also possible to redirect errors and warnings to your own replacement
+functions after png_create_*_struct() has been called by calling:
+
+    png_set_error_fn(png_structp png_ptr,
+        png_voidp error_ptr, png_error_ptr error_fn,
+        png_error_ptr warning_fn);
+
+    png_voidp error_ptr = png_get_error_ptr(png_ptr);
+
+If NULL is supplied for either error_fn or warning_fn, then the libpng
+default function will be used, calling fprintf() and/or longjmp() if a
+problem is encountered.  The replacement error functions should have
+parameters as follows:
+
+    void user_error_fn(png_structp png_ptr,
+        png_const_charp error_msg);
+    void user_warning_fn(png_structp png_ptr,
+        png_const_charp warning_msg);
+
+The motivation behind using setjmp() and longjmp() is the C++ throw and
+catch exception handling methods.  This makes the code much easier to write,
+as there is no need to check every return code of every function call.
+However, there are some uncertainties about the status of local variables
+after a longjmp, so the user may want to be careful about doing anything after
+setjmp returns non-zero besides returning itself.  Consult your compiler
+documentation for more details.  For an alternative approach, you may wish
+to use the "cexcept" facility (see http://cexcept.sourceforge.net).
+
+.SS Custom chunks
+
+If you need to read or write custom chunks, you may need to get deeper
+into the libpng code.  The library now has mechanisms for storing
+and writing chunks of unknown type; you can even declare callbacks
+for custom chunks.  Hoewver, this may not be good enough if the
+library code itself needs to know about interactions between your
+chunk and existing `intrinsic' chunks.
+
+If you need to write a new intrinsic chunk, first read the PNG
+specification. Acquire a first level of
+understanding of how it works.  Pay particular attention to the
+sections that describe chunk names, and look at how other chunks were
+designed, so you can do things similarly.  Second, check out the
+sections of libpng that read and write chunks.  Try to find a chunk
+that is similar to yours and use it as a template.  More details can
+be found in the comments inside the code.  It is best to handle unknown
+chunks in a generic method, via callback functions, instead of by
+modifying libpng functions.
+
+If you wish to write your own transformation for the data, look through
+the part of the code that does the transformations, and check out some of
+the simpler ones to get an idea of how they work.  Try to find a similar
+transformation to the one you want to add and copy off of it.  More details
+can be found in the comments inside the code itself.
+
+.SS Configuring for 16 bit platforms
+
+You will want to look into zconf.h to tell zlib (and thus libpng) that
+it cannot allocate more then 64K at a time.  Even if you can, the memory
+won't be accessible.  So limit zlib and libpng to 64K by defining MAXSEG_64K.
+
+.SS Configuring for DOS
+
+For DOS users who only have access to the lower 640K, you will
+have to limit zlib's memory usage via a png_set_compression_mem_level()
+call.  See zlib.h or zconf.h in the zlib library for more information.
+
+.SS Configuring for Medium Model
+
+Libpng's support for medium model has been tested on most of the popular
+compilers.  Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
+defined, and FAR gets defined to far in pngconf.h, and you should be
+all set.  Everything in the library (except for zlib's structure) is
+expecting far data.  You must use the typedefs with the p or pp on
+the end for pointers (or at least look at them and be careful).  Make
+note that the rows of data are defined as png_bytepp, which is an
+unsigned char far * far *.
+
+.SS Configuring for gui/windowing platforms:
+
+You will need to write new error and warning functions that use the GUI
+interface, as described previously, and set them to be the error and
+warning functions at the time that png_create_*_struct() is called,
+in order to have them available during the structure initialization.
+They can be changed later via png_set_error_fn().  On some compilers,
+you may also have to change the memory allocators (png_malloc, etc.).
+
+.SS Configuring for compiler xxx:
+
+All includes for libpng are in pngconf.h.  If you need to add/change/delete
+an include, this is the place to do it.  The includes that are not
+needed outside libpng are protected by the PNG_INTERNAL definition,
+which is only defined for those routines inside libpng itself.  The
+files in libpng proper only include png.h, which includes pngconf.h.
+
+.SS Configuring zlib:
+
+There are special functions to configure the compression.  Perhaps the
+most useful one changes the compression level, which currently uses
+input compression values in the range 0 - 9.  The library normally
+uses the default compression level (Z_DEFAULT_COMPRESSION = 6).  Tests
+have shown that for a large majority of images, compression values in
+the range 3-6 compress nearly as well as higher levels, and do so much
+faster.  For online applications it may be desirable to have maximum speed
+(Z_BEST_SPEED = 1).  With versions of zlib after v0.99, you can also
+specify no compression (Z_NO_COMPRESSION = 0), but this would create
+files larger than just storing the raw bitmap.  You can specify the
+compression level by calling:
+
+    png_set_compression_level(png_ptr, level);
+
+Another useful one is to reduce the memory level used by the library.
+The memory level defaults to 8, but it can be lowered if you are
+short on memory (running DOS, for example, where you only have 640K).
+
+    png_set_compression_mem_level(png_ptr, level);
+
+The other functions are for configuring zlib.  They are not recommended
+for normal use and may result in writing an invalid PNG file.  See
+zlib.h for more information on what these mean.
+
+    png_set_compression_strategy(png_ptr,
+        strategy);
+    png_set_compression_window_bits(png_ptr,
+        window_bits);
+    png_set_compression_method(png_ptr, method);
+    png_set_compression_buffer_size(png_ptr, size);
+
+.SS Controlling row filtering
+
+If you want to control whether libpng uses filtering or not, which
+filters are used, and how it goes about picking row filters, you
+can call one of these functions.  The selection and configuration
+of row filters can have a significant impact on the size and
+encoding speed and a somewhat lesser impact on the decoding speed
+of an image.  Filtering is enabled by default for RGB and grayscale
+images (with and without alpha), but not for paletted images nor
+for any images with bit depths less than 8 bits/pixel.
+
+The 'method' parameter sets the main filtering method, which is
+currently only '0' in the PNG 1.2 specification.  The 'filters'
+parameter sets which filter(s), if any, should be used for each
+scanline.  Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS
+to turn filtering on and off, respectively.
+
+Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB,
+PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise
+ORed together with '|' to specify one or more filters to use.
+These filters are described in more detail in the PNG specification.  If
+you intend to change the filter type during the course of writing
+the image, you should start with flags set for all of the filters
+you intend to use so that libpng can initialize its internal
+structures appropriately for all of the filter types.
+
+    filters = PNG_FILTER_NONE | PNG_FILTER_SUB
+              PNG_FILTER_UP | PNG_FILTER_AVE |
+              PNG_FILTER_PAETH | PNG_ALL_FILTERS;
+    or
+    filters = one of PNG_FILTER_VALUE_NONE,
+              PNG_FILTER_VALUE_SUB, PNG_FILTER_VALUE_UP,
+              PNG_FILTER_VALUE_AVE, PNG_FILTER_VALUE_PAETH
+
+    png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE,
+       filters);
+              The second parameter can also be
+              PNG_INTRAPIXEL_DIFFERENCING if you are
+              writing a PNG to be embedded in a MNG
+              datastream.  This parameter must be the
+              same as the value of filter_method used
+              in png_set_IHDR().
+
+It is also possible to influence how libpng chooses from among the
+available filters.  This is done in two ways - by telling it how
+important it is to keep the same filter for successive rows, and
+by telling it the relative computational costs of the filters.
+
+    double weights[3] = {1.5, 1.3, 1.1},
+       costs[PNG_FILTER_VALUE_LAST] =
+       {1.0, 1.3, 1.3, 1.5, 1.7};
+
+    png_set_filter_selection(png_ptr,
+       PNG_FILTER_SELECTION_WEIGHTED, 3,
+       weights, costs);
+
+The weights are multiplying factors that indicate to libpng that the
+row filter should be the same for successive rows unless another row filter
+is that many times better than the previous filter.  In the above example,
+if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a
+"sum of absolute differences" 1.5 x 1.3 times higher than other filters
+and still be chosen, while the NONE filter could have a sum 1.1 times
+higher than other filters and still be chosen.  Unspecified weights are
+taken to be 1.0, and the specified weights should probably be declining
+like those above in order to emphasize recent filters over older filters.
+
+The filter costs specify for each filter type a relative decoding cost
+to be considered when selecting row filters.  This means that filters
+with higher costs are less likely to be chosen over filters with lower
+costs, unless their "sum of absolute differences" is that much smaller.
+The costs do not necessarily reflect the exact computational speeds of
+the various filters, since this would unduly influence the final image
+size.
+
+Note that the numbers above were invented purely for this example and
+are given only to help explain the function usage.  Little testing has
+been done to find optimum values for either the costs or the weights.
+
+.SS Removing unwanted object code
+
+There are a bunch of #define's in pngconf.h that control what parts of
+libpng are compiled.  All the defines end in _SUPPORTED.  If you are
+never going to use a capability, you can change the #define to #undef
+before recompiling libpng and save yourself code and data space, or
+you can turn off individual capabilities with defines that begin with
+PNG_NO_.
+
+You can also turn all of the transforms and ancillary chunk capabilities
+off en masse with compiler directives that define
+PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
+or all four,
+along with directives to turn on any of the capabilities that you do
+want.  The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable
+the extra transformations but still leave the library fully capable of reading
+and writing PNG files with all known public chunks
+Use of the PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive
+produces a library that is incapable of reading or writing ancillary chunks.
+If you are not using the progressive reading capability, you can
+turn that off with PNG_NO_PROGRESSIVE_READ (don't confuse
+this with the INTERLACING capability, which you'll still have).
+
+All the reading and writing specific code are in separate files, so the
+linker should only grab the files it needs.  However, if you want to
+make sure, or if you are building a stand alone library, all the
+reading files start with pngr and all the writing files start with
+pngw.  The files that don't match either (like png.c, pngtrans.c, etc.)
+are used for both reading and writing, and always need to be included.
+The progressive reader is in pngpread.c
+
+If you are creating or distributing a dynamically linked library (a .so
+or DLL file), you should not remove or disable any parts of the library,
+as this will cause applications linked with different versions of the
+library to fail if they call functions not available in your library.
+The size of the library itself should not be an issue, because only
+those sections that are actually used will be loaded into memory.
+
+.SS Requesting debug printout
+
+The macro definition PNG_DEBUG can be used to request debugging
+printout.  Set it to an integer value in the range 0 to 3.  Higher
+numbers result in increasing amounts of debugging information.  The
+information is printed to the "stderr" file, unless another file
+name is specified in the PNG_DEBUG_FILE macro definition.
+
+When PNG_DEBUG > 0, the following functions (macros) become available:
+
+   png_debug(level, message)
+   png_debug1(level, message, p1)
+   png_debug2(level, message, p1, p2)
+
+in which "level" is compared to PNG_DEBUG to decide whether to print
+the message, "message" is the formatted string to be printed,
+and p1 and p2 are parameters that are to be embedded in the string
+according to printf-style formatting directives.  For example,
+
+   png_debug1(2, "foo=%d\n", foo);
+
+is expanded to
+
+   if(PNG_DEBUG > 2)
+     fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo);
+
+When PNG_DEBUG is defined but is zero, the macros aren't defined, but you
+can still use PNG_DEBUG to control your own debugging:
+
+   #ifdef PNG_DEBUG
+       fprintf(stderr, ...
+   #endif
+
+When PNG_DEBUG = 1, the macros are defined, but only png_debug statements
+having level = 0 will be printed.  There aren't any such statements in
+this version of libpng, but if you insert some they will be printed.
+
+.SH VI.  Runtime optimization
+
+A new feature in libpng 1.2.0 is the ability to dynamically switch between
+standard and optimized versions of some routines.  Currently these are
+limited to three computationally intensive tasks when reading PNG files:
+decoding row filters, expanding interlacing, and combining interlaced or
+transparent row data with previous row data.  Currently the optimized
+versions are available only for x86 (Intel, AMD, etc.) platforms with
+MMX support, though this may change in future versions.  (For example,
+the non-MMX assembler optimizations for zlib might become similarly
+runtime-selectable in future releases, in which case libpng could be
+extended to support them.  Alternatively, the compile-time choice of
+floating-point versus integer routines for gamma correction might become
+runtime-selectable.)
+
+Because such optimizations tend to be very platform- and compiler-dependent,
+both in how they are written and in how they perform, the new runtime code
+in libpng has been written to allow programs to query, enable, and disable
+either specific optimizations or all such optimizations.  For example, to
+enable all possible optimizations (bearing in mind that some "optimizations"
+may actually run more slowly in rare cases):
+
+    #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+       png_uint_32 mask, flags;
+
+       flags = png_get_asm_flags(png_ptr);
+       mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
+       png_set_asm_flags(png_ptr, flags | mask);
+    #endif
+
+To enable only optimizations relevant to reading PNGs, use PNG_SELECT_READ
+by itself when calling png_get_asm_flagmask(); similarly for optimizing
+only writing.  To disable all optimizations:
+
+    #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+       flags = png_get_asm_flags(png_ptr);
+       mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
+       png_set_asm_flags(png_ptr, flags & ~mask);
+    #endif
+
+To enable or disable only MMX-related features, use png_get_mmx_flagmask()
+in place of png_get_asm_flagmask().  The mmx version takes one additional
+parameter:
+
+    #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+       int selection = PNG_SELECT_READ | PNG_SELECT_WRITE;
+       int compilerID;
+
+       mask = png_get_mmx_flagmask(selection, &compilerID);
+    #endif
+
+On return, compilerID will indicate which version of the MMX assembler
+optimizations was compiled.  Currently two flavors exist:  Microsoft
+Visual C++ (compilerID == 1) and GNU C (a.k.a. gcc/gas, compilerID == 2).
+On non-x86 platforms or on systems compiled without MMX optimizations, a
+value of -1 is used.
+
+Note that both png_get_asm_flagmask() and png_get_mmx_flagmask() return
+all valid, settable optimization bits for the version of the library that's
+currently in use.  In the case of shared (dynamically linked) libraries,
+this may include optimizations that did not exist at the time the code was
+written and compiled.  It is also possible, of course, to enable only known,
+specific optimizations; for example:
+
+    #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+       flags = PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  \
+             | PNG_ASM_FLAG_MMX_READ_INTERLACE    \
+             | PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
+             | PNG_ASM_FLAG_MMX_READ_FILTER_UP    \
+             | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
+             | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ;
+       png_set_asm_flags(png_ptr, flags);
+    #endif
+
+This method would enable only the MMX read-optimizations available at the
+time of libpng 1.2.0's release, regardless of whether a later version of
+the DLL were actually being used.  (Also note that these functions did not
+exist in versions older than 1.2.0, so any attempt to run a dynamically
+linked app on such an older version would fail.)
+
+To determine whether the processor supports MMX instructions at all, use
+the png_mmx_support() function:
+
+    #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+       mmxsupport = png_mmx_support();
+    #endif
+
+It returns -1 if MMX support is not compiled into libpng, 0 if MMX code
+is compiled but MMX is not supported by the processor, or 1 if MMX support
+is fully available.  Note that png_mmx_support(), png_get_mmx_flagmask(),
+and png_get_asm_flagmask() all may be called without allocating and ini-
+tializing any PNG structures (for example, as part of a usage screen or
+"about" box).
+
+The following code can be used to prevent an application from using the
+thread_unsafe features, even if libpng was built with PNG_THREAD_UNSAFE_OK
+defined:
+
+#if defined(PNG_USE_PNGGCCRD) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) \
+  && defined(PNG_THREAD_UNSAFE_OK)
+    /* Disable thread-unsafe features of pnggccrd */
+    if (png_access_version() >= 10200)
+    {
+      png_uint_32 mmx_disable_mask = 0;
+      png_uint_32 asm_flags;
+
+      mmx_disable_mask |= ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  \
+                          | PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
+                          | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
+                          | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH );
+      asm_flags = png_get_asm_flags(png_ptr);
+      png_set_asm_flags(png_ptr, asm_flags & ~mmx_disable_mask);
+    }
+#endif
+
+For more extensive examples of runtime querying, enabling and disabling
+of optimized features, see contrib/gregbook/readpng2.c in the libpng
+source-code distribution.
+
+
+.SH VII.  MNG support
+
+The MNG specification (available at http://www.libpng.org/pub/mng) allows
+certain extensions to PNG for PNG images that are embedded in MNG datastreams.
+Libpng can support some of these extensions.  To enable them, use the
+png_permit_mng_features() function:
+
+   feature_set = png_permit_mng_features(png_ptr, mask)
+   mask is a png_uint_32 containing the logical OR of the
+        features you want to enable.  These include
+        PNG_FLAG_MNG_EMPTY_PLTE
+        PNG_FLAG_MNG_FILTER_64
+        PNG_ALL_MNG_FEATURES
+   feature_set is a png_32_uint that is the logical AND of
+      your mask with the set of MNG features that is
+      supported by the version of libpng that you are using.
+
+It is an error to use this function when reading or writing a standalone
+PNG file with the PNG 8-byte signature.  The PNG datastream must be wrapped
+in a MNG datastream.  As a minimum, it must have the MNG 8-byte signature
+and the MHDR and MEND chunks.  Libpng does not provide support for these
+or any other MNG chunks; your application must provide its own support for
+them.  You may wish to consider using libmng (available at
+http://www.libmng.com) instead.
+
+.SH VIII.  Changes to Libpng from version 0.88
+
+It should be noted that versions of libpng later than 0.96 are not
+distributed by the original libpng author, Guy Schalnat, nor by
+Andreas Dilger, who had taken over from Guy during 1996 and 1997, and
+distributed versions 0.89 through 0.96, but rather by another member
+of the original PNG Group, Glenn Randers-Pehrson.  Guy and Andreas are
+still alive and well, but they have moved on to other things.
+
+The old libpng functions png_read_init(), png_write_init(),
+png_info_init(), png_read_destroy(), and png_write_destroy() have been
+moved to PNG_INTERNAL in version 0.95 to discourage their use.  These
+functions will be removed from libpng version 2.0.0.
+
+The preferred method of creating and initializing the libpng structures is
+via the png_create_read_struct(), png_create_write_struct(), and
+png_create_info_struct() because they isolate the size of the structures
+from the application, allow version error checking, and also allow the
+use of custom error handling routines during the initialization, which
+the old functions do not.  The functions png_read_destroy() and
+png_write_destroy() do not actually free the memory that libpng
+allocated for these structs, but just reset the data structures, so they
+can be used instead of png_destroy_read_struct() and
+png_destroy_write_struct() if you feel there is too much system overhead
+allocating and freeing the png_struct for each image read.
+
+Setting the error callbacks via png_set_message_fn() before
+png_read_init() as was suggested in libpng-0.88 is no longer supported
+because this caused applications that do not use custom error functions
+to fail if the png_ptr was not initialized to zero.  It is still possible
+to set the error callbacks AFTER png_read_init(), or to change them with
+png_set_error_fn(), which is essentially the same function, but with a new
+name to force compilation errors with applications that try to use the old
+method.
+
+Starting with version 1.0.7, you can find out which version of the library
+you are using at run-time:
+
+   png_uint_32 libpng_vn = png_access_version_number();
+
+The number libpng_vn is constructed from the major version, minor
+version with leading zero, and release number with leading zero,
+(e.g., libpng_vn for version 1.0.7 is 10007).
+
+You can also check which version of png.h you used when compiling your
+application:
+
+   png_uint_32 application_vn = PNG_LIBPNG_VER;
+
+.SH IX. Y2K Compliance in libpng
+
+September 1, 2001
+
+Since the PNG Development group is an ad-hoc body, we can't make
+an official declaration.
+
+This is your unofficial assurance that libpng from version 0.71 and
+upward through 1.2.0 are Y2K compliant.  It is my belief that earlier
+versions were also Y2K compliant.
+
+Libpng only has three year fields.  One is a 2-byte unsigned integer that
+will hold years up to 65535.  The other two hold the date in text
+format, and will hold years up to 9999.
+
+The integer is
+    "png_uint_16 year" in png_time_struct.
+
+The strings are
+    "png_charp time_buffer" in png_struct and
+    "near_time_buffer", which is a local character string in png.c.
+
+There are seven time-related functions:
+
+    png_convert_to_rfc_1123() in png.c
+      (formerly png_convert_to_rfc_1152() in error)
+    png_convert_from_struct_tm() in pngwrite.c, called
+      in pngwrite.c
+    png_convert_from_time_t() in pngwrite.c
+    png_get_tIME() in pngget.c
+    png_handle_tIME() in pngrutil.c, called in pngread.c
+    png_set_tIME() in pngset.c
+    png_write_tIME() in pngwutil.c, called in pngwrite.c
+
+All appear to handle dates properly in a Y2K environment.  The
+png_convert_from_time_t() function calls gmtime() to convert from system
+clock time, which returns (year - 1900), which we properly convert to
+the full 4-digit year.  There is a possibility that applications using
+libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+function, or that they are incorrectly passing only a 2-digit year
+instead of "year - 1900" into the png_convert_from_struct_tm() function,
+but this is not under our control.  The libpng documentation has always
+stated that it works with 4-digit years, and the APIs have been
+documented as such.
+
+The tIME chunk itself is also Y2K compliant.  It uses a 2-byte unsigned
+integer to hold the year, and can hold years as large as 65535.
+
+zlib, upon which libpng depends, is also Y2K compliant.  It contains
+no date-related code.
+
+
+   Glenn Randers-Pehrson
+   libpng maintainer
+   PNG Development Group
+
+.SH NOTE
+
+Note about libpng version numbers:
+
+Due to various miscommunications, unforeseen code incompatibilities
+and occasional factors outside the authors' control, version numbering
+on the library has not always been consistent and straightforward.
+The following table summarizes matters since version 0.89c, which was
+the first widely used release:
+
+ source             png.h  png.h  shared-lib
+ version            string   int  version
+ -------            ------  ----- ----------
+ 0.89c ("beta 3")  0.89       89  1.0.89
+ 0.90  ("beta 4")  0.90       90  0.90
+ 0.95  ("beta 5")  0.95       95  0.95
+ 0.96  ("beta 6")  0.96       96  0.96
+ 0.97b ("beta 7")  1.00.97    97  1.0.1
+ 0.97c             0.97       97  2.0.97
+ 0.98              0.98       98  2.0.98
+ 0.99              0.99       98  2.0.99
+ 0.99a-m           0.99       99  2.0.99
+ 1.00              1.00      100  2.1.0
+ 1.0.0             1.0.0     100  2.1.0
+ 1.0.0   (from here on, the  100  2.1.0
+ 1.0.1    png.h string is  10001  2.1.0
+ 1.0.1a-e identical to the 10002  from here on, the
+ 1.0.2    source version)  10002  shared library is 2.V
+ 1.0.2a-b                  10003  where V is the source
+ 1.0.1                     10001  code version except as
+ 1.0.1a-e                  10002  2.1.0.1a-e   noted.
+ 1.0.2                     10002  2.1.0.2
+ 1.0.2a-b                  10003  2.1.0.2a-b
+ 1.0.3                     10003  2.1.0.3
+ 1.0.3a-d                  10004  2.1.0.3a-d
+ 1.0.4                     10004  2.1.0.4
+ 1.0.4a-f                  10005  2.1.0.4a-f
+ 1.0.5 (+ 2 patches)       10005  2.1.0.5
+ 1.0.5a-d                  10006  2.1.0.5a-d
+ 1.0.5e-r                  10100  2.1.0.5e-r
+ 1.0.5s-v                  10006  2.1.0.5s-v
+ 1.0.6 (+ 3 patches)       10006  2.1.0.6
+ 1.0.6d-g                  10007  2.1.0.6d-g
+ 1.0.6h                    10007  10.6h
+ 1.0.6i                    10007  10.6i
+ 1.0.6j                    10007  2.1.0.6j
+ 1.0.7beta11-14    DLLNUM  10007  2.1.0.7beta11-14
+ 1.0.7beta15-18       1    10007  2.1.0.7beta15-18
+ 1.0.7rc1-2           1    10007  2.1.0.7rc1-2
+ 1.0.7                1    10007  2.1.0.7
+ 1.0.8beta1-4         1    10008  2.1.0.8beta1-4
+ 1.0.8rc1             1    10008  2.1.0.8rc1
+ 1.0.8                1    10008  2.1.0.8
+ 1.0.9beta1-6         1    10009  2.1.0.9beta1-6
+ 1.0.9rc1             1    10009  2.1.0.9rc1
+ 1.0.9beta7-10        1    10009  2.1.0.9beta7-10
+ 1.0.9rc2             1    10009  2.1.0.9rc2
+ 1.0.9                1    10009  2.1.0.9
+ 1.0.10beta1          1    10010  2.1.0.10beta1
+ 1.0.10rc1            1    10010  2.1.0.10rc1
+ 1.0.10               1    10010  2.1.0.10
+ 1.0.11beta1-3        1    10011  2.1.0.11beta1-3
+ 1.0.11rc1            1    10011  2.1.0.11rc1
+ 1.0.11               1    10011  2.1.0.11
+ 1.0.12beta1-2        2    10012  2.1.0.12beta1-2
+ 1.0.12rc1            2    10012  2.1.0.12rc1
+ 1.0.12               2    10012  2.1.0.12
+ 1.1.0a-f             -    10100  2.1.1.0a-f abandoned
+ 1.2.0beta1-2         2    10200  2.1.2.0beta1-2
+ 1.2.0beta3-4         3    10200  3.1.2.0beta3-4
+
+Henceforth the source version will match the shared-library minor
+and patch numbers; the shared-library major version number will be
+used for changes in backward compatibility, as it is intended.  The
+PNG_PNGLIB_VER macro, which is not used within libpng but is available
+for applications, is an unsigned integer of the form xyyzz corresponding
+to the source version x.y.z (leading zeros in y and z).  Beta versions
+were given the previous public release number plus a letter, until
+version 1.0.6j; from then on they were given the upcoming public
+release number plus "betaNN" or "rcN".
+
+.SH "SEE ALSO"
+libpngpf(3), png(5)
+.LP
+.IR libpng :
+.IP
+ftp://ftp.uu.net/graphics/png
+http://www.libpng.org/pub/png
+
+.LP
+.IR zlib :
+.IP
+(generally) at the same location as
+.I libpng
+or at
+.br
+ftp://ftp.uu.net/pub/archiving/zip/zlib
+.br
+ftp://ftp.info-zip.org/pub/infozip/zlib
+
+.LP
+.IR PNG specification: RFC 2083
+.IP
+(generally) at the same location as
+.I libpng
+or at
+.br
+ftp://ds.internic.net/rfc/rfc2083.txt
+.br
+or (as a W3C Recommendation) at
+.br
+http://www.w3.org/TR/REC-png.html
+
+.LP
+In the case of any inconsistency between the PNG specification
+and this library, the specification takes precedence.
+
+.SH AUTHORS
+This man page: Glenn Randers-Pehrson
+<randeg@alum.rpi.edu>
+
+The contributing authors would like to thank all those who helped
+with testing, bug fixes, and patience.  This wouldn't have been
+possible without all of you.
+
+Thanks to Frank J. T. Wojcik for helping with the documentation.
+
+Libpng version 1.2.0 - September 1, 2001:
+Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
+Currently maintained by Glenn Randers-Pehrson (randeg@alum.rpi.edu).
+
+Supported by the PNG development group
+.br
+(png-implement@ccrc.wustl.edu).
+
+.SH COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+(This copy of the libpng notices is provided for your convenience.  In case of
+any discrepancy between this copy and the notices in the file png.h that is
+included in the libpng distribution, the latter shall prevail.)
+
+If you modify libpng you may insert additional notices immediately following
+this sentence.
+
+libpng versions 1.0.7, July 1, 2000, through  1.2.0, September 1, 2001, are
+Copyright (c) 2000-2001 Glenn Randers-Pehrson, and are
+distributed according to the same disclaimer and license as libpng-1.0.6
+with the following individuals added to the list of Contributing Authors
+
+   Simon-Pierre Cadieux
+   Eric S. Raymond
+   Gilles Vollant
+
+and with the following additions to the disclaimer:
+
+   There is no warranty against interference with your
+   enjoyment of the library or against infringement.
+   There is no warranty that our efforts or the library
+   will fulfill any of your particular purposes or needs.
+   This library is provided with all faults, and the entire
+   risk of satisfactory quality, performance, accuracy, and
+   effort is with the user.
+
+libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+Distributed according to the same disclaimer and license as libpng-0.96,
+with the following individuals added to the list of Contributing Authors:
+
+   Tom Lane
+   Glenn Randers-Pehrson
+   Willem van Schaik
+
+libpng versions 0.89, June 1996, through 0.96, May 1997, are
+Copyright (c) 1996, 1997 Andreas Dilger
+Distributed according to the same disclaimer and license as libpng-0.88,
+with the following individuals added to the list of Contributing Authors:
+
+   John Bowler
+   Kevin Bracey
+   Sam Bushell
+   Magnus Holmgren
+   Greg Roelofs
+   Tom Tanner
+
+libpng versions 0.5, May 1995, through 0.88, January 1996, are
+Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+
+For the purposes of this copyright and license, "Contributing Authors"
+is defined as the following set of individuals:
+
+   Andreas Dilger
+   Dave Martindale
+   Guy Eric Schalnat
+   Paul Schmidt
+   Tim Wegner
+
+The PNG Reference Library is supplied "AS IS".  The Contributing Authors
+and Group 42, Inc. disclaim all warranties, expressed or implied,
+including, without limitation, the warranties of merchantability and of
+fitness for any purpose.  The Contributing Authors and Group 42, Inc.
+assume no liability for direct, indirect, incidental, special, exemplary,
+or consequential damages, which may result from the use of the PNG
+Reference Library, even if advised of the possibility of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, without fee, subject
+to the following restrictions:
+
+1. The origin of this source code must not be misrepresented.
+
+2. Altered versions must be plainly marked as such and
+   must not be misrepresented as being the original source.
+
+3. This Copyright notice may not be removed or altered from
+   any source or altered source distribution.
+
+The Contributing Authors and Group 42, Inc. specifically permit, without
+fee, and encourage the use of this source code as a component to
+supporting the PNG file format in commercial products.  If you use this
+source code in a product, acknowledgment is not required but would be
+appreciated.
+
+
+A "png_get_copyright" function is available, for convenient use in "about"
+boxes and the like:
+
+   printf("%s",png_get_copyright(NULL));
+
+Also, the PNG logo (in PNG format, of course) is supplied in the
+files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+
+Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is a
+certification mark of the Open Source Initiative.
+
+Glenn Randers-Pehrson
+randeg@alum.rpi.edu
+September 1, 2001
+
+.\" end of man page
+
diff --git a/libraries/libpng-1.2.0/libpng.txt b/libraries/libpng-1.2.0/libpng.txt
new file mode 100644 (file)
index 0000000..fd08096
--- /dev/null
@@ -0,0 +1,2903 @@
+libpng.txt - A description on how to use and modify libpng
+
+ libpng version 1.2.0 - September 1, 2001
+ Updated and distributed by Glenn Randers-Pehrson
+ <randeg@alum.rpi.edu>
+ Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ For conditions of distribution and use, see copyright
+ notice in png.h.
+
+ based on:
+
+ libpng 1.0 beta 6  version 0.96 May 28, 1997
+ Updated and distributed by Andreas Dilger
+ Copyright (c) 1996, 1997 Andreas Dilger
+
+ libpng 1.0 beta 2 - version 0.88  January 26, 1996
+ For conditions of distribution and use, see copyright
+ notice in png.h. Copyright (c) 1995, 1996 Guy Eric
+ Schalnat, Group 42, Inc.
+
+ Updated/rewritten per request in the libpng FAQ
+ Copyright (c) 1995, 1996 Frank J. T. Wojcik
+ December 18, 1995 & January 20, 1996
+
+I. Introduction
+
+This file describes how to use and modify the PNG reference library
+(known as libpng) for your own use.  There are five sections to this
+file: introduction, structures, reading, writing, and modification and
+configuration notes for various special platforms.  In addition to this
+file, example.c is a good starting point for using the library, as
+it is heavily commented and should include everything most people
+will need.  We assume that libpng is already installed; see the
+INSTALL file for instructions on how to install libpng.
+
+Libpng was written as a companion to the PNG specification, as a way
+of reducing the amount of time and effort it takes to support the PNG
+file format in application programs.
+
+The PNG-1.2 specification is available at <http://www.libpng.org/pub/png>
+and at <ftp://ftp.uu.net/graphics/png/documents/>.
+
+The PNG-1.0 specification is available
+as RFC 2083 <ftp://ftp.uu.net/graphics/png/documents/> and as a
+W3C Recommendation <http://www.w3.org/TR/REC.png.html>. Some
+additional chunks are described in the special-purpose public chunks
+documents at <ftp://ftp.uu.net/graphics/png/documents/>.
+
+Other information
+about PNG, and the latest version of libpng, can be found at the PNG home
+page, <http://www.libpng.org/pub/png/>
+and at <ftp://ftp.uu.net/graphics/png/>.
+
+Most users will not have to modify the library significantly; advanced
+users may want to modify it more.  All attempts were made to make it as
+complete as possible, while keeping the code easy to understand.
+Currently, this library only supports C.  Support for other languages
+is being considered.
+
+Libpng has been designed to handle multiple sessions at one time,
+to be easily modifiable, to be portable to the vast majority of
+machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy
+to use.  The ultimate goal of libpng is to promote the acceptance of
+the PNG file format in whatever way possible.  While there is still
+work to be done (see the TODO file), libpng should cover the
+majority of the needs of its users.
+
+Libpng uses zlib for its compression and decompression of PNG files.
+Further information about zlib, and the latest version of zlib, can
+be found at the zlib home page, <http://www.info-zip.org/pub/infozip/zlib/>.
+The zlib compression utility is a general purpose utility that is
+useful for more than PNG files, and can be used without libpng.
+See the documentation delivered with zlib for more details.
+You can usually find the source files for the zlib utility wherever you
+find the libpng source files.
+
+Libpng is thread safe, provided the threads are using different
+instances of the structures.  Each thread should have its own
+png_struct and png_info instances, and thus its own image.
+Libpng does not protect itself against two threads using the
+same instance of a structure.  Note: thread safety may be defeated
+by use of some of the MMX assembler code in pnggccrd.c, which is only
+compiled when the user defines PNG_THREAD_UNSAFE_OK.
+
+
+II. Structures
+
+There are two main structures that are important to libpng, png_struct
+and png_info.  The first, png_struct, is an internal structure that
+will not, for the most part, be used by a user except as the first
+variable passed to every libpng function call.
+
+The png_info structure is designed to provide information about the
+PNG file.  At one time, the fields of png_info were intended to be
+directly accessible to the user.  However, this tended to cause problems
+with applications using dynamically loaded libraries, and as a result
+a set of interface functions for png_info (the png_get_*() and png_set_*()
+functions) was developed.  The fields of png_info are still available for
+older applications, but it is suggested that applications use the new
+interfaces if at all possible.
+
+Applications that do make direct access to the members of png_struct (except
+for png_ptr->jmpbuf) must be recompiled whenever the library is updated,
+and applications that make direct access to the members of png_info must
+be recompiled if they were compiled or loaded with libpng version 1.0.6,
+in which the members were in a different order.  In version 1.0.7, the
+members of the png_info structure reverted to the old order, as they were
+in versions 0.97c through 1.0.5.  Starting with version 2.0.0, both
+structures are going to be hidden, and the contents of the structures will
+only be accessible through the png_get/png_set functions.
+
+The png.h header file is an invaluable reference for programming with libpng.
+And while I'm on the topic, make sure you include the libpng header file:
+
+#include <png.h>
+
+III. Reading
+
+We'll now walk you through the possible functions to call when reading
+in a PNG file sequentially, briefly explaining the syntax and purpose
+of each one.  See example.c and png.h for more detail.  While
+progressive reading is covered in the next section, you will still
+need some of the functions discussed in this section to read a PNG
+file.
+
+Setup
+
+You will want to do the I/O initialization(*) before you get into libpng,
+so if it doesn't work, you don't have much to undo.  Of course, you
+will also want to insure that you are, in fact, dealing with a PNG
+file.  Libpng provides a simple check to see if a file is a PNG file.
+To use it, pass in the first 1 to 8 bytes of the file to the function
+png_sig_cmp(), and it will return 0 if the bytes match the corresponding
+bytes of the PNG signature, or nonzero otherwise.  Of course, the more bytes
+you pass in, the greater the accuracy of the prediction.
+
+If you are intending to keep the file pointer open for use in libpng,
+you must ensure you don't read more than 8 bytes from the beginning
+of the file, and you also have to make a call to png_set_sig_bytes_read()
+with the number of bytes you read from the beginning.  Libpng will
+then only check the bytes (if any) that your program didn't read.
+
+(*): If you are not using the standard I/O functions, you will need
+to replace them with custom functions.  See the discussion under
+Customizing libpng.
+
+
+    FILE *fp = fopen(file_name, "rb");
+    if (!fp)
+    {
+        return (ERROR);
+    }
+    fread(header, 1, number, fp);
+    is_png = !png_sig_cmp(header, 0, number);
+    if (!is_png)
+    {
+        return (NOT_PNG);
+    }
+
+
+Next, png_struct and png_info need to be allocated and initialized.  In
+order to ensure that the size of these structures is correct even with a
+dynamically linked libpng, there are functions to initialize and
+allocate the structures.  We also pass the library version, optional
+pointers to error handling functions, and a pointer to a data struct for
+use by the error functions, if necessary (the pointer and functions can
+be NULL if the default error handlers are to be used).  See the section
+on Changes to Libpng below regarding the old initialization functions.
+The structure allocation functions quietly return NULL if they fail to
+create the structure, so your application should check for that.
+
+    png_structp png_ptr = png_create_read_struct
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+        user_error_fn, user_warning_fn);
+    if (!png_ptr)
+        return (ERROR);
+
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr)
+    {
+        png_destroy_read_struct(&png_ptr,
+           (png_infopp)NULL, (png_infopp)NULL);
+        return (ERROR);
+    }
+
+    png_infop end_info = png_create_info_struct(png_ptr);
+    if (!end_info)
+    {
+        png_destroy_read_struct(&png_ptr, &info_ptr,
+          (png_infopp)NULL);
+        return (ERROR);
+    }
+
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_read_struct_2() instead of png_create_read_struct():
+
+    png_structp png_ptr = png_create_read_struct_2
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+        user_error_fn, user_warning_fn, (png_voidp)
+        user_mem_ptr, user_malloc_fn, user_free_fn);
+
+The error handling routines passed to png_create_read_struct()
+and the memory alloc/free routines passed to png_create_struct_2()
+are only necessary if you are not using the libpng supplied error
+handling and memory alloc/free functions.
+
+When libpng encounters an error, it expects to longjmp back
+to your routine.  Therefore, you will need to call setjmp and pass
+your png_jmpbuf(png_ptr).  If you read the file from different
+routines, you will need to update the jmpbuf field every time you enter
+a new routine that will call a png_*() function.
+
+See your documentation of setjmp/longjmp for your compiler for more
+information on setjmp/longjmp.  See the discussion on libpng error
+handling in the Customizing Libpng section below for more information
+on the libpng error handling.  If an error occurs, and libpng longjmp's
+back to your setjmp, you will want to call png_destroy_read_struct() to
+free any memory.
+
+    if (setjmp(png_jmpbuf(png_ptr)))
+    {
+        png_destroy_read_struct(&png_ptr, &info_ptr,
+           &end_info);
+        fclose(fp);
+        return (ERROR);
+    }
+
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
+Now you need to set up the input code.  The default for libpng is to
+use the C function fread().  If you use this, you will need to pass a
+valid FILE * in the function png_init_io().  Be sure that the file is
+opened in binary mode.  If you wish to handle reading data in another
+way, you need not call the png_init_io() function, but you must then
+implement the libpng I/O methods discussed in the Customizing Libpng
+section below.
+
+    png_init_io(png_ptr, fp);
+
+If you had previously opened the file and read any of the signature from
+the beginning in order to see if this was a PNG file, you need to let
+libpng know that there are some bytes missing from the start of the file.
+
+    png_set_sig_bytes(png_ptr, number);
+
+Setting up callback code
+
+You can set up a callback function to handle any unknown chunks in the
+input stream. You must supply the function
+
+    read_chunk_callback(png_ptr ptr,
+         png_unknown_chunkp chunk);
+    {
+       /* The unknown chunk structure contains your
+          chunk data: */
+           png_byte name[5];
+           png_byte *data;
+           png_size_t size;
+       /* Note that libpng has already taken care of
+          the CRC handling */
+
+       /* put your code here.  Return one of the
+          following: */
+
+       return (-n); /* chunk had an error */
+       return (0); /* did not recognize */
+       return (n); /* success */
+    }
+
+(You can give your function another name that you like instead of
+"read_chunk_callback")
+
+To inform libpng about your function, use
+
+    png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr,
+        read_chunk_callback);
+
+This names not only the callback function, but also a user pointer that
+you can retrieve with
+
+    png_get_user_chunk_ptr(png_ptr);
+
+At this point, you can set up a callback function that will be
+called after each row has been read, which you can use to control
+a progress meter or the like.  It's demonstrated in pngtest.c.
+You must supply a function
+
+    void read_row_callback(png_ptr ptr, png_uint_32 row,
+       int pass);
+    {
+      /* put your code here */
+    }
+
+(You can give it another name that you like instead of "read_row_callback")
+
+To inform libpng about your function, use
+
+    png_set_read_status_fn(png_ptr, read_row_callback);
+
+Unknown-chunk handling
+
+Now you get to set the way the library processes unknown chunks in the
+input PNG stream. Both known and unknown chunks will be read.  Normal
+behavior is that known chunks will be parsed into information in
+various info_ptr members; unknown chunks will be discarded. To change
+this, you can call:
+
+    png_set_keep_unknown_chunks(png_ptr, info_ptr, keep,
+        chunk_list, num_chunks);
+    keep       - 0: do not keep
+                 1: keep only if safe-to-copy
+                 2: keep even if unsafe-to-copy
+    chunk_list - list of chunks affected (a byte string,
+                 five bytes per chunk, NULL or '\0' if
+                 num_chunks is 0)
+    num_chunks - number of chunks affected; if 0, all
+                 unknown chunks are affected
+
+Unknown chunks declared in this way will be saved as raw data onto a
+list of png_unknown_chunk structures.  If a chunk that is normally
+known to libpng is named in the list, it will be handled as unknown,
+according to the "keep" directive.  If a chunk is named in successive
+instances of png_set_keep_unknown_chunks(), the final instance will
+take precedence.
+
+The high-level read interface
+
+At this point there are two ways to proceed; through the high-level
+read interface, or through a sequence of low-level read operations.
+You can use the high-level interface if (a) you are willing to read
+the entire image into memory, and (b) the input transformations
+you want to do are limited to the following set:
+
+    PNG_TRANSFORM_IDENTITY      No transformation
+    PNG_TRANSFORM_STRIP_16      Strip 16-bit samples to
+                                8 bits
+    PNG_TRANSFORM_STRIP_ALPHA   Discard the alpha channel
+    PNG_TRANSFORM_PACKING       Expand 1, 2 and 4-bit
+                                samples to bytes
+    PNG_TRANSFORM_PACKSWAP      Change order of packed
+                                pixels to LSB first
+    PNG_TRANSFORM_EXPAND        Perform set_expand()
+    PNG_TRANSFORM_INVERT_MONO   Invert monochrome images
+    PNG_TRANSFORM_SHIFT         Normalize pixels to the
+                                sBIT depth
+    PNG_TRANSFORM_BGR           Flip RGB to BGR, RGBA
+                                to BGRA
+    PNG_TRANSFORM_SWAP_ALPHA    Flip RGBA to ARGB or GA
+                                to AG
+    PNG_TRANSFORM_INVERT_ALPHA  Change alpha from opacity
+                                to transparency
+    PNG_TRANSFORM_SWAP_ENDIAN   Byte-swap 16-bit samples
+
+(This excludes setting a background color, doing gamma transformation,
+dithering, and setting filler.)  If this is the case, simply do this:
+
+    png_read_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the logical OR of
+some set of transformation flags.  This call is equivalent to png_read_info(),
+followed the set of transformations indicated by the transform mask,
+then png_read_image(), and finally png_read_end().
+
+(The final parameter of this call is not yet used.  Someday it might point
+to transformation parameters required by some future input transform.)
+
+After you have called png_read_png(), you can retrieve the image data
+with
+
+   row_pointers = png_get_rows(png_ptr, info_ptr);
+
+where row_pointers is an array of pointers to the pixel data for each row:
+
+   png_bytep row_pointers[height];
+
+If you know your image size and pixel size ahead of time, you can allocate
+row_pointers prior to calling png_read_png() with
+
+   row_pointers = png_malloc(png_ptr,
+      height*sizeof(png_bytep));
+   for (int i=0; i<height, i++)
+      row_pointers[i]=png_malloc(png_ptr,
+         width*pixel_size);
+   png_set_rows(png_ptr, info_ptr, &row_pointers);
+
+Alternatively you could allocate your image in one big block and define
+row_pointers[i] to point into the proper places in your block.
+
+If you use png_set_rows(), the application is responsible for freeing
+row_pointers (and row_pointers[i], if they were separately allocated).
+
+If you don't allocate row_pointers ahead of time, png_read_png() will
+do it, and it'll be free'ed when you call png_destroy_*().
+
+The low-level read interface
+
+If you are going the low-level route, you are now ready to read all
+the file information up to the actual image data.  You do this with a
+call to png_read_info().
+
+    png_read_info(png_ptr, info_ptr);
+
+This will process all chunks up to but not including the image data.
+
+Querying the info structure
+
+Functions are used to get the information from the info_ptr once it
+has been read.  Note that these fields may not be completely filled
+in until png_read_end() has read the chunk data following the image.
+
+    png_get_IHDR(png_ptr, info_ptr, &width, &height,
+       &bit_depth, &color_type, &interlace_type,
+       &compression_type, &filter_method);
+
+    width          - holds the width of the image
+                     in pixels (up to 2^31).
+    height         - holds the height of the image
+                     in pixels (up to 2^31).
+    bit_depth      - holds the bit depth of one of the
+                     image channels.  (valid values are
+                     1, 2, 4, 8, 16 and depend also on
+                     the color_type.  See also
+                     significant bits (sBIT) below).
+    color_type     - describes which color/alpha channels
+                         are present.
+                     PNG_COLOR_TYPE_GRAY
+                        (bit depths 1, 2, 4, 8, 16)
+                     PNG_COLOR_TYPE_GRAY_ALPHA
+                        (bit depths 8, 16)
+                     PNG_COLOR_TYPE_PALETTE
+                        (bit depths 1, 2, 4, 8)
+                     PNG_COLOR_TYPE_RGB
+                        (bit_depths 8, 16)
+                     PNG_COLOR_TYPE_RGB_ALPHA
+                        (bit_depths 8, 16)
+
+                     PNG_COLOR_MASK_PALETTE
+                     PNG_COLOR_MASK_COLOR
+                     PNG_COLOR_MASK_ALPHA
+
+    filter_method  - (must be PNG_FILTER_TYPE_BASE
+                     for PNG 1.0, and can also be
+                     PNG_INTRAPIXEL_DIFFERENCING if
+                     the PNG datastream is embedded in
+                     a MNG-1.0 datastream)
+    compression_type - (must be PNG_COMPRESSION_TYPE_BASE
+                     for PNG 1.0)
+    interlace_type - (PNG_INTERLACE_NONE or
+                     PNG_INTERLACE_ADAM7)
+    Any or all of interlace_type, compression_type, of
+    filter_method can be NULL if you are
+    not interested in their values.
+
+    channels = png_get_channels(png_ptr, info_ptr);
+    channels       - number of channels of info for the
+                     color type (valid values are 1 (GRAY,
+                     PALETTE), 2 (GRAY_ALPHA), 3 (RGB),
+                     4 (RGB_ALPHA or RGB + filler byte))
+    rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+    rowbytes       - number of bytes needed to hold a row
+
+    signature = png_get_signature(png_ptr, info_ptr);
+    signature      - holds the signature read from the
+                     file (if any).  The data is kept in
+                     the same offset it would be if the
+                     whole signature were read (i.e. if an
+                     application had already read in 4
+                     bytes of signature before starting
+                     libpng, the remaining 4 bytes would
+                     be in signature[4] through signature[7]
+                     (see png_set_sig_bytes())).
+
+
+    width            = png_get_image_width(png_ptr,
+                         info_ptr);
+    height           = png_get_image_height(png_ptr,
+                         info_ptr);
+    bit_depth        = png_get_bit_depth(png_ptr,
+                         info_ptr);
+    color_type       = png_get_color_type(png_ptr,
+                         info_ptr);
+    filter_method    = png_get_filter_type(png_ptr,
+                         info_ptr);
+    compression_type = png_get_compression_type(png_ptr,
+                         info_ptr);
+    interlace_type   = png_get_interlace_type(png_ptr,
+                         info_ptr);
+
+
+These are also important, but their validity depends on whether the chunk
+has been read.  The png_get_valid(png_ptr, info_ptr, PNG_INFO_<chunk>) and
+png_get_<chunk>(png_ptr, info_ptr, ...) functions return non-zero if the
+data has been read, or zero if it is missing.  The parameters to the
+png_get_<chunk> are set directly if they are simple data types, or a pointer
+into the info_ptr is returned for any complex types.
+
+    png_get_PLTE(png_ptr, info_ptr, &palette,
+                     &num_palette);
+    palette        - the palette for the file
+                     (array of png_color)
+    num_palette    - number of entries in the palette
+
+    png_get_gAMA(png_ptr, info_ptr, &gamma);
+    gamma          - the gamma the file is written
+                     at (PNG_INFO_gAMA)
+
+    png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
+    srgb_intent    - the rendering intent (PNG_INFO_sRGB)
+                     The presence of the sRGB chunk
+                     means that the pixel data is in the
+                     sRGB color space.  This chunk also
+                     implies specific values of gAMA and
+                     cHRM.
+
+    png_get_iCCP(png_ptr, info_ptr, &name,
+       &compression_type, &profile, &proflen);
+    name            - The profile name.
+    compression     - The compression type; always
+                      PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
+                      You may give NULL to this argument to
+                      ignore it.
+    profile         - International Color Consortium color
+                      profile data. May contain NULs.
+    proflen         - length of profile data in bytes.
+
+    png_get_sBIT(png_ptr, info_ptr, &sig_bit);
+    sig_bit        - the number of significant bits for
+                     (PNG_INFO_sBIT) each of the gray,
+                     red, green, and blue channels,
+                     whichever are appropriate for the
+                     given color type (png_color_16)
+
+    png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans,
+                     &trans_values);
+    trans          - array of transparent entries for
+                     palette (PNG_INFO_tRNS)
+    trans_values   - graylevel or color sample values of
+                     the single transparent color for
+                     non-paletted images (PNG_INFO_tRNS)
+    num_trans      - number of transparent entries
+                     (PNG_INFO_tRNS)
+
+    png_get_hIST(png_ptr, info_ptr, &hist);
+                     (PNG_INFO_hIST)
+    hist           - histogram of palette (array of
+                     png_uint_16)
+
+    png_get_tIME(png_ptr, info_ptr, &mod_time);
+    mod_time       - time image was last modified
+                    (PNG_VALID_tIME)
+
+    png_get_bKGD(png_ptr, info_ptr, &background);
+    background     - background color (PNG_VALID_bKGD)
+                     valid 16-bit red, green and blue
+                     values, regardless of color_type
+
+    num_comments   = png_get_text(png_ptr, info_ptr,
+                     &text_ptr, &num_text);
+    num_comments   - number of comments
+    text_ptr       - array of png_text holding image
+                     comments
+    text_ptr[i].compression - type of compression used
+                 on "text" PNG_TEXT_COMPRESSION_NONE
+                           PNG_TEXT_COMPRESSION_zTXt
+                           PNG_ITXT_COMPRESSION_NONE
+                           PNG_ITXT_COMPRESSION_zTXt
+    text_ptr[i].key   - keyword for comment.  Must contain
+                         1-79 characters.
+    text_ptr[i].text  - text comments for current
+                         keyword.  Can be empty.
+    text_ptr[i].text_length - length of text string,
+                 after decompression, 0 for iTXt
+    text_ptr[i].itxt_length - length of itxt string,
+                 after decompression, 0 for tEXt/zTXt
+    text_ptr[i].lang  - language of comment (empty
+                         string for unknown).
+    text_ptr[i].translated_keyword  - keyword in UTF-8
+                         (empty string for unknown).
+    num_text       - number of comments (same as
+                     num_comments; you can put NULL here
+                     to avoid the duplication)
+    Note while png_set_text() will accept text, language,
+    and translated keywords that can be NULL pointers, the
+    structure returned by png_get_text will always contain
+    regular zero-terminated C strings.  They might be
+    empty strings but they will never be NULL pointers.
+
+    num_spalettes = png_get_sPLT(png_ptr, info_ptr,
+       &palette_ptr);
+    palette_ptr    - array of palette structures holding
+                     contents of one or more sPLT chunks
+                     read.
+    num_spalettes  - number of sPLT chunks read.
+
+    png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y,
+       &unit_type);
+    offset_x       - positive offset from the left edge
+                     of the screen
+    offset_y       - positive offset from the top edge
+                     of the screen
+    unit_type      - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
+
+    png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y,
+       &unit_type);
+    res_x          - pixels/unit physical resolution in
+                     x direction
+    res_y          - pixels/unit physical resolution in
+                     x direction
+    unit_type      - PNG_RESOLUTION_UNKNOWN,
+                     PNG_RESOLUTION_METER
+
+    png_get_sCAL(png_ptr, info_ptr, &unit, &width,
+       &height)
+    unit        - physical scale units (an integer)
+    width       - width of a pixel in physical scale units
+    height      - height of a pixel in physical scale units
+                 (width and height are doubles)
+
+    png_get_sCAL_s(png_ptr, info_ptr, &unit, &width,
+       &height)
+    unit        - physical scale units (an integer)
+    width       - width of a pixel in physical scale units
+    height      - height of a pixel in physical scale units
+                 (width and height are strings like "2.54")
+
+    num_unknown_chunks = png_get_unknown_chunks(png_ptr,
+       info_ptr, &unknowns)
+    unknowns          - array of png_unknown_chunk
+                        structures holding unknown chunks
+    unknowns[i].name  - name of unknown chunk
+    unknowns[i].data  - data of unknown chunk
+    unknowns[i].size  - size of unknown chunk's data
+    unknowns[i].location - position of chunk in file
+
+    The value of "i" corresponds to the order in which the
+    chunks were read from the PNG file or inserted with the
+    png_set_unknown_chunks() function.
+
+The data from the pHYs chunk can be retrieved in several convenient
+forms:
+
+    res_x = png_get_x_pixels_per_meter(png_ptr,
+       info_ptr)
+    res_y = png_get_y_pixels_per_meter(png_ptr,
+       info_ptr)
+    res_x_and_y = png_get_pixels_per_meter(png_ptr,
+       info_ptr)
+    res_x = png_get_x_pixels_per_inch(png_ptr,
+       info_ptr)
+    res_y = png_get_y_pixels_per_inch(png_ptr,
+       info_ptr)
+    res_x_and_y = png_get_pixels_per_inch(png_ptr,
+       info_ptr)
+    aspect_ratio = png_get_pixel_aspect_ratio(png_ptr,
+       info_ptr)
+
+   (Each of these returns 0 [signifying "unknown"] if
+       the data is not present or if res_x is 0;
+       res_x_and_y is 0 if res_x != res_y)
+
+The data from the oFFs chunk can be retrieved in several convenient
+forms:
+
+    x_offset = png_get_x_offset_microns(png_ptr, info_ptr);
+    y_offset = png_get_y_offset_microns(png_ptr, info_ptr);
+    x_offset = png_get_x_offset_inches(png_ptr, info_ptr);
+    y_offset = png_get_y_offset_inches(png_ptr, info_ptr);
+
+   (Each of these returns 0 [signifying "unknown" if both
+       x and y are 0] if the data is not present or if the
+       chunk is present but the unit is the pixel)
+
+For more information, see the png_info definition in png.h and the
+PNG specification for chunk contents.  Be careful with trusting
+rowbytes, as some of the transformations could increase the space
+needed to hold a row (expand, filler, gray_to_rgb, etc.).
+See png_read_update_info(), below.
+
+A quick word about text_ptr and num_text.  PNG stores comments in
+keyword/text pairs, one pair per chunk, with no limit on the number
+of text chunks, and a 2^31 byte limit on their size.  While there are
+suggested keywords, there is no requirement to restrict the use to these
+strings.  It is strongly suggested that keywords and text be sensible
+to humans (that's the point), so don't use abbreviations.  Non-printing
+symbols are not allowed.  See the PNG specification for more details.
+There is also no requirement to have text after the keyword.
+
+Keywords should be limited to 79 Latin-1 characters without leading or
+trailing spaces, but non-consecutive spaces are allowed within the
+keyword.  It is possible to have the same keyword any number of times.
+The text_ptr is an array of png_text structures, each holding a
+pointer to a language string, a pointer to a keyword and a pointer to
+a text string.  The text string, language code, and translated
+keyword may be empty or NULL pointers.  The keyword/text
+pairs are put into the array in the order that they are received.
+However, some or all of the text chunks may be after the image, so, to
+make sure you have read all the text chunks, don't mess with these
+until after you read the stuff after the image.  This will be
+mentioned again below in the discussion that goes with png_read_end().
+
+Input transformations
+
+After you've read the header information, you can set up the library
+to handle any special transformations of the image data.  The various
+ways to transform the data will be described in the order that they
+should occur.  This is important, as some of these change the color
+type and/or bit depth of the data, and some others only work on
+certain color types and bit depths.  Even though each transformation
+checks to see if it has data that it can do something with, you should
+make sure to only enable a transformation if it will be valid for the
+data.  For example, don't swap red and blue on grayscale data.
+
+The colors used for the background and transparency values should be
+supplied in the same format/depth as the current image data.  They
+are stored in the same format/depth as the image data in a bKGD or tRNS
+chunk, so this is what libpng expects for this data.  The colors are
+transformed to keep in sync with the image data when an application
+calls the png_read_update_info() routine (see below).
+
+Data will be decoded into the supplied row buffers packed into bytes
+unless the library has been told to transform it into another format.
+For example, 4 bit/pixel paletted or grayscale data will be returned
+2 pixels/byte with the leftmost pixel in the high-order bits of the
+byte, unless png_set_packing() is called.  8-bit RGB data will be stored
+in RGB RGB RGB format unless png_set_filler() is called to insert filler
+bytes, either before or after each RGB triplet.  16-bit RGB data will
+be returned RRGGBB RRGGBB, with the most significant byte of the color
+value first, unless png_set_strip_16() is called to transform it to
+regular RGB RGB triplets, or png_set_filler() is called to insert
+filler bytes, either before or after each RRGGBB triplet.  Similarly,
+8-bit or 16-bit grayscale data can be modified with png_set_filler()
+or png_set_strip_16().
+
+The following code transforms grayscale images of less than 8 to 8 bits,
+changes paletted images to RGB, and adds a full alpha channel if there is
+transparency information in a tRNS chunk.  This is most useful on
+grayscale images with bit depths of 2 or 4 or if there is a multiple-image
+viewing application that wishes to treat all images in the same way.
+
+    if (color_type == PNG_COLOR_TYPE_PALETTE)
+        png_set_palette_to_rgb(png_ptr);
+
+    if (color_type == PNG_COLOR_TYPE_GRAY &&
+        bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);
+
+    if (png_get_valid(png_ptr, info_ptr,
+        PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
+
+These three functions are actually aliases for png_set_expand(), added
+in libpng version 1.0.4, with the function names expanded to improve code
+readability.  In some future version they may actually do different
+things.
+
+PNG can have files with 16 bits per channel.  If you only can handle
+8 bits per channel, this will strip the pixels down to 8 bit.
+
+    if (bit_depth == 16)
+        png_set_strip_16(png_ptr);
+
+If, for some reason, you don't need the alpha channel on an image,
+and you want to remove it rather than combining it with the background
+(but the image author certainly had in mind that you *would* combine
+it with the background, so that's what you should probably do):
+
+    if (color_type & PNG_COLOR_MASK_ALPHA)
+        png_set_strip_alpha(png_ptr);
+
+In PNG files, the alpha channel in an image
+is the level of opacity.  If you need the alpha channel in an image to
+be the level of transparency instead of opacity, you can invert the
+alpha channel (or the tRNS chunk data) after it's read, so that 0 is
+fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit
+images) is fully transparent, with
+
+    png_set_invert_alpha(png_ptr);
+
+PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
+they can, resulting in, for example, 8 pixels per byte for 1 bit
+files.  This code expands to 1 pixel per byte without changing the
+values of the pixels:
+
+    if (bit_depth < 8)
+        png_set_packing(png_ptr);
+
+PNG files have possible bit depths of 1, 2, 4, 8, and 16.  All pixels
+stored in a PNG image have been "scaled" or "shifted" up to the next
+higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] to
+8 bits/sample in the range [0, 255]).  However, it is also possible to
+convert the PNG pixel data back to the original bit depth of the image.
+This call reduces the pixels back down to the original bit depth:
+
+    png_color_8p sig_bit;
+
+    if (png_get_sBIT(png_ptr, info_ptr, &sig_bit))
+        png_set_shift(png_ptr, sig_bit);
+
+PNG files store 3-color pixels in red, green, blue order.  This code
+changes the storage of the pixels to blue, green, red:
+
+    if (color_type == PNG_COLOR_TYPE_RGB ||
+        color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+        png_set_bgr(png_ptr);
+
+PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them
+into 4 or 8 bytes for windowing systems that need them in this format:
+
+    if (color_type == PNG_COLOR_TYPE_RGB)
+        png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE);
+
+where "filler" is the 8 or 16-bit number to fill with, and the location is
+either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether
+you want the filler before the RGB or after.  This transformation
+does not affect images that already have full alpha channels.  To add an
+opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which
+will generate RGBA pixels.
+
+If you are reading an image with an alpha channel, and you need the
+data as ARGB instead of the normal PNG format RGBA:
+
+    if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+        png_set_swap_alpha(png_ptr);
+
+For some uses, you may want a grayscale image to be represented as
+RGB.  This code will do that conversion:
+
+    if (color_type == PNG_COLOR_TYPE_GRAY ||
+        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+          png_set_gray_to_rgb(png_ptr);
+
+Conversely, you can convert an RGB or RGBA image to grayscale or grayscale
+with alpha.
+
+    if (color_type == PNG_COLOR_TYPE_RGB ||
+        color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+          png_set_rgb_to_gray_fixed(png_ptr, error_action,
+             int red_weight, int green_weight);
+
+    error_action = 1: silently do the conversion
+    error_action = 2: issue a warning if the original
+                      image has any pixel where
+                      red != green or red != blue
+    error_action = 3: issue an error and abort the
+                      conversion if the original
+                      image has any pixel where
+                      red != green or red != blue
+
+    red_weight:       weight of red component times 100000
+    green_weight:     weight of green component times 100000
+                      If either weight is negative, default
+                      weights (21268, 71514) are used.
+
+If you have set error_action = 1 or 2, you can
+later check whether the image really was gray, after processing
+the image rows, with the png_get_rgb_to_gray_status(png_ptr) function.
+It will return a png_byte that is zero if the image was gray or
+1 if there were any non-gray pixels.  bKGD and sBIT data
+will be silently converted to grayscale, using the green channel
+data, regardless of the error_action setting.
+
+With red_weight+green_weight<=100000,
+the normalized graylevel is computed:
+
+    int rw = red_weight * 65536;
+    int gw = green_weight * 65536;
+    int bw = 65536 - (rw + gw);
+    gray = (rw*red + gw*green + bw*blue)/65536;
+
+The default values approximate those recommended in the Charles
+Poynton's Color FAQ, <http://www.inforamp.net/~poynton/>
+Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
+
+    Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+
+Libpng approximates this with
+
+    Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
+
+which can be expressed with integers as
+
+    Y = (6969 * R + 23434 * G + 2365 * B)/32768
+
+The calculation is done in a linear colorspace, if the image gamma
+is known.
+
+If you have a grayscale and you are using png_set_expand_depth() or
+png_set_expand() to change to
+a higher bit-depth, you must either supply the background color as a gray
+value at the original file bit-depth (need_expand = 1) or else supply the
+background color as an RGB triplet at the final, expanded bit depth
+(need_expand = 0).  Similarly, if you are reading a paletted image, you
+must either supply the background color as a palette index (need_expand = 1)
+or as an RGB triplet that may or may not be in the palette (need_expand = 0).
+
+    png_color_16 my_background;
+    png_color_16p image_background;
+
+    if (png_get_bKGD(png_ptr, info_ptr, &image_background))
+        png_set_background(png_ptr, image_background,
+          PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+    else
+        png_set_background(png_ptr, &my_background,
+          PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+
+The png_set_background() function tells libpng to composite images
+with alpha or simple transparency against the supplied background
+color.  If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid),
+you may use this color, or supply another color more suitable for
+the current display (e.g., the background color from a web page).  You
+need to tell libpng whether the color is in the gamma space of the
+display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file
+(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one
+that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't
+know why anyone would use this, but it's here).
+
+To properly display PNG images on any kind of system, the application needs
+to know what the display gamma is.  Ideally, the user will know this, and
+the application will allow them to set it.  One method of allowing the user
+to set the display gamma separately for each system is to check for a
+SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be
+correctly set.
+
+Note that display_gamma is the overall gamma correction required to produce
+pleasing results, which depends on the lighting conditions in the surrounding
+environment.  In a dim or brightly lit room, no compensation other than
+the physical gamma exponent of the monitor is needed, while in a dark room
+a slightly smaller exponent is better.
+
+   double gamma, screen_gamma;
+
+   if (/* We have a user-defined screen
+       gamma value */)
+   {
+      screen_gamma = user_defined_screen_gamma;
+   }
+   /* One way that applications can share the same
+      screen gamma value */
+   else if ((gamma_str = getenv("SCREEN_GAMMA"))
+      != NULL)
+   {
+      screen_gamma = (double)atof(gamma_str);
+   }
+   /* If we don't have another value */
+   else
+   {
+      screen_gamma = 2.2; /* A good guess for a
+           PC monitor in a bright office or a dim room */
+      screen_gamma = 2.0; /* A good guess for a
+           PC monitor in a dark room */
+      screen_gamma = 1.7 or 1.0;  /* A good
+           guess for Mac systems */
+   }
+
+The png_set_gamma() function handles gamma transformations of the data.
+Pass both the file gamma and the current screen_gamma.  If the file does
+not have a gamma value, you can pass one anyway if you have an idea what
+it is (usually 0.45455 is a good guess for GIF images on PCs).  Note
+that file gammas are inverted from screen gammas.  See the discussions
+on gamma in the PNG specification for an excellent description of what
+gamma is, and why all applications should support it.  It is strongly
+recommended that PNG viewers support gamma correction.
+
+   if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+      png_set_gamma(png_ptr, screen_gamma, gamma);
+   else
+      png_set_gamma(png_ptr, screen_gamma, 0.45455);
+
+If you need to reduce an RGB file to a paletted file, or if a paletted
+file has more entries then will fit on your screen, png_set_dither()
+will do that.  Note that this is a simple match dither that merely
+finds the closest color available.  This should work fairly well with
+optimized palettes, and fairly badly with linear color cubes.  If you
+pass a palette that is larger then maximum_colors, the file will
+reduce the number of colors in the palette so it will fit into
+maximum_colors.  If there is a histogram, it will use it to make
+more intelligent choices when reducing the palette.  If there is no
+histogram, it may not do as good a job.
+
+   if (color_type & PNG_COLOR_MASK_COLOR)
+   {
+      if (png_get_valid(png_ptr, info_ptr,
+         PNG_INFO_PLTE))
+      {
+         png_uint_16p histogram;
+
+         png_get_hIST(png_ptr, info_ptr,
+            &histogram);
+         png_set_dither(png_ptr, palette, num_palette,
+            max_screen_colors, histogram, 1);
+      }
+      else
+      {
+         png_color std_color_cube[MAX_SCREEN_COLORS] =
+            { ... colors ... };
+
+         png_set_dither(png_ptr, std_color_cube,
+            MAX_SCREEN_COLORS, MAX_SCREEN_COLORS,
+            NULL,0);
+      }
+   }
+
+PNG files describe monochrome as black being zero and white being one.
+The following code will reverse this (make black be one and white be
+zero):
+
+   if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY)
+      png_set_invert_mono(png_ptr);
+
+This function can also be used to invert grayscale and gray-alpha images:
+
+   if (color_type == PNG_COLOR_TYPE_GRAY ||
+        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      png_set_invert_mono(png_ptr);
+
+PNG files store 16 bit pixels in network byte order (big-endian,
+ie. most significant bits first).  This code changes the storage to the
+other way (little-endian, i.e. least significant bits first, the
+way PCs store them):
+
+    if (bit_depth == 16)
+        png_set_swap(png_ptr);
+
+If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
+need to change the order the pixels are packed into bytes, you can use:
+
+    if (bit_depth < 8)
+       png_set_packswap(png_ptr);
+
+Finally, you can write your own transformation function if none of
+the existing ones meets your needs.  This is done by setting a callback
+with
+
+    png_set_read_user_transform_fn(png_ptr,
+       read_transform_fn);
+
+You must supply the function
+
+    void read_transform_fn(png_ptr ptr, row_info_ptr
+       row_info, png_bytep data)
+
+See pngtest.c for a working example.  Your function will be called
+after all of the other transformations have been processed.
+
+You can also set up a pointer to a user structure for use by your
+callback function, and you can inform libpng that your transform
+function will change the number of channels or bit depth with the
+function
+
+    png_set_user_transform_info(png_ptr, user_ptr,
+       user_depth, user_channels);
+
+The user's application, not libpng, is responsible for allocating and
+freeing any memory required for the user structure.
+
+You can retrieve the pointer via the function
+png_get_user_transform_ptr().  For example:
+
+    voidp read_user_transform_ptr =
+       png_get_user_transform_ptr(png_ptr);
+
+The last thing to handle is interlacing; this is covered in detail below,
+but you must call the function here if you want libpng to handle expansion
+of the interlaced image.
+
+    number_of_passes = png_set_interlace_handling(png_ptr);
+
+After setting the transformations, libpng can update your png_info
+structure to reflect any transformations you've requested with this
+call.  This is most useful to update the info structure's rowbytes
+field so you can use it to allocate your image memory.  This function
+will also update your palette with the correct screen_gamma and
+background if these have been given with the calls above.
+
+    png_read_update_info(png_ptr, info_ptr);
+
+After you call png_read_update_info(), you can allocate any
+memory you need to hold the image.  The row data is simply
+raw byte data for all forms of images.  As the actual allocation
+varies among applications, no example will be given.  If you
+are allocating one large chunk, you will need to build an
+array of pointers to each row, as it will be needed for some
+of the functions below.
+
+Reading image data
+
+After you've allocated memory, you can read the image data.
+The simplest way to do this is in one function call.  If you are
+allocating enough memory to hold the whole image, you can just
+call png_read_image() and libpng will read in all the image data
+and put it in the memory area supplied.  You will need to pass in
+an array of pointers to each row.
+
+This function automatically handles interlacing, so you don't need
+to call png_set_interlace_handling() or call this function multiple
+times, or any of that other stuff necessary with png_read_rows().
+
+   png_read_image(png_ptr, row_pointers);
+
+where row_pointers is:
+
+   png_bytep row_pointers[height];
+
+You can point to void or char or whatever you use for pixels.
+
+If you don't want to read in the whole image at once, you can
+use png_read_rows() instead.  If there is no interlacing (check
+interlace_type == PNG_INTERLACE_NONE), this is simple:
+
+    png_read_rows(png_ptr, row_pointers, NULL,
+       number_of_rows);
+
+where row_pointers is the same as in the png_read_image() call.
+
+If you are doing this just one row at a time, you can do this with
+a single row_pointer instead of an array of row_pointers:
+
+    png_bytep row_pointer = row;
+    png_read_row(png_ptr, row_pointer, NULL);
+
+If the file is interlaced (interlace_type != 0 in the IHDR chunk), things
+get somewhat harder.  The only current (PNG Specification version 1.2)
+interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7)
+is a somewhat complicated 2D interlace scheme, known as Adam7, that
+breaks down an image into seven smaller images of varying size, based
+on an 8x8 grid.
+
+libpng can fill out those images or it can give them to you "as is".
+If you want them filled out, there are two ways to do that.  The one
+mentioned in the PNG specification is to expand each pixel to cover
+those pixels that have not been read yet (the "rectangle" method).
+This results in a blocky image for the first pass, which gradually
+smooths out as more pixels are read.  The other method is the "sparkle"
+method, where pixels are drawn only in their final locations, with the
+rest of the image remaining whatever colors they were initialized to
+before the start of the read.  The first method usually looks better,
+but tends to be slower, as there are more pixels to put in the rows.
+
+If you don't want libpng to handle the interlacing details, just call
+png_read_rows() seven times to read in all seven images.  Each of the
+images is a valid image by itself, or they can all be combined on an
+8x8 grid to form a single image (although if you intend to combine them
+you would be far better off using the libpng interlace handling).
+
+The first pass will return an image 1/8 as wide as the entire image
+(every 8th column starting in column 0) and 1/8 as high as the original
+(every 8th row starting in row 0), the second will be 1/8 as wide
+(starting in column 4) and 1/8 as high (also starting in row 0).  The
+third pass will be 1/4 as wide (every 4th pixel starting in column 0) and
+1/8 as high (every 8th row starting in row 4), and the fourth pass will
+be 1/4 as wide and 1/4 as high (every 4th column starting in column 2,
+and every 4th row starting in row 0).  The fifth pass will return an
+image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2),
+while the sixth pass will be 1/2 as wide and 1/2 as high as the original
+(starting in column 1 and row 0).  The seventh and final pass will be as
+wide as the original, and 1/2 as high, containing all of the odd
+numbered scanlines.  Phew!
+
+If you want libpng to expand the images, call this before calling
+png_start_read_image() or png_read_update_info():
+
+    if (interlace_type == PNG_INTERLACE_ADAM7)
+        number_of_passes
+           = png_set_interlace_handling(png_ptr);
+
+This will return the number of passes needed.  Currently, this
+is seven, but may change if another interlace type is added.
+This function can be called even if the file is not interlaced,
+where it will return one pass.
+
+If you are not going to display the image after each pass, but are
+going to wait until the entire image is read in, use the sparkle
+effect.  This effect is faster and the end result of either method
+is exactly the same.  If you are planning on displaying the image
+after each pass, the "rectangle" effect is generally considered the
+better looking one.
+
+If you only want the "sparkle" effect, just call png_read_rows() as
+normal, with the third parameter NULL.  Make sure you make pass over
+the image number_of_passes times, and you don't change the data in the
+rows between calls.  You can change the locations of the data, just
+not the data.  Each pass only writes the pixels appropriate for that
+pass, and assumes the data from previous passes is still valid.
+
+    png_read_rows(png_ptr, row_pointers, NULL,
+       number_of_rows);
+
+If you only want the first effect (the rectangles), do the same as
+before except pass the row buffer in the third parameter, and leave
+the second parameter NULL.
+
+    png_read_rows(png_ptr, NULL, row_pointers,
+       number_of_rows);
+
+Finishing a sequential read
+
+After you are finished reading the image through either the high- or
+low-level interfaces, you can finish reading the file.  If you are
+interested in comments or time, which may be stored either before or
+after the image data, you should pass the separate png_info struct if
+you want to keep the comments from before and after the image
+separate.  If you are not interested, you can pass NULL.
+
+   png_read_end(png_ptr, end_info);
+
+When you are done, you can free all memory allocated by libpng like this:
+
+   png_destroy_read_struct(&png_ptr, &info_ptr,
+       &end_info);
+
+It is also possible to individually free the info_ptr members that
+point to libpng-allocated storage with the following function:
+
+    png_free_data(png_ptr, info_ptr, mask, seq)
+    mask - identifies data to be freed, a mask
+           containing the logical OR of one or
+           more of
+             PNG_FREE_PLTE, PNG_FREE_TRNS,
+             PNG_FREE_HIST, PNG_FREE_ICCP,
+             PNG_FREE_PCAL, PNG_FREE_ROWS,
+             PNG_FREE_SCAL, PNG_FREE_SPLT,
+             PNG_FREE_TEXT, PNG_FREE_UNKN,
+           or simply PNG_FREE_ALL
+    seq  - sequence number of item to be freed
+           (-1 for all items)
+
+This function may be safely called when the relevant storage has
+already been freed, or has not yet been allocated, or was allocated
+by the user and not by libpng,  and will in those
+cases do nothing.  The "seq" parameter is ignored if only one item
+of the selected data type, such as PLTE, is allowed.  If "seq" is not
+-1, and multiple items are allowed for the data type identified in
+the mask, such as text or sPLT, only the n'th item in the structure
+is freed, where n is "seq".
+
+The default behavior is only to free data that was allocated internally
+by libpng.  This can be changed, so that libpng will not free the data,
+or so that it will free data that was allocated by the user with png_malloc()
+or png_zalloc() and passed in via a png_set_*() function, with
+
+    png_data_freer(png_ptr, info_ptr, freer, mask)
+    mask   - which data elements are affected
+             same choices as in png_free_data()
+    freer  - one of
+               PNG_DESTROY_WILL_FREE_DATA
+               PNG_SET_WILL_FREE_DATA
+               PNG_USER_WILL_FREE_DATA
+
+This function only affects data that has already been allocated.
+You can call this function after reading the PNG data but before calling
+any png_set_*() functions, to control whether the user or the png_set_*()
+function is responsible for freeing any existing data that might be present,
+and again after the png_set_*() functions to control whether the user
+or png_destroy_*() is supposed to free the data.  When the user assumes
+responsibility for libpng-allocated data, the application must use
+png_free() to free it, and when the user transfers responsibility to libpng
+for data that the user has allocated, the user must have used png_malloc()
+or png_zalloc() to allocate it.
+
+If you allocated your row_pointers in a single block, as suggested above in
+the description of the high level read interface, you must not transfer
+responsibility for freeing it to the png_set_rows or png_read_destroy function,
+because they would also try to free the individual row_pointers[i].
+
+If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
+separately, do not transfer responsibility for freeing text_ptr to libpng,
+because when libpng fills a png_text structure it combines these members with
+the key member, and png_free_data() will free only text_ptr.key.  Similarly,
+if you transfer responsibility for free'ing text_ptr from libpng to your
+application, your application must not separately free those members.
+
+The png_free_data() function will turn off the "valid" flag for anything
+it frees.  If you need to turn the flag off for a chunk that was freed by your
+application instead of by libpng, you can use
+
+    png_set_invalid(png_ptr, info_ptr, mask);
+    mask - identifies the chunks to be made invalid,
+           containing the logical OR of one or
+           more of
+             PNG_INFO_gAMA, PNG_INFO_sBIT,
+             PNG_INFO_cHRM, PNG_INFO_PLTE,
+             PNG_INFO_tRNS, PNG_INFO_bKGD,
+             PNG_INFO_hIST, PNG_INFO_pHYs,
+             PNG_INFO_oFFs, PNG_INFO_tIME,
+             PNG_INFO_pCAL, PNG_INFO_sRGB,
+             PNG_INFO_iCCP, PNG_INFO_sPLT,
+             PNG_INFO_sCAL, PNG_INFO_IDAT
+
+For a more compact example of reading a PNG image, see the file example.c.
+
+Reading PNG files progressively
+
+The progressive reader is slightly different then the non-progressive
+reader.  Instead of calling png_read_info(), png_read_rows(), and
+png_read_end(), you make one call to png_process_data(), which calls
+callbacks when it has the info, a row, or the end of the image.  You
+set up these callbacks with png_set_progressive_read_fn().  You don't
+have to worry about the input/output functions of libpng, as you are
+giving the library the data directly in png_process_data().  I will
+assume that you have read the section on reading PNG files above,
+so I will only highlight the differences (although I will show
+all of the code).
+
+png_structp png_ptr;
+png_infop info_ptr;
+
+ /*  An example code fragment of how you would
+     initialize the progressive reader in your
+     application. */
+ int
+ initialize_png_reader()
+ {
+    png_ptr = png_create_read_struct
+        (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+         user_error_fn, user_warning_fn);
+    if (!png_ptr)
+        return (ERROR);
+    info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr)
+    {
+        png_destroy_read_struct(&png_ptr, (png_infopp)NULL,
+           (png_infopp)NULL);
+        return (ERROR);
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr)))
+    {
+        png_destroy_read_struct(&png_ptr, &info_ptr,
+           (png_infopp)NULL);
+        return (ERROR);
+    }
+
+    /* This one's new.  You can provide functions
+       to be called when the header info is valid,
+       when each row is completed, and when the image
+       is finished.  If you aren't using all functions,
+       you can specify NULL parameters.  Even when all
+       three functions are NULL, you need to call
+       png_set_progressive_read_fn().  You can use
+       any struct as the user_ptr (cast to a void pointer
+       for the function call), and retrieve the pointer
+       from inside the callbacks using the function
+
+          png_get_progressive_ptr(png_ptr);
+
+       which will return a void pointer, which you have
+       to cast appropriately.
+     */
+    png_set_progressive_read_fn(png_ptr, (void *)user_ptr,
+        info_callback, row_callback, end_callback);
+
+    return 0;
+ }
+
+ /* A code fragment that you call as you receive blocks
+   of data */
+ int
+ process_data(png_bytep buffer, png_uint_32 length)
+ {
+    if (setjmp(png_jmpbuf(png_ptr)))
+    {
+        png_destroy_read_struct(&png_ptr, &info_ptr,
+           (png_infopp)NULL);
+        return (ERROR);
+    }
+
+    /* This one's new also.  Simply give it a chunk
+       of data from the file stream (in order, of
+       course).  On machines with segmented memory
+       models machines, don't give it any more than
+       64K.  The library seems to run fine with sizes
+       of 4K. Although you can give it much less if
+       necessary (I assume you can give it chunks of
+       1 byte, I haven't tried less then 256 bytes
+       yet).  When this function returns, you may
+       want to display any rows that were generated
+       in the row callback if you don't already do
+       so there.
+     */
+    png_process_data(png_ptr, info_ptr, buffer, length);
+    return 0;
+ }
+
+ /* This function is called (as set by
+    png_set_progressive_read_fn() above) when enough data
+    has been supplied so all of the header has been
+    read.
+ */
+ void
+ info_callback(png_structp png_ptr, png_infop info)
+ {
+    /* Do any setup here, including setting any of
+       the transformations mentioned in the Reading
+       PNG files section.  For now, you _must_ call
+       either png_start_read_image() or
+       png_read_update_info() after all the
+       transformations are set (even if you don't set
+       any).  You may start getting rows before
+       png_process_data() returns, so this is your
+       last chance to prepare for that.
+     */
+ }
+
+ /* This function is called when each row of image
+    data is complete */
+ void
+ row_callback(png_structp png_ptr, png_bytep new_row,
+    png_uint_32 row_num, int pass)
+ {
+    /* If the image is interlaced, and you turned
+       on the interlace handler, this function will
+       be called for every row in every pass.  Some
+       of these rows will not be changed from the
+       previous pass.  When the row is not changed,
+       the new_row variable will be NULL.  The rows
+       and passes are called in order, so you don't
+       really need the row_num and pass, but I'm
+       supplying them because it may make your life
+       easier.
+
+       For the non-NULL rows of interlaced images,
+       you must call png_progressive_combine_row()
+       passing in the row and the old row.  You can
+       call this function for NULL rows (it will just
+       return) and for non-interlaced images (it just
+       does the memcpy for you) if it will make the
+       code easier.  Thus, you can just do this for
+       all cases:
+     */
+
+        png_progressive_combine_row(png_ptr, old_row,
+          new_row);
+
+    /* where old_row is what was displayed for
+       previously for the row.  Note that the first
+       pass (pass == 0, really) will completely cover
+       the old row, so the rows do not have to be
+       initialized.  After the first pass (and only
+       for interlaced images), you will have to pass
+       the current row, and the function will combine
+       the old row and the new row.
+    */
+ }
+
+ void
+ end_callback(png_structp png_ptr, png_infop info)
+ {
+    /* This function is called after the whole image
+       has been read, including any chunks after the
+       image (up to and including the IEND).  You
+       will usually have the same info chunk as you
+       had in the header, although some data may have
+       been added to the comments and time fields.
+
+       Most people won't do much here, perhaps setting
+       a flag that marks the image as finished.
+     */
+ }
+
+
+
+IV. Writing
+
+Much of this is very similar to reading.  However, everything of
+importance is repeated here, so you won't have to constantly look
+back up in the reading section to understand writing.
+
+Setup
+
+You will want to do the I/O initialization before you get into libpng,
+so if it doesn't work, you don't have anything to undo. If you are not
+using the standard I/O functions, you will need to replace them with
+custom writing functions.  See the discussion under Customizing libpng.
+
+    FILE *fp = fopen(file_name, "wb");
+    if (!fp)
+    {
+       return (ERROR);
+    }
+
+Next, png_struct and png_info need to be allocated and initialized.
+As these can be both relatively large, you may not want to store these
+on the stack, unless you have stack space to spare.  Of course, you
+will want to check if they return NULL.  If you are also reading,
+you won't want to name your read structure and your write structure
+both "png_ptr"; you can call them anything you like, such as
+"read_ptr" and "write_ptr".  Look at pngtest.c, for example.
+
+    png_structp png_ptr = png_create_write_struct
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+        user_error_fn, user_warning_fn);
+    if (!png_ptr)
+       return (ERROR);
+
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr)
+    {
+       png_destroy_write_struct(&png_ptr,
+         (png_infopp)NULL);
+       return (ERROR);
+    }
+
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_write_struct_2() instead of png_create_write_struct():
+
+    png_structp png_ptr = png_create_write_struct_2
+       (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+        user_error_fn, user_warning_fn, (png_voidp)
+        user_mem_ptr, user_malloc_fn, user_free_fn);
+
+After you have these structures, you will need to set up the
+error handling.  When libpng encounters an error, it expects to
+longjmp() back to your routine.  Therefore, you will need to call
+setjmp() and pass the png_jmpbuf(png_ptr).  If you
+write the file from different routines, you will need to update
+the png_jmpbuf(png_ptr) every time you enter a new routine that will
+call a png_*() function.  See your documentation of setjmp/longjmp
+for your compiler for more information on setjmp/longjmp.  See
+the discussion on libpng error handling in the Customizing Libpng
+section below for more information on the libpng error handling.
+
+    if (setjmp(png_jmpbuf(png_ptr)))
+    {
+       png_destroy_write_struct(&png_ptr, &info_ptr);
+       fclose(fp);
+       return (ERROR);
+    }
+    ...
+    return;
+
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
+Now you need to set up the output code.  The default for libpng is to
+use the C function fwrite().  If you use this, you will need to pass a
+valid FILE * in the function png_init_io().  Be sure that the file is
+opened in binary mode.  Again, if you wish to handle writing data in
+another way, see the discussion on libpng I/O handling in the Customizing
+Libpng section below.
+
+    png_init_io(png_ptr, fp);
+
+Write callbacks
+
+At this point, you can set up a callback function that will be
+called after each row has been written, which you can use to control
+a progress meter or the like.  It's demonstrated in pngtest.c.
+You must supply a function
+
+    void write_row_callback(png_ptr, png_uint_32 row,
+       int pass);
+    {
+      /* put your code here */
+    }
+
+(You can give it another name that you like instead of "write_row_callback")
+
+To inform libpng about your function, use
+
+    png_set_write_status_fn(png_ptr, write_row_callback);
+
+You now have the option of modifying how the compression library will
+run.  The following functions are mainly for testing, but may be useful
+in some cases, like if you need to write PNG files extremely fast and
+are willing to give up some compression, or if you want to get the
+maximum possible compression at the expense of slower writing.  If you
+have no special needs in this area, let the library do what it wants by
+not calling this function at all, as it has been tuned to deliver a good
+speed/compression ratio. The second parameter to png_set_filter() is
+the filter method, for which the only valid values are 0 (as of the
+July 1999 PNG specification, version 1.2) or 64 (if you are writing
+a PNG datastream that is to be embedded in a MNG datastream).  The third
+parameter is a flag that indicates which filter type(s) are to be tested
+for each scanline.  See the PNG specification for details on the specific filter
+types.
+
+
+    /* turn on or off filtering, and/or choose
+       specific filters.  You can use either a single
+       PNG_FILTER_VALUE_NAME or the logical OR of one
+       or more PNG_FILTER_NAME masks. */
+    png_set_filter(png_ptr, 0,
+       PNG_FILTER_NONE  | PNG_FILTER_VALUE_NONE |
+       PNG_FILTER_SUB   | PNG_FILTER_VALUE_SUB  |
+       PNG_FILTER_UP    | PNG_FILTER_VALUE_UP   |
+       PNG_FILTER_AVE   | PNG_FILTER_VALUE_AVE  |
+       PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
+       PNG_ALL_FILTERS);
+
+If an application
+wants to start and stop using particular filters during compression,
+it should start out with all of the filters (to ensure that the previous
+row of pixels will be stored in case it's needed later), and then add
+and remove them after the start of compression.
+
+If you are writing a PNG datastream that is to be embedded in a MNG
+datastream, the second parameter can be either 0 or 64.
+
+The png_set_compression_*() functions interface to the zlib compression
+library, and should mostly be ignored unless you really know what you are
+doing.  The only generally useful call is png_set_compression_level()
+which changes how much time zlib spends on trying to compress the image
+data.  See the Compression Library (zlib.h and algorithm.txt, distributed
+with zlib) for details on the compression levels.
+
+    /* set the zlib compression level */
+    png_set_compression_level(png_ptr,
+        Z_BEST_COMPRESSION);
+
+    /* set other zlib parameters */
+    png_set_compression_mem_level(png_ptr, 8);
+    png_set_compression_strategy(png_ptr,
+        Z_DEFAULT_STRATEGY);
+    png_set_compression_window_bits(png_ptr, 15);
+    png_set_compression_method(png_ptr, 8);
+    png_set_compression_buffer_size(png_ptr, 8192)
+
+extern PNG_EXPORT(void,png_set_zbuf_size)
+
+Setting the contents of info for output
+
+You now need to fill in the png_info structure with all the data you
+wish to write before the actual image.  Note that the only thing you
+are allowed to write after the image is the text chunks and the time
+chunk (as of PNG Specification 1.2, anyway).  See png_write_end() and
+the latest PNG specification for more information on that.  If you
+wish to write them before the image, fill them in now, and flag that
+data as being valid.  If you want to wait until after the data, don't
+fill them until png_write_end().  For all the fields in png_info and
+their data types, see png.h.  For explanations of what the fields
+contain, see the PNG specification.
+
+Some of the more important parts of the png_info are:
+
+    png_set_IHDR(png_ptr, info_ptr, width, height,
+       bit_depth, color_type, interlace_type,
+       compression_type, filter_method)
+    width          - holds the width of the image
+                     in pixels (up to 2^31).
+    height         - holds the height of the image
+                     in pixels (up to 2^31).
+    bit_depth      - holds the bit depth of one of the
+                     image channels.
+                     (valid values are 1, 2, 4, 8, 16
+                     and depend also on the
+                     color_type.  See also significant
+                     bits (sBIT) below).
+    color_type     - describes which color/alpha
+                     channels are present.
+                     PNG_COLOR_TYPE_GRAY
+                        (bit depths 1, 2, 4, 8, 16)
+                     PNG_COLOR_TYPE_GRAY_ALPHA
+                        (bit depths 8, 16)
+                     PNG_COLOR_TYPE_PALETTE
+                        (bit depths 1, 2, 4, 8)
+                     PNG_COLOR_TYPE_RGB
+                        (bit_depths 8, 16)
+                     PNG_COLOR_TYPE_RGB_ALPHA
+                        (bit_depths 8, 16)
+
+                     PNG_COLOR_MASK_PALETTE
+                     PNG_COLOR_MASK_COLOR
+                     PNG_COLOR_MASK_ALPHA
+
+    interlace_type - PNG_INTERLACE_NONE or
+                     PNG_INTERLACE_ADAM7
+    compression_type - (must be
+                     PNG_COMPRESSION_TYPE_DEFAULT)
+    filter_method  - (must be PNG_FILTER_TYPE_DEFAULT
+                     or, if you are writing a PNG to
+                     be embedded in a MNG datastream,
+                     can also be
+                     PNG_INTRAPIXEL_DIFFERENCING)
+
+    png_set_PLTE(png_ptr, info_ptr, palette,
+       num_palette);
+    palette        - the palette for the file
+                     (array of png_color)
+    num_palette    - number of entries in the palette
+
+    png_set_gAMA(png_ptr, info_ptr, gamma);
+    gamma          - the gamma the image was created
+                     at (PNG_INFO_gAMA)
+
+    png_set_sRGB(png_ptr, info_ptr, srgb_intent);
+    srgb_intent    - the rendering intent
+                     (PNG_INFO_sRGB) The presence of
+                     the sRGB chunk means that the pixel
+                     data is in the sRGB color space.
+                     This chunk also implies specific
+                     values of gAMA and cHRM.  Rendering
+                     intent is the CSS-1 property that
+                     has been defined by the International
+                     Color Consortium
+                     (http://www.color.org).
+                     It can be one of
+                     PNG_sRGB_INTENT_SATURATION,
+                     PNG_sRGB_INTENT_PERCEPTUAL,
+                     PNG_sRGB_INTENT_ABSOLUTE, or
+                     PNG_sRGB_INTENT_RELATIVE.
+
+
+    png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr,
+       srgb_intent);
+    srgb_intent    - the rendering intent
+                     (PNG_INFO_sRGB) The presence of the
+                     sRGB chunk means that the pixel
+                     data is in the sRGB color space.
+                     This function also causes gAMA and
+                     cHRM chunks with the specific values
+                     that are consistent with sRGB to be
+                     written.
+
+    png_set_iCCP(png_ptr, info_ptr, name, compression_type,
+                      profile, proflen);
+    name            - The profile name.
+    compression     - The compression type; always
+                      PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
+                      You may give NULL to this argument to
+                      ignore it.
+    profile         - International Color Consortium color
+                      profile data. May contain NULs.
+    proflen         - length of profile data in bytes.
+
+    png_set_sBIT(png_ptr, info_ptr, sig_bit);
+    sig_bit        - the number of significant bits for
+                     (PNG_INFO_sBIT) each of the gray, red,
+                     green, and blue channels, whichever are
+                     appropriate for the given color type
+                     (png_color_16)
+
+    png_set_tRNS(png_ptr, info_ptr, trans, num_trans,
+       trans_values);
+    trans          - array of transparent entries for
+                     palette (PNG_INFO_tRNS)
+    trans_values   - graylevel or color sample values of
+                     the single transparent color for
+                     non-paletted images (PNG_INFO_tRNS)
+    num_trans      - number of transparent entries
+                     (PNG_INFO_tRNS)
+
+    png_set_hIST(png_ptr, info_ptr, hist);
+                    (PNG_INFO_hIST)
+    hist           - histogram of palette (array of
+                     png_uint_16)
+
+    png_set_tIME(png_ptr, info_ptr, mod_time);
+    mod_time       - time image was last modified
+                     (PNG_VALID_tIME)
+
+    png_set_bKGD(png_ptr, info_ptr, background);
+    background     - background color (PNG_VALID_bKGD)
+
+    png_set_text(png_ptr, info_ptr, text_ptr, num_text);
+    text_ptr       - array of png_text holding image
+                     comments
+    text_ptr[i].compression - type of compression used
+                 on "text" PNG_TEXT_COMPRESSION_NONE
+                           PNG_TEXT_COMPRESSION_zTXt
+                           PNG_ITXT_COMPRESSION_NONE
+                           PNG_ITXT_COMPRESSION_zTXt
+    text_ptr[i].key   - keyword for comment.  Must contain
+                 1-79 characters.
+    text_ptr[i].text  - text comments for current
+                         keyword.  Can be NULL or empty.
+    text_ptr[i].text_length - length of text string,
+                 after decompression, 0 for iTXt
+    text_ptr[i].itxt_length - length of itxt string,
+                 after decompression, 0 for tEXt/zTXt
+    text_ptr[i].lang  - language of comment (NULL or
+                         empty for unknown).
+    text_ptr[i].translated_keyword  - keyword in UTF-8 (NULL
+                         or empty for unknown).
+    num_text       - number of comments
+
+    png_set_sPLT(png_ptr, info_ptr, &palette_ptr,
+       num_spalettes);
+    palette_ptr    - array of png_sPLT_struct structures
+                     to be added to the list of palettes
+                     in the info structure.
+    num_spalettes  - number of palette structures to be
+                     added.
+
+    png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y,
+        unit_type);
+    offset_x  - positive offset from the left
+                     edge of the screen
+    offset_y  - positive offset from the top
+                     edge of the screen
+    unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
+
+    png_set_pHYs(png_ptr, info_ptr, res_x, res_y,
+        unit_type);
+    res_x       - pixels/unit physical resolution
+                  in x direction
+    res_y       - pixels/unit physical resolution
+                  in y direction
+    unit_type   - PNG_RESOLUTION_UNKNOWN,
+                  PNG_RESOLUTION_METER
+
+    png_set_sCAL(png_ptr, info_ptr, unit, width, height)
+    unit        - physical scale units (an integer)
+    width       - width of a pixel in physical scale units
+    height      - height of a pixel in physical scale units
+                  (width and height are doubles)
+
+    png_set_sCAL_s(png_ptr, info_ptr, unit, width, height)
+    unit        - physical scale units (an integer)
+    width       - width of a pixel in physical scale units
+    height      - height of a pixel in physical scale units
+                 (width and height are strings like "2.54")
+
+    png_set_unknown_chunks(png_ptr, info_ptr, &unknowns,
+       num_unknowns)
+    unknowns          - array of png_unknown_chunk
+                        structures holding unknown chunks
+    unknowns[i].name  - name of unknown chunk
+    unknowns[i].data  - data of unknown chunk
+    unknowns[i].size  - size of unknown chunk's data
+    unknowns[i].location - position to write chunk in file
+                           0: do not write chunk
+                           PNG_HAVE_IHDR: before PLTE
+                           PNG_HAVE_PLTE: before IDAT
+                           PNG_AFTER_IDAT: after IDAT
+
+The "location" member is set automatically according to
+what part of the output file has already been written.
+You can change its value after calling png_set_unknown_chunks()
+as demonstrated in pngtest.c.  Within each of the "locations",
+the chunks are sequenced according to their position in the
+structure (that is, the value of "i", which is the order in which
+the chunk was either read from the input file or defined with
+png_set_unknown_chunks).
+
+A quick word about text and num_text.  text is an array of png_text
+structures.  num_text is the number of valid structures in the array.
+Each png_text structure holds a language code, a keyword, a text value,
+and a compression type.
+
+The compression types have the same valid numbers as the compression
+types of the image data.  Currently, the only valid number is zero.
+However, you can store text either compressed or uncompressed, unlike
+images, which always have to be compressed.  So if you don't want the
+text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE.
+Because tEXt and zTXt chunks don't have a language field, if you
+specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt
+any language code or translated keyword will not be written out.
+
+Until text gets around 1000 bytes, it is not worth compressing it.
+After the text has been written out to the file, the compression type
+is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR,
+so that it isn't written out again at the end (in case you are calling
+png_write_end() with the same struct.
+
+The keywords that are given in the PNG Specification are:
+
+    Title            Short (one line) title or
+                     caption for image
+    Author           Name of image's creator
+    Description      Description of image (possibly long)
+    Copyright        Copyright notice
+    Creation Time    Time of original image creation
+                     (usually RFC 1123 format, see below)
+    Software         Software used to create the image
+    Disclaimer       Legal disclaimer
+    Warning          Warning of nature of content
+    Source           Device used to create the image
+    Comment          Miscellaneous comment; conversion
+                     from other image format
+
+The keyword-text pairs work like this.  Keywords should be short
+simple descriptions of what the comment is about.  Some typical
+keywords are found in the PNG specification, as is some recommendations
+on keywords.  You can repeat keywords in a file.  You can even write
+some text before the image and some after.  For example, you may want
+to put a description of the image before the image, but leave the
+disclaimer until after, so viewers working over modem connections
+don't have to wait for the disclaimer to go over the modem before
+they start seeing the image.  Finally, keywords should be full
+words, not abbreviations.  Keywords and text are in the ISO 8859-1
+(Latin-1) character set (a superset of regular ASCII) and can not
+contain NUL characters, and should not contain control or other
+unprintable characters.  To make the comments widely readable, stick
+with basic ASCII, and avoid machine specific character set extensions
+like the IBM-PC character set.  The keyword must be present, but
+you can leave off the text string on non-compressed pairs.
+Compressed pairs must have a text string, as only the text string
+is compressed anyway, so the compression would be meaningless.
+
+PNG supports modification time via the png_time structure.  Two
+conversion routines are provided, png_convert_from_time_t() for
+time_t and png_convert_from_struct_tm() for struct tm.  The
+time_t routine uses gmtime().  You don't have to use either of
+these, but if you wish to fill in the png_time structure directly,
+you should provide the time in universal time (GMT) if possible
+instead of your local time.  Note that the year number is the full
+year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and
+that months start with 1.
+
+If you want to store the time of the original image creation, you should
+use a plain tEXt chunk with the "Creation Time" keyword.  This is
+necessary because the "creation time" of a PNG image is somewhat vague,
+depending on whether you mean the PNG file, the time the image was
+created in a non-PNG format, a still photo from which the image was
+scanned, or possibly the subject matter itself.  In order to facilitate
+machine-readable dates, it is recommended that the "Creation Time"
+tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"),
+although this isn't a requirement.  Unlike the tIME chunk, the
+"Creation Time" tEXt chunk is not expected to be automatically changed
+by the software.  To facilitate the use of RFC 1123 dates, a function
+png_convert_to_rfc1123(png_timep) is provided to convert from PNG
+time to an RFC 1123 format string.
+
+Writing unknown chunks
+
+You can use the png_set_unknown_chunks function to queue up chunks
+for writing.  You give it a chunk name, raw data, and a size; that's
+all there is to it.  The chunks will be written by the next following
+png_write_info_before_PLTE, png_write_info, or png_write_end function.
+Any chunks previously read into the info structure's unknown-chunk
+list will also be written out in a sequence that satisfies the PNG
+specification's ordering rules.
+
+The high-level write interface
+
+At this point there are two ways to proceed; through the high-level
+write interface, or through a sequence of low-level write operations.
+You can use the high-level interface if your image data is present
+in the info structure.  All defined output
+transformations are permitted, enabled by the following masks.
+
+    PNG_TRANSFORM_IDENTITY      No transformation
+    PNG_TRANSFORM_PACKING       Pack 1, 2 and 4-bit samples
+    PNG_TRANSFORM_PACKSWAP      Change order of packed
+                                pixels to LSB first
+    PNG_TRANSFORM_INVERT_MONO   Invert monochrome images
+    PNG_TRANSFORM_SHIFT         Normalize pixels to the
+                                sBIT depth
+    PNG_TRANSFORM_BGR           Flip RGB to BGR, RGBA
+                                to BGRA
+    PNG_TRANSFORM_SWAP_ALPHA    Flip RGBA to ARGB or GA
+                                to AG
+    PNG_TRANSFORM_INVERT_ALPHA  Change alpha from opacity
+                                to transparency
+    PNG_TRANSFORM_SWAP_ENDIAN   Byte-swap 16-bit samples
+    PNG_TRANSFORM_STRIP_FILLER  Strip out filler bytes.
+
+If you have valid image data in the info structure (you can use
+png_set_rows() to put image data in the info structure), simply do this:
+
+    png_write_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the logical OR of some set of
+transformation flags.  This call is equivalent to png_write_info(),
+followed the set of transformations indicated by the transform mask,
+then png_write_image(), and finally png_write_end().
+
+(The final parameter of this call is not yet used.  Someday it might point
+to transformation parameters required by some future output transform.)
+
+The low-level write interface
+
+If you are going the low-level route instead, you are now ready to
+write all the file information up to the actual image data.  You do
+this with a call to png_write_info().
+
+    png_write_info(png_ptr, info_ptr);
+
+Note that there is one transformation you may need to do before
+png_write_info().  In PNG files, the alpha channel in an image is the
+level of opacity.  If your data is supplied as a level of
+transparency, you can invert the alpha channel before you write it, so
+that 0 is fully transparent and 255 (in 8-bit or paletted images) or
+65535 (in 16-bit images) is fully opaque, with
+
+    png_set_invert_alpha(png_ptr);
+
+This must appear before png_write_info() instead of later with the
+other transformations because in the case of paletted images the tRNS
+chunk data has to be inverted before the tRNS chunk is written.  If
+your image is not a paletted image, the tRNS data (which in such cases
+represents a single color to be rendered as transparent) won't need to
+be changed, and you can safely do this transformation after your
+png_write_info() call.
+
+If you need to write a private chunk that you want to appear before
+the PLTE chunk when PLTE is present, you can write the PNG info in
+two steps, and insert code to write your own chunk between them:
+
+    png_write_info_before_PLTE(png_ptr, info_ptr);
+    png_set_unknown_chunks(png_ptr, info_ptr, ...);
+    png_write_info(png_ptr, info_ptr);
+
+After you've written the file information, you can set up the library
+to handle any special transformations of the image data.  The various
+ways to transform the data will be described in the order that they
+should occur.  This is important, as some of these change the color
+type and/or bit depth of the data, and some others only work on
+certain color types and bit depths.  Even though each transformation
+checks to see if it has data that it can do something with, you should
+make sure to only enable a transformation if it will be valid for the
+data.  For example, don't swap red and blue on grayscale data.
+
+PNG files store RGB pixels packed into 3 or 6 bytes.  This code tells
+the library to strip input data that has 4 or 8 bytes per pixel down
+to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2
+bytes per pixel).
+
+    png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+
+where the 0 is unused, and the location is either PNG_FILLER_BEFORE or
+PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel
+is stored XRGB or RGBX.
+
+PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
+they can, resulting in, for example, 8 pixels per byte for 1 bit files.
+If the data is supplied at 1 pixel per byte, use this code, which will
+correctly pack the pixels into a single byte:
+
+    png_set_packing(png_ptr);
+
+PNG files reduce possible bit depths to 1, 2, 4, 8, and 16.  If your
+data is of another bit depth, you can write an sBIT chunk into the
+file so that decoders can recover the original data if desired.
+
+    /* Set the true bit depth of the image data */
+    if (color_type & PNG_COLOR_MASK_COLOR)
+    {
+        sig_bit.red = true_bit_depth;
+        sig_bit.green = true_bit_depth;
+        sig_bit.blue = true_bit_depth;
+    }
+    else
+    {
+        sig_bit.gray = true_bit_depth;
+    }
+    if (color_type & PNG_COLOR_MASK_ALPHA)
+    {
+        sig_bit.alpha = true_bit_depth;
+    }
+
+    png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+If the data is stored in the row buffer in a bit depth other than
+one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG),
+this will scale the values to appear to be the correct bit depth as
+is required by PNG.
+
+    png_set_shift(png_ptr, &sig_bit);
+
+PNG files store 16 bit pixels in network byte order (big-endian,
+ie. most significant bits first).  This code would be used if they are
+supplied the other way (little-endian, i.e. least significant bits
+first, the way PCs store them):
+
+    if (bit_depth > 8)
+       png_set_swap(png_ptr);
+
+If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
+need to change the order the pixels are packed into bytes, you can use:
+
+    if (bit_depth < 8)
+       png_set_packswap(png_ptr);
+
+PNG files store 3 color pixels in red, green, blue order.  This code
+would be used if they are supplied as blue, green, red:
+
+    png_set_bgr(png_ptr);
+
+PNG files describe monochrome as black being zero and white being
+one. This code would be used if the pixels are supplied with this reversed
+(black being one and white being zero):
+
+    png_set_invert_mono(png_ptr);
+
+Finally, you can write your own transformation function if none of
+the existing ones meets your needs.  This is done by setting a callback
+with
+
+    png_set_write_user_transform_fn(png_ptr,
+       write_transform_fn);
+
+You must supply the function
+
+    void write_transform_fn(png_ptr ptr, row_info_ptr
+       row_info, png_bytep data)
+
+See pngtest.c for a working example.  Your function will be called
+before any of the other transformations are processed.
+
+You can also set up a pointer to a user structure for use by your
+callback function.
+
+    png_set_user_transform_info(png_ptr, user_ptr, 0, 0);
+
+The user_channels and user_depth parameters of this function are ignored
+when writing; you can set them to zero as shown.
+
+You can retrieve the pointer via the function png_get_user_transform_ptr().
+For example:
+
+    voidp write_user_transform_ptr =
+       png_get_user_transform_ptr(png_ptr);
+
+It is possible to have libpng flush any pending output, either manually,
+or automatically after a certain number of lines have been written.  To
+flush the output stream a single time call:
+
+    png_write_flush(png_ptr);
+
+and to have libpng flush the output stream periodically after a certain
+number of scanlines have been written, call:
+
+    png_set_flush(png_ptr, nrows);
+
+Note that the distance between rows is from the last time png_write_flush()
+was called, or the first row of the image if it has never been called.
+So if you write 50 lines, and then png_set_flush 25, it will flush the
+output on the next scanline, and every 25 lines thereafter, unless
+png_write_flush() is called before 25 more lines have been written.
+If nrows is too small (less than about 10 lines for a 640 pixel wide
+RGB image) the image compression may decrease noticeably (although this
+may be acceptable for real-time applications).  Infrequent flushing will
+only degrade the compression performance by a few percent over images
+that do not use flushing.
+
+Writing the image data
+
+That's it for the transformations.  Now you can write the image data.
+The simplest way to do this is in one function call.  If you have the
+whole image in memory, you can just call png_write_image() and libpng
+will write the image.  You will need to pass in an array of pointers to
+each row.  This function automatically handles interlacing, so you don't
+need to call png_set_interlace_handling() or call this function multiple
+times, or any of that other stuff necessary with png_write_rows().
+
+    png_write_image(png_ptr, row_pointers);
+
+where row_pointers is:
+
+    png_byte *row_pointers[height];
+
+You can point to void or char or whatever you use for pixels.
+
+If you don't want to write the whole image at once, you can
+use png_write_rows() instead.  If the file is not interlaced,
+this is simple:
+
+    png_write_rows(png_ptr, row_pointers,
+       number_of_rows);
+
+row_pointers is the same as in the png_write_image() call.
+
+If you are just writing one row at a time, you can do this with
+a single row_pointer instead of an array of row_pointers:
+
+    png_bytep row_pointer = row;
+
+    png_write_row(png_ptr, row_pointer);
+
+When the file is interlaced, things can get a good deal more
+complicated.  The only currently (as of the PNG Specification
+version 1.2, dated July 1999) defined interlacing scheme for PNG files
+is the "Adam7" interlace scheme, that breaks down an
+image into seven smaller images of varying size.  libpng will build
+these images for you, or you can do them yourself.  If you want to
+build them yourself, see the PNG specification for details of which
+pixels to write when.
+
+If you don't want libpng to handle the interlacing details, just
+use png_set_interlace_handling() and call png_write_rows() the
+correct number of times to write all seven sub-images.
+
+If you want libpng to build the sub-images, call this before you start
+writing any rows:
+
+    number_of_passes =
+       png_set_interlace_handling(png_ptr);
+
+This will return the number of passes needed.  Currently, this
+is seven, but may change if another interlace type is added.
+
+Then write the complete image number_of_passes times.
+
+    png_write_rows(png_ptr, row_pointers,
+       number_of_rows);
+
+As some of these rows are not used, and thus return immediately,
+you may want to read about interlacing in the PNG specification,
+and only update the rows that are actually used.
+
+Finishing a sequential write
+
+After you are finished writing the image, you should finish writing
+the file.  If you are interested in writing comments or time, you should
+pass an appropriately filled png_info pointer.  If you are not interested,
+you can pass NULL.
+
+    png_write_end(png_ptr, info_ptr);
+
+When you are done, you can free all memory used by libpng like this:
+
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+
+It is also possible to individually free the info_ptr members that
+point to libpng-allocated storage with the following function:
+
+    png_free_data(png_ptr, info_ptr, mask, seq)
+    mask  - identifies data to be freed, a mask
+            containing the logical OR of one or
+            more of
+              PNG_FREE_PLTE, PNG_FREE_TRNS,
+              PNG_FREE_HIST, PNG_FREE_ICCP,
+              PNG_FREE_PCAL, PNG_FREE_ROWS,
+              PNG_FREE_SCAL, PNG_FREE_SPLT,
+              PNG_FREE_TEXT, PNG_FREE_UNKN,
+            or simply PNG_FREE_ALL
+    seq   - sequence number of item to be freed
+            (-1 for all items)
+
+This function may be safely called when the relevant storage has
+already been freed, or has not yet been allocated, or was allocated
+by the user  and not by libpng,  and will in those
+cases do nothing.  The "seq" parameter is ignored if only one item
+of the selected data type, such as PLTE, is allowed.  If "seq" is not
+-1, and multiple items are allowed for the data type identified in
+the mask, such as text or sPLT, only the n'th item in the structure
+is freed, where n is "seq".
+
+If you allocated data such as a palette that you passed
+in to libpng with png_set_*, you must not free it until just before the call to
+png_destroy_write_struct().
+
+The default behavior is only to free data that was allocated internally
+by libpng.  This can be changed, so that libpng will not free the data,
+or so that it will free data that was allocated by the user with png_malloc()
+or png_zalloc() and passed in via a png_set_*() function, with
+
+    png_data_freer(png_ptr, info_ptr, freer, mask)
+    mask   - which data elements are affected
+             same choices as in png_free_data()
+    freer  - one of
+               PNG_DESTROY_WILL_FREE_DATA
+               PNG_SET_WILL_FREE_DATA
+               PNG_USER_WILL_FREE_DATA
+
+For example, to transfer responsibility for some data from a read structure
+to a write structure, you could use
+
+    png_data_freer(read_ptr, read_info_ptr,
+       PNG_USER_WILL_FREE_DATA,
+       PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST)
+    png_data_freer(write_ptr, write_info_ptr,
+       PNG_DESTROY_WILL_FREE_DATA,
+       PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST)
+
+thereby briefly reassigning responsibility for freeing to the user but
+immediately afterwards reassigning it once more to the write_destroy
+function.  Having done this, it would then be safe to destroy the read
+structure and continue to use the PLTE, tRNS, and hIST data in the write
+structure.
+
+This function only affects data that has already been allocated.
+You can call this function before calling after the png_set_*() functions
+to control whether the user or png_destroy_*() is supposed to free the data.
+When the user assumes responsibility for libpng-allocated data, the
+application must use
+png_free() to free it, and when the user transfers responsibility to libpng
+for data that the user has allocated, the user must have used png_malloc()
+or png_zalloc() to allocate it.
+
+If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
+separately, do not transfer responsibility for freeing text_ptr to libpng,
+because when libpng fills a png_text structure it combines these members with
+the key member, and png_free_data() will free only text_ptr.key.  Similarly,
+if you transfer responsibility for free'ing text_ptr from libpng to your
+application, your application must not separately free those members.
+For a more compact example of writing a PNG image, see the file example.c.
+
+V. Modifying/Customizing libpng:
+
+There are three issues here.  The first is changing how libpng does
+standard things like memory allocation, input/output, and error handling.
+The second deals with more complicated things like adding new chunks,
+adding new transformations, and generally changing how libpng works.
+Both of those are compile-time issues; that is, they are generally
+determined at the time the code is written, and there is rarely a need
+to provide the user with a means of changing them.  The third is a
+run-time issue:  choosing between and/or tuning one or more alternate
+versions of computationally intensive routines; specifically, optimized
+assembly-language (and therefore compiler- and platform-dependent)
+versions.
+
+Memory allocation, input/output, and error handling
+
+All of the memory allocation, input/output, and error handling in libpng
+goes through callbacks that are user-settable.  The default routines are
+in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively.  To change
+these functions, call the appropriate png_set_*_fn() function.
+
+Memory allocation is done through the functions png_malloc(), png_zalloc(),
+and png_free().  These currently just call the standard C functions.  If
+your pointers can't access more then 64K at a time, you will want to set
+MAXSEG_64K in zlib.h.  Since it is unlikely that the method of handling
+memory allocation on a platform will change between applications, these
+functions must be modified in the library at compile time.  If you prefer
+to use a different method of allocating and freeing data, you can use
+
+    png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr,
+       png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+
+This function also provides a void pointer that can be retrieved via
+
+    mem_ptr=png_get_mem_ptr(png_ptr);
+
+Your replacement memory functions must have prototypes as follows:
+
+    png_voidp malloc_fn(png_structp png_ptr,
+       png_uint_32 size);
+    void free_fn(png_structp png_ptr, png_voidp ptr);
+
+Your malloc_fn() can return NULL in case of failure.  The png_malloc()
+function will call png_error() if it receives a NULL from the system
+memory allocator or from your replacement malloc_fn().
+
+Input/Output in libpng is done through png_read() and png_write(),
+which currently just call fread() and fwrite().  The FILE * is stored in
+png_struct and is initialized via png_init_io().  If you wish to change
+the method of I/O, the library supplies callbacks that you can set
+through the function png_set_read_fn() and png_set_write_fn() at run
+time, instead of calling the png_init_io() function.  These functions
+also provide a void pointer that can be retrieved via the function
+png_get_io_ptr().  For example:
+
+    png_set_read_fn(png_structp read_ptr,
+        voidp read_io_ptr, png_rw_ptr read_data_fn)
+
+    png_set_write_fn(png_structp write_ptr,
+        voidp write_io_ptr, png_rw_ptr write_data_fn,
+        png_flush_ptr output_flush_fn);
+
+    voidp read_io_ptr = png_get_io_ptr(read_ptr);
+    voidp write_io_ptr = png_get_io_ptr(write_ptr);
+
+The replacement I/O functions must have prototypes as follows:
+
+    void user_read_data(png_structp png_ptr,
+        png_bytep data, png_uint_32 length);
+    void user_write_data(png_structp png_ptr,
+        png_bytep data, png_uint_32 length);
+    void user_flush_data(png_structp png_ptr);
+
+Supplying NULL for the read, write, or flush functions sets them back
+to using the default C stream functions.  It is an error to read from
+a write stream, and vice versa.
+
+Error handling in libpng is done through png_error() and png_warning().
+Errors handled through png_error() are fatal, meaning that png_error()
+should never return to its caller.  Currently, this is handled via
+setjmp() and longjmp() (unless you have compiled libpng with
+PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()),
+but you could change this to do things like exit() if you should wish.
+
+On non-fatal errors, png_warning() is called
+to print a warning message, and then control returns to the calling code.
+By default png_error() and png_warning() print a message on stderr via
+fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined
+(because you don't want the messages) or PNG_NO_STDIO defined (because
+fprintf() isn't available).  If you wish to change the behavior of the error
+functions, you will need to set up your own message callbacks.  These
+functions are normally supplied at the time that the png_struct is created.
+It is also possible to redirect errors and warnings to your own replacement
+functions after png_create_*_struct() has been called by calling:
+
+    png_set_error_fn(png_structp png_ptr,
+        png_voidp error_ptr, png_error_ptr error_fn,
+        png_error_ptr warning_fn);
+
+    png_voidp error_ptr = png_get_error_ptr(png_ptr);
+
+If NULL is supplied for either error_fn or warning_fn, then the libpng
+default function will be used, calling fprintf() and/or longjmp() if a
+problem is encountered.  The replacement error functions should have
+parameters as follows:
+
+    void user_error_fn(png_structp png_ptr,
+        png_const_charp error_msg);
+    void user_warning_fn(png_structp png_ptr,
+        png_const_charp warning_msg);
+
+The motivation behind using setjmp() and longjmp() is the C++ throw and
+catch exception handling methods.  This makes the code much easier to write,
+as there is no need to check every return code of every function call.
+However, there are some uncertainties about the status of local variables
+after a longjmp, so the user may want to be careful about doing anything after
+setjmp returns non-zero besides returning itself.  Consult your compiler
+documentation for more details.  For an alternative approach, you may wish
+to use the "cexcept" facility (see http://cexcept.sourceforge.net).
+
+Custom chunks
+
+If you need to read or write custom chunks, you may need to get deeper
+into the libpng code.  The library now has mechanisms for storing
+and writing chunks of unknown type; you can even declare callbacks
+for custom chunks.  Hoewver, this may not be good enough if the
+library code itself needs to know about interactions between your
+chunk and existing `intrinsic' chunks.
+
+If you need to write a new intrinsic chunk, first read the PNG
+specification. Acquire a first level of
+understanding of how it works.  Pay particular attention to the
+sections that describe chunk names, and look at how other chunks were
+designed, so you can do things similarly.  Second, check out the
+sections of libpng that read and write chunks.  Try to find a chunk
+that is similar to yours and use it as a template.  More details can
+be found in the comments inside the code.  It is best to handle unknown
+chunks in a generic method, via callback functions, instead of by
+modifying libpng functions.
+
+If you wish to write your own transformation for the data, look through
+the part of the code that does the transformations, and check out some of
+the simpler ones to get an idea of how they work.  Try to find a similar
+transformation to the one you want to add and copy off of it.  More details
+can be found in the comments inside the code itself.
+
+Configuring for 16 bit platforms
+
+You will want to look into zconf.h to tell zlib (and thus libpng) that
+it cannot allocate more then 64K at a time.  Even if you can, the memory
+won't be accessible.  So limit zlib and libpng to 64K by defining MAXSEG_64K.
+
+Configuring for DOS
+
+For DOS users who only have access to the lower 640K, you will
+have to limit zlib's memory usage via a png_set_compression_mem_level()
+call.  See zlib.h or zconf.h in the zlib library for more information.
+
+Configuring for Medium Model
+
+Libpng's support for medium model has been tested on most of the popular
+compilers.  Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
+defined, and FAR gets defined to far in pngconf.h, and you should be
+all set.  Everything in the library (except for zlib's structure) is
+expecting far data.  You must use the typedefs with the p or pp on
+the end for pointers (or at least look at them and be careful).  Make
+note that the rows of data are defined as png_bytepp, which is an
+unsigned char far * far *.
+
+Configuring for gui/windowing platforms:
+
+You will need to write new error and warning functions that use the GUI
+interface, as described previously, and set them to be the error and
+warning functions at the time that png_create_*_struct() is called,
+in order to have them available during the structure initialization.
+They can be changed later via png_set_error_fn().  On some compilers,
+you may also have to change the memory allocators (png_malloc, etc.).
+
+Configuring for compiler xxx:
+
+All includes for libpng are in pngconf.h.  If you need to add/change/delete
+an include, this is the place to do it.  The includes that are not
+needed outside libpng are protected by the PNG_INTERNAL definition,
+which is only defined for those routines inside libpng itself.  The
+files in libpng proper only include png.h, which includes pngconf.h.
+
+Configuring zlib:
+
+There are special functions to configure the compression.  Perhaps the
+most useful one changes the compression level, which currently uses
+input compression values in the range 0 - 9.  The library normally
+uses the default compression level (Z_DEFAULT_COMPRESSION = 6).  Tests
+have shown that for a large majority of images, compression values in
+the range 3-6 compress nearly as well as higher levels, and do so much
+faster.  For online applications it may be desirable to have maximum speed
+(Z_BEST_SPEED = 1).  With versions of zlib after v0.99, you can also
+specify no compression (Z_NO_COMPRESSION = 0), but this would create
+files larger than just storing the raw bitmap.  You can specify the
+compression level by calling:
+
+    png_set_compression_level(png_ptr, level);
+
+Another useful one is to reduce the memory level used by the library.
+The memory level defaults to 8, but it can be lowered if you are
+short on memory (running DOS, for example, where you only have 640K).
+
+    png_set_compression_mem_level(png_ptr, level);
+
+The other functions are for configuring zlib.  They are not recommended
+for normal use and may result in writing an invalid PNG file.  See
+zlib.h for more information on what these mean.
+
+    png_set_compression_strategy(png_ptr,
+        strategy);
+    png_set_compression_window_bits(png_ptr,
+        window_bits);
+    png_set_compression_method(png_ptr, method);
+    png_set_compression_buffer_size(png_ptr, size);
+
+Controlling row filtering
+
+If you want to control whether libpng uses filtering or not, which
+filters are used, and how it goes about picking row filters, you
+can call one of these functions.  The selection and configuration
+of row filters can have a significant impact on the size and
+encoding speed and a somewhat lesser impact on the decoding speed
+of an image.  Filtering is enabled by default for RGB and grayscale
+images (with and without alpha), but not for paletted images nor
+for any images with bit depths less than 8 bits/pixel.
+
+The 'method' parameter sets the main filtering method, which is
+currently only '0' in the PNG 1.2 specification.  The 'filters'
+parameter sets which filter(s), if any, should be used for each
+scanline.  Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS
+to turn filtering on and off, respectively.
+
+Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB,
+PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise
+ORed together with '|' to specify one or more filters to use.
+These filters are described in more detail in the PNG specification.  If
+you intend to change the filter type during the course of writing
+the image, you should start with flags set for all of the filters
+you intend to use so that libpng can initialize its internal
+structures appropriately for all of the filter types.
+
+    filters = PNG_FILTER_NONE | PNG_FILTER_SUB
+              PNG_FILTER_UP | PNG_FILTER_AVE |
+              PNG_FILTER_PAETH | PNG_ALL_FILTERS;
+    or
+    filters = one of PNG_FILTER_VALUE_NONE,
+              PNG_FILTER_VALUE_SUB, PNG_FILTER_VALUE_UP,
+              PNG_FILTER_VALUE_AVE, PNG_FILTER_VALUE_PAETH
+
+    png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE,
+       filters);
+              The second parameter can also be
+              PNG_INTRAPIXEL_DIFFERENCING if you are
+              writing a PNG to be embedded in a MNG
+              datastream.  This parameter must be the
+              same as the value of filter_method used
+              in png_set_IHDR().
+
+It is also possible to influence how libpng chooses from among the
+available filters.  This is done in two ways - by telling it how
+important it is to keep the same filter for successive rows, and
+by telling it the relative computational costs of the filters.
+
+    double weights[3] = {1.5, 1.3, 1.1},
+       costs[PNG_FILTER_VALUE_LAST] =
+       {1.0, 1.3, 1.3, 1.5, 1.7};
+
+    png_set_filter_selection(png_ptr,
+       PNG_FILTER_SELECTION_WEIGHTED, 3,
+       weights, costs);
+
+The weights are multiplying factors that indicate to libpng that the
+row filter should be the same for successive rows unless another row filter
+is that many times better than the previous filter.  In the above example,
+if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a
+"sum of absolute differences" 1.5 x 1.3 times higher than other filters
+and still be chosen, while the NONE filter could have a sum 1.1 times
+higher than other filters and still be chosen.  Unspecified weights are
+taken to be 1.0, and the specified weights should probably be declining
+like those above in order to emphasize recent filters over older filters.
+
+The filter costs specify for each filter type a relative decoding cost
+to be considered when selecting row filters.  This means that filters
+with higher costs are less likely to be chosen over filters with lower
+costs, unless their "sum of absolute differences" is that much smaller.
+The costs do not necessarily reflect the exact computational speeds of
+the various filters, since this would unduly influence the final image
+size.
+
+Note that the numbers above were invented purely for this example and
+are given only to help explain the function usage.  Little testing has
+been done to find optimum values for either the costs or the weights.
+
+Removing unwanted object code
+
+There are a bunch of #define's in pngconf.h that control what parts of
+libpng are compiled.  All the defines end in _SUPPORTED.  If you are
+never going to use a capability, you can change the #define to #undef
+before recompiling libpng and save yourself code and data space, or
+you can turn off individual capabilities with defines that begin with
+PNG_NO_.
+
+You can also turn all of the transforms and ancillary chunk capabilities
+off en masse with compiler directives that define
+PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
+or all four,
+along with directives to turn on any of the capabilities that you do
+want.  The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable
+the extra transformations but still leave the library fully capable of reading
+and writing PNG files with all known public chunks
+Use of the PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive
+produces a library that is incapable of reading or writing ancillary chunks.
+If you are not using the progressive reading capability, you can
+turn that off with PNG_NO_PROGRESSIVE_READ (don't confuse
+this with the INTERLACING capability, which you'll still have).
+
+All the reading and writing specific code are in separate files, so the
+linker should only grab the files it needs.  However, if you want to
+make sure, or if you are building a stand alone library, all the
+reading files start with pngr and all the writing files start with
+pngw.  The files that don't match either (like png.c, pngtrans.c, etc.)
+are used for both reading and writing, and always need to be included.
+The progressive reader is in pngpread.c
+
+If you are creating or distributing a dynamically linked library (a .so
+or DLL file), you should not remove or disable any parts of the library,
+as this will cause applications linked with different versions of the
+library to fail if they call functions not available in your library.
+The size of the library itself should not be an issue, because only
+those sections that are actually used will be loaded into memory.
+
+Requesting debug printout
+
+The macro definition PNG_DEBUG can be used to request debugging
+printout.  Set it to an integer value in the range 0 to 3.  Higher
+numbers result in increasing amounts of debugging information.  The
+information is printed to the "stderr" file, unless another file
+name is specified in the PNG_DEBUG_FILE macro definition.
+
+When PNG_DEBUG > 0, the following functions (macros) become available:
+
+   png_debug(level, message)
+   png_debug1(level, message, p1)
+   png_debug2(level, message, p1, p2)
+
+in which "level" is compared to PNG_DEBUG to decide whether to print
+the message, "message" is the formatted string to be printed,
+and p1 and p2 are parameters that are to be embedded in the string
+according to printf-style formatting directives.  For example,
+
+   png_debug1(2, "foo=%d\n", foo);
+
+is expanded to
+
+   if(PNG_DEBUG > 2)
+     fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo);
+
+When PNG_DEBUG is defined but is zero, the macros aren't defined, but you
+can still use PNG_DEBUG to control your own debugging:
+
+   #ifdef PNG_DEBUG
+       fprintf(stderr, ...
+   #endif
+
+When PNG_DEBUG = 1, the macros are defined, but only png_debug statements
+having level = 0 will be printed.  There aren't any such statements in
+this version of libpng, but if you insert some they will be printed.
+
+VI.  Runtime optimization
+
+A new feature in libpng 1.2.0 is the ability to dynamically switch between
+standard and optimized versions of some routines.  Currently these are
+limited to three computationally intensive tasks when reading PNG files:
+decoding row filters, expanding interlacing, and combining interlaced or
+transparent row data with previous row data.  Currently the optimized
+versions are available only for x86 (Intel, AMD, etc.) platforms with
+MMX support, though this may change in future versions.  (For example,
+the non-MMX assembler optimizations for zlib might become similarly
+runtime-selectable in future releases, in which case libpng could be
+extended to support them.  Alternatively, the compile-time choice of
+floating-point versus integer routines for gamma correction might become
+runtime-selectable.)
+
+Because such optimizations tend to be very platform- and compiler-dependent,
+both in how they are written and in how they perform, the new runtime code
+in libpng has been written to allow programs to query, enable, and disable
+either specific optimizations or all such optimizations.  For example, to
+enable all possible optimizations (bearing in mind that some "optimizations"
+may actually run more slowly in rare cases):
+
+    #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+       png_uint_32 mask, flags;
+
+       flags = png_get_asm_flags(png_ptr);
+       mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
+       png_set_asm_flags(png_ptr, flags | mask);
+    #endif
+
+To enable only optimizations relevant to reading PNGs, use PNG_SELECT_READ
+by itself when calling png_get_asm_flagmask(); similarly for optimizing
+only writing.  To disable all optimizations:
+
+    #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+       flags = png_get_asm_flags(png_ptr);
+       mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE);
+       png_set_asm_flags(png_ptr, flags & ~mask);
+    #endif
+
+To enable or disable only MMX-related features, use png_get_mmx_flagmask()
+in place of png_get_asm_flagmask().  The mmx version takes one additional
+parameter:
+
+    #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+       int selection = PNG_SELECT_READ | PNG_SELECT_WRITE;
+       int compilerID;
+
+       mask = png_get_mmx_flagmask(selection, &compilerID);
+    #endif
+
+On return, compilerID will indicate which version of the MMX assembler
+optimizations was compiled.  Currently two flavors exist:  Microsoft
+Visual C++ (compilerID == 1) and GNU C (a.k.a. gcc/gas, compilerID == 2).
+On non-x86 platforms or on systems compiled without MMX optimizations, a
+value of -1 is used.
+
+Note that both png_get_asm_flagmask() and png_get_mmx_flagmask() return
+all valid, settable optimization bits for the version of the library that's
+currently in use.  In the case of shared (dynamically linked) libraries,
+this may include optimizations that did not exist at the time the code was
+written and compiled.  It is also possible, of course, to enable only known,
+specific optimizations; for example:
+
+    #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+       flags = PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  \
+             | PNG_ASM_FLAG_MMX_READ_INTERLACE    \
+             | PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
+             | PNG_ASM_FLAG_MMX_READ_FILTER_UP    \
+             | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
+             | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ;
+       png_set_asm_flags(png_ptr, flags);
+    #endif
+
+This method would enable only the MMX read-optimizations available at the
+time of libpng 1.2.0's release, regardless of whether a later version of
+the DLL were actually being used.  (Also note that these functions did not
+exist in versions older than 1.2.0, so any attempt to run a dynamically
+linked app on such an older version would fail.)
+
+To determine whether the processor supports MMX instructions at all, use
+the png_mmx_support() function:
+
+    #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+       mmxsupport = png_mmx_support();
+    #endif
+
+It returns -1 if MMX support is not compiled into libpng, 0 if MMX code
+is compiled but MMX is not supported by the processor, or 1 if MMX support
+is fully available.  Note that png_mmx_support(), png_get_mmx_flagmask(),
+and png_get_asm_flagmask() all may be called without allocating and ini-
+tializing any PNG structures (for example, as part of a usage screen or
+"about" box).
+
+The following code can be used to prevent an application from using the
+thread_unsafe features, even if libpng was built with PNG_THREAD_UNSAFE_OK
+defined:
+
+#if defined(PNG_USE_PNGGCCRD) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) \
+  && defined(PNG_THREAD_UNSAFE_OK)
+    /* Disable thread-unsafe features of pnggccrd */
+    if (png_access_version() >= 10200)
+    {
+      png_uint_32 mmx_disable_mask = 0;
+      png_uint_32 asm_flags;
+
+      mmx_disable_mask |= ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  \
+                          | PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
+                          | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
+                          | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH );
+      asm_flags = png_get_asm_flags(png_ptr);
+      png_set_asm_flags(png_ptr, asm_flags & ~mmx_disable_mask);
+    }
+#endif
+
+For more extensive examples of runtime querying, enabling and disabling
+of optimized features, see contrib/gregbook/readpng2.c in the libpng
+source-code distribution.
+
+
+VII.  MNG support
+
+The MNG specification (available at http://www.libpng.org/pub/mng) allows
+certain extensions to PNG for PNG images that are embedded in MNG datastreams.
+Libpng can support some of these extensions.  To enable them, use the
+png_permit_mng_features() function:
+
+   feature_set = png_permit_mng_features(png_ptr, mask)
+   mask is a png_uint_32 containing the logical OR of the
+        features you want to enable.  These include
+        PNG_FLAG_MNG_EMPTY_PLTE
+        PNG_FLAG_MNG_FILTER_64
+        PNG_ALL_MNG_FEATURES
+   feature_set is a png_32_uint that is the logical AND of
+      your mask with the set of MNG features that is
+      supported by the version of libpng that you are using.
+
+It is an error to use this function when reading or writing a standalone
+PNG file with the PNG 8-byte signature.  The PNG datastream must be wrapped
+in a MNG datastream.  As a minimum, it must have the MNG 8-byte signature
+and the MHDR and MEND chunks.  Libpng does not provide support for these
+or any other MNG chunks; your application must provide its own support for
+them.  You may wish to consider using libmng (available at
+http://www.libmng.com) instead.
+
+VIII.  Changes to Libpng from version 0.88
+
+It should be noted that versions of libpng later than 0.96 are not
+distributed by the original libpng author, Guy Schalnat, nor by
+Andreas Dilger, who had taken over from Guy during 1996 and 1997, and
+distributed versions 0.89 through 0.96, but rather by another member
+of the original PNG Group, Glenn Randers-Pehrson.  Guy and Andreas are
+still alive and well, but they have moved on to other things.
+
+The old libpng functions png_read_init(), png_write_init(),
+png_info_init(), png_read_destroy(), and png_write_destroy() have been
+moved to PNG_INTERNAL in version 0.95 to discourage their use.  These
+functions will be removed from libpng version 2.0.0.
+
+The preferred method of creating and initializing the libpng structures is
+via the png_create_read_struct(), png_create_write_struct(), and
+png_create_info_struct() because they isolate the size of the structures
+from the application, allow version error checking, and also allow the
+use of custom error handling routines during the initialization, which
+the old functions do not.  The functions png_read_destroy() and
+png_write_destroy() do not actually free the memory that libpng
+allocated for these structs, but just reset the data structures, so they
+can be used instead of png_destroy_read_struct() and
+png_destroy_write_struct() if you feel there is too much system overhead
+allocating and freeing the png_struct for each image read.
+
+Setting the error callbacks via png_set_message_fn() before
+png_read_init() as was suggested in libpng-0.88 is no longer supported
+because this caused applications that do not use custom error functions
+to fail if the png_ptr was not initialized to zero.  It is still possible
+to set the error callbacks AFTER png_read_init(), or to change them with
+png_set_error_fn(), which is essentially the same function, but with a new
+name to force compilation errors with applications that try to use the old
+method.
+
+Starting with version 1.0.7, you can find out which version of the library
+you are using at run-time:
+
+   png_uint_32 libpng_vn = png_access_version_number();
+
+The number libpng_vn is constructed from the major version, minor
+version with leading zero, and release number with leading zero,
+(e.g., libpng_vn for version 1.0.7 is 10007).
+
+You can also check which version of png.h you used when compiling your
+application:
+
+   png_uint_32 application_vn = PNG_LIBPNG_VER;
+
+IX. Y2K Compliance in libpng
+
+September 1, 2001
+
+Since the PNG Development group is an ad-hoc body, we can't make
+an official declaration.
+
+This is your unofficial assurance that libpng from version 0.71 and
+upward through 1.2.0 are Y2K compliant.  It is my belief that earlier
+versions were also Y2K compliant.
+
+Libpng only has three year fields.  One is a 2-byte unsigned integer that
+will hold years up to 65535.  The other two hold the date in text
+format, and will hold years up to 9999.
+
+The integer is
+    "png_uint_16 year" in png_time_struct.
+
+The strings are
+    "png_charp time_buffer" in png_struct and
+    "near_time_buffer", which is a local character string in png.c.
+
+There are seven time-related functions:
+
+    png_convert_to_rfc_1123() in png.c
+      (formerly png_convert_to_rfc_1152() in error)
+    png_convert_from_struct_tm() in pngwrite.c, called
+      in pngwrite.c
+    png_convert_from_time_t() in pngwrite.c
+    png_get_tIME() in pngget.c
+    png_handle_tIME() in pngrutil.c, called in pngread.c
+    png_set_tIME() in pngset.c
+    png_write_tIME() in pngwutil.c, called in pngwrite.c
+
+All appear to handle dates properly in a Y2K environment.  The
+png_convert_from_time_t() function calls gmtime() to convert from system
+clock time, which returns (year - 1900), which we properly convert to
+the full 4-digit year.  There is a possibility that applications using
+libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+function, or that they are incorrectly passing only a 2-digit year
+instead of "year - 1900" into the png_convert_from_struct_tm() function,
+but this is not under our control.  The libpng documentation has always
+stated that it works with 4-digit years, and the APIs have been
+documented as such.
+
+The tIME chunk itself is also Y2K compliant.  It uses a 2-byte unsigned
+integer to hold the year, and can hold years as large as 65535.
+
+zlib, upon which libpng depends, is also Y2K compliant.  It contains
+no date-related code.
+
+
+   Glenn Randers-Pehrson
+   libpng maintainer
+   PNG Development Group
diff --git a/libraries/libpng-1.2.0/libpngpf.3 b/libraries/libpng-1.2.0/libpngpf.3
new file mode 100644 (file)
index 0000000..f3eb09d
--- /dev/null
@@ -0,0 +1,556 @@
+.TH LIBPNGPF 3 "September 1, 2001"
+.SH NAME
+libpng \- Portable Network Graphics (PNG) Reference Library 1.2.0
+(private functions)
+.SH SYNOPSIS
+\fB#include <png.h>\fP
+
+\fI\fB
+
+\fBvoid png_build_gamma_table (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_build_grayscale_palette (int \fP\fIbit_depth\fP\fB, png_colorp \fIpalette\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_calculate_crc (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIptr\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_check_chunk_name (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_size_t png_check_keyword (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charpp \fInew_key\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fImask\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_correct_palette (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_crc_error (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_crc_finish (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIskip\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_crc_read (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuf\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_create_struct (int \fItype\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_create_struct_2 (int \fP\fItype\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_voidp \fImem_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_charp png_decompress_chunk (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcomp_type\fP\fB, png_charp \fP\fIchunkdata\fP\fB, png_size_t \fP\fIchunklength\fP\fB, png_size_t \fP\fIprefix_length\fP\fB, png_size_t \fI*data_length\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_destroy_struct (png_voidp \fIstruct_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_destroy_struct_2 (png_voidp \fP\fIstruct_ptr\fP\fB, png_free_ptr \fP\fIfree_fn\fP\fB, png_voidp \fImem_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_background (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_16p \fP\fItrans_values\fP\fB, png_color_16p \fP\fIbackground\fP\fB, png_color_16p \fP\fIbackground_1\fP\fB, png_bytep \fP\fIgamma_table\fP\fB, png_bytep \fP\fIgamma_from_1\fP\fB, png_bytep \fP\fIgamma_to_1\fP\fB, png_uint_16pp \fP\fIgamma_16\fP\fB, png_uint_16pp \fP\fIgamma_16_from_1\fP\fB, png_uint_16pp \fP\fIgamma_16_to_1\fP\fB, int \fIgamma_shift\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_bgr (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_chop (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_dither (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIpalette_lookup\fP\fB, png_bytep \fIdither_lookup\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_expand (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_16p \fItrans_value\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_expand_palette (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_colorp \fP\fIpalette\fP\fB, png_bytep \fP\fItrans\fP\fB, int \fInum_trans\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_gamma (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIgamma_table\fP\fB, png_uint_16pp \fP\fIgamma_16_table\fP\fB, int \fIgamma_shift\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_gray_to_rgb (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_invert (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_pack (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fIbit_depth\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_packswap (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_read_filler (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, png_uint_32 \fIflags\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_read_interlace (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fP\fIpass\fP\fB, png_uint_32 \fItransformations\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_read_invert_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_read_swap_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_read_transformations (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_do_rgb_to_gray (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_shift (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_8p \fIbit_depth\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_strip_filler (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fIflags\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_swap (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_unpack (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_unshift (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_8p \fIsig_bits\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_write_interlace (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fIpass\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_write_invert_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_write_swap_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_do_write_transformations (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid *png_far_to_near (png_structp png_ptr,png_voidp \fP\fIptr\fP\fB, int \fIcheck\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_flush (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_int_32 png_get_int_32 (png_bytep \fIbuf\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_16 png_get_uint_16 (png_bytep \fIbuf\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_uint_32 (png_bytep \fIbuf\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_handle_as_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_IEND (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_iTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_handle_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_info_destroy (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_init_mmx_flags (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_init_read_transformations (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_process_IDAT_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_length\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_process_some_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_check_crc (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_crc_finish (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_crc_skip (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_fill_buffer (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_handle_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_handle_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_handle_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_have_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_have_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_have_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_process_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_read_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_read_IDAT (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_read_sig (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_read_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_read_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_restore_buffer (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_length\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_push_save_buffer (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_filter_row (png_structp \fP\fIpng_ptr\fP\fB, png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIprev_row\fP\fB, int \fIfilter\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_finish_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_push_finish_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_start_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_reset_crc (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_save_int_32 (png_bytep \fP\fIbuf\fP\fB, png_int_32 \fIi\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_save_uint_16 (png_bytep \fP\fIbuf\fP\fB, unsigned int \fIi\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_save_uint_32 (png_bytep \fP\fIbuf\fP\fB, png_uint_32 \fIi\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIvalues\fP\fB, int \fIcolor_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_cHRM (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_filtered_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIfiltered_row\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_find_filter (png_structp \fP\fIpng_ptr\fP\fB, png_row_infop \fIrow_info\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_finish_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_gAMA (png_structp \fP\fIpng_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIint_file_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_uint_16p \fP\fIhist\fP\fB, int \fInum_hist\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, int \fIproflen\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_IDAT (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_IEND (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fP\fIfilter_type\fP\fB, int \fIinterlace_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_iTXt (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcompression\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fIlang\fP\fB, png_charp \fP\fItranslated_key\fP\fB, png_charp \fItext)\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIx_offset\fP\fB, png_uint_32 \fP\fIy_offset\fP\fB, int \fIunit_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIx_pixels_per_unit\fP\fB, png_uint_32 \fP\fIy_pixels_per_unit\fP\fB, int \fIunit_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, png_uint_32 \fInum_pal\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fP\fIsbit\fP\fB, int \fIcolor_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_sCAL_s (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, png_charp \fP\fIwidth\fP\fB, png_charp \fIheight\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_sig (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_sRGB (png_structp \fP\fIpng_ptr\fP\fB, int \fIintent\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_spalette_p \fIpalette\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_start_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fItext\fP\fB, png_size_t \fItext_len\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fItrans\fP\fB, png_color_16p \fP\fIvalues\fP\fB, int \fP\fInumber\fP\fB, int \fIcolor_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fItext\fP\fB, png_size_t \fP\fItext_len\fP\fB, int \fIcompression\fP\fB);\fP
+
+\fI\fB
+
+\fBvoidpf png_zalloc (voidpf \fP\fIpng_ptr\fP\fB, uInt \fP\fIitems\fP\fB, uInt \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_zfree (voidpf \fP\fIpng_ptr\fP\fB, voidpf \fIptr\fP\fB);\fP
+
+\fI\fB
+
+.SH DESCRIPTION
+The functions listed above are used privately by libpng
+and are not recommended for use by applications.  They are
+not "exported" to applications using shared libraries.  They
+are listed alphabetically here as an aid to libpng maintainers.
+See png.h for more information on these functions.
+
+.SH SEE ALSO
+libpng(3), png(5)
+.SH AUTHOR
+Glenn Randers-Pehrson
diff --git a/libraries/libpng-1.2.0/png.5 b/libraries/libpng-1.2.0/png.5
new file mode 100644 (file)
index 0000000..e2d44f0
--- /dev/null
@@ -0,0 +1,60 @@
+.TH PNG 5 "September 1, 2001"
+.SH NAME
+png \- Portable Network Graphics (PNG) format
+.SH DESCRIPTION
+PNG (Portable Network Graphics) is an extensible file format for the
+lossless, portable, well-compressed storage of raster images. PNG provides
+a patent-free replacement for GIF and can also replace many
+common uses of TIFF. Indexed-color, grayscale, and truecolor images are
+supported, plus an optional alpha channel. Sample depths range from
+1 to 16 bits.
+.br
+
+PNG is designed to work well in online viewing applications, such as the
+World Wide Web, so it is fully streamable with a progressive display
+option. PNG is robust, providing both full file integrity checking and
+fast, simple detection of common transmission errors. Also, PNG can store
+gamma and chromaticity data for improved color matching on heterogeneous
+platforms.
+
+.SH "SEE ALSO"
+.IR libpng(3), zlib(3), deflate(5), and zlib(5)
+.LP
+PNG 1.2 specification, July 1999:
+.IP
+.br
+http://www.libpng.org/pub/png
+.br
+or ftp://ftp.uu.net/graphics/png/documents
+.LP
+PNG 1.0 specification, October 1996:
+.IP
+.br
+RFC 2083
+.IP
+.br
+ftp://ds.internic.net/rfc/rfc2083.txt
+.br
+or (as a W3C Recommendation) at
+.br
+http://www.w3.org/TR/REC-png.html
+.SH AUTHORS
+This man page: Glenn Randers-Pehrson
+.LP
+Portable Network Graphics (PNG) Specification Version 1.2 (July 8, 1999):
+Glenn Randers-Pehrson and others (png-list@ccrc.wustl.edu).
+.LP
+Portable Network Graphics (PNG) Specification Version 1.0 (October 1, 1996):
+Thomas Boutell and others (png-list@ccrc.wustl.edu).
+.LP
+
+
+.SH COPYRIGHT NOTICE
+The PNG-1.2 specification is copyright (c) 1999 Glenn Randers-Pehrson.
+See the specification for conditions of use and distribution.
+.LP
+The PNG-1.0 specification is copyright (c) 1996 Massachussets Institute of
+Technology.  See the specification for conditions of use and distribution.
+.LP
+.\" end of man page
+
diff --git a/libraries/libpng-1.2.0/png.c b/libraries/libpng-1.2.0/png.c
new file mode 100644 (file)
index 0000000..8b56fee
--- /dev/null
@@ -0,0 +1,778 @@
+
+/* png.c - location for general purpose libpng functions
+ *
+ * libpng version 1.2.0 - September 1, 2001
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_EXTERN
+#include "png.h"
+
+/* Generate a compiler error if there is an old png.h in the search path. */
+typedef version_1_2_0 Your_png_h_is_not_version_1_2_0;
+
+/* Version information for C files.  This had better match the version
+ * string defined in png.h.  */
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+/* png_libpng_ver was changed to a function in version 1.0.5c */
+const char png_libpng_ver[18] = "1.2.0";
+
+/* png_sig was changed to a function in version 1.0.5c */
+/* Place to hold the signature string for a PNG file. */
+const png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+
+/* Invoke global declarations for constant strings for known chunk types */
+PNG_IHDR;
+PNG_IDAT;
+PNG_IEND;
+PNG_PLTE;
+PNG_bKGD;
+PNG_cHRM;
+PNG_gAMA;
+PNG_hIST;
+PNG_iCCP;
+PNG_iTXt;
+PNG_oFFs;
+PNG_pCAL;
+PNG_sCAL;
+PNG_pHYs;
+PNG_sBIT;
+PNG_sPLT;
+PNG_sRGB;
+PNG_tEXt;
+PNG_tIME;
+PNG_tRNS;
+PNG_zTXt;
+
+/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+/* start of interlace block */
+const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+
+/* offset to next interlace block */
+const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+
+/* start of interlace block in the y direction */
+const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+
+/* offset to next interlace block in the y direction */
+const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+
+/* width of interlace block (used in assembler routines only) */
+#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW
+const int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
+#endif
+
+/* Height of interlace block.  This is not currently used - if you need
+ * it, uncomment it here and in png.h
+const int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+*/
+
+/* Mask to determine which pixels are valid in a pass */
+const int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
+
+/* Mask to determine which pixels to overwrite while displaying */
+const int FARDATA png_pass_dsp_mask[]
+   = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
+
+#endif
+
+/* Tells libpng that we have already handled the first "num_bytes" bytes
+ * of the PNG file signature.  If the PNG data is embedded into another
+ * stream we can set num_bytes = 8 so that libpng will not attempt to read
+ * or write any of the magic bytes before it starts on the IHDR.
+ */
+
+void PNGAPI
+png_set_sig_bytes(png_structp png_ptr, int num_bytes)
+{
+   png_debug(1, "in png_set_sig_bytes\n");
+   if (num_bytes > 8)
+      png_error(png_ptr, "Too many bytes for PNG signature.");
+
+   png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes);
+}
+
+/* Checks whether the supplied bytes match the PNG signature.  We allow
+ * checking less than the full 8-byte signature so that those apps that
+ * already read the first few bytes of a file to determine the file type
+ * can simply check the remaining bytes for extra assurance.  Returns
+ * an integer less than, equal to, or greater than zero if sig is found,
+ * respectively, to be less than, to match, or be greater than the correct
+ * PNG signature (this is the same behaviour as strcmp, memcmp, etc).
+ */
+int PNGAPI
+png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check)
+{
+   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+   if (num_to_check > 8)
+      num_to_check = 8;
+   else if (num_to_check < 1)
+      return (0);
+
+   if (start > 7)
+      return (0);
+
+   if (start + num_to_check > 8)
+      num_to_check = 8 - start;
+
+   return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check)));
+}
+
+/* (Obsolete) function to check signature bytes.  It does not allow one
+ * to check a partial signature.  This function might be removed in the
+ * future - use png_sig_cmp().  Returns true (nonzero) if the file is a PNG.
+ */
+int PNGAPI
+png_check_sig(png_bytep sig, int num)
+{
+  return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num));
+}
+
+/* Function to allocate memory for zlib and clear it to 0. */
+voidpf /* PRIVATE */
+png_zalloc(voidpf png_ptr, uInt items, uInt size)
+{
+   png_uint_32 num_bytes = (png_uint_32)items * size;
+   png_voidp ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes);
+
+#ifndef PNG_NO_ZALLOC_ZERO
+   if (num_bytes > (png_uint_32)0x8000L)
+   {
+      png_memset(ptr, 0, (png_size_t)0x8000L);
+      png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0,
+         (png_size_t)(num_bytes - (png_uint_32)0x8000L));
+   }
+   else
+   {
+      png_memset(ptr, 0, (png_size_t)num_bytes);
+   }
+#endif
+   return ((voidpf)ptr);
+}
+
+/* function to free memory for zlib */
+void /* PRIVATE */
+png_zfree(voidpf png_ptr, voidpf ptr)
+{
+   png_free((png_structp)png_ptr, (png_voidp)ptr);
+}
+
+/* Reset the CRC variable to 32 bits of 1's.  Care must be taken
+ * in case CRC is > 32 bits to leave the top bits 0.
+ */
+void /* PRIVATE */
+png_reset_crc(png_structp png_ptr)
+{
+   png_ptr->crc = crc32(0, Z_NULL, 0);
+}
+
+/* Calculate the CRC over a section of data.  We can only pass as
+ * much data to this routine as the largest single buffer size.  We
+ * also check that this data will actually be used before going to the
+ * trouble of calculating it.
+ */
+void /* PRIVATE */
+png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length)
+{
+   int need_crc = 1;
+
+   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
+   {
+      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
+          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
+         need_crc = 0;
+   }
+   else                                                    /* critical */
+   {
+      if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+         need_crc = 0;
+   }
+
+   if (need_crc)
+      png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length);
+}
+
+/* Allocate the memory for an info_struct for the application.  We don't
+ * really need the png_ptr, but it could potentially be useful in the
+ * future.  This should be used in favour of malloc(sizeof(png_info))
+ * and png_info_init() so that applications that want to use a shared
+ * libpng don't have to be recompiled if png_info changes size.
+ */
+png_infop PNGAPI
+png_create_info_struct(png_structp png_ptr)
+{
+   png_infop info_ptr;
+
+   png_debug(1, "in png_create_info_struct\n");
+   if(png_ptr == NULL) return (NULL);
+#ifdef PNG_USER_MEM_SUPPORTED
+   if ((info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO,
+      png_ptr->malloc_fn, png_ptr->mem_ptr)) != NULL)
+#else
+   if ((info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO)) != NULL)
+#endif
+   {
+      png_info_init_3(&info_ptr, sizeof(png_info));
+   }
+
+   return (info_ptr);
+}
+
+/* This function frees the memory associated with a single info struct.
+ * Normally, one would use either png_destroy_read_struct() or
+ * png_destroy_write_struct() to free an info struct, but this may be
+ * useful for some applications.
+ */
+void PNGAPI
+png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
+{
+   png_infop info_ptr = NULL;
+
+   png_debug(1, "in png_destroy_info_struct\n");
+   if (info_ptr_ptr != NULL)
+      info_ptr = *info_ptr_ptr;
+
+   if (info_ptr != NULL)
+   {
+      png_info_destroy(png_ptr, info_ptr);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn,
+          png_ptr->mem_ptr);
+#else
+      png_destroy_struct((png_voidp)info_ptr);
+#endif
+      *info_ptr_ptr = (png_infop)NULL;
+   }
+}
+
+/* Initialize the info structure.  This is now an internal function (0.89)
+ * and applications using it are urged to use png_create_info_struct()
+ * instead.
+ */
+#undef png_info_init
+void PNGAPI
+png_info_init(png_infop info_ptr)
+{
+   /* We only come here via pre-1.0.12-compiled applications */
+   png_info_init_3(&info_ptr, 0);
+}
+
+void PNGAPI
+png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
+{
+   png_infop info_ptr = *ptr_ptr;
+
+   png_debug(1, "in png_info_init_3\n");
+
+   if(sizeof(png_info) > png_info_struct_size)
+     {
+       png_destroy_struct(info_ptr);
+       info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
+       *ptr_ptr = info_ptr;
+     }
+
+   /* set everything to 0 */
+   png_memset(info_ptr, 0, sizeof (png_info));
+}
+
+#ifdef PNG_FREE_ME_SUPPORTED
+void PNGAPI
+png_data_freer(png_structp png_ptr, png_infop info_ptr,
+   int freer, png_uint_32 mask)
+{
+   png_debug(1, "in png_data_freer\n");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+   if(freer == PNG_DESTROY_WILL_FREE_DATA)
+      info_ptr->free_me |= mask;
+   else if(freer == PNG_USER_WILL_FREE_DATA)
+      info_ptr->free_me &= ~mask;
+   else
+      png_warning(png_ptr,
+         "Unknown freer parameter in png_data_freer.");
+}
+#endif
+
+void PNGAPI
+png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
+   int num)
+{
+   png_debug(1, "in png_free_data\n");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+#if defined(PNG_TEXT_SUPPORTED)
+/* free text item num or (if num == -1) all text items */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_TEXT)
+#endif
+{
+   if (num != -1)
+   {
+     if (info_ptr->text && info_ptr->text[num].key)
+     {
+         png_free(png_ptr, info_ptr->text[num].key);
+         info_ptr->text[num].key = NULL;
+     }
+   }
+   else
+   {
+       int i;
+       for (i = 0; i < info_ptr->num_text; i++)
+           png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
+       png_free(png_ptr, info_ptr->text);
+       info_ptr->text = NULL;
+       info_ptr->num_text=0;
+   }
+}
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+/* free any tRNS entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
+#else
+if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS))
+#endif
+{
+    png_free(png_ptr, info_ptr->trans);
+    info_ptr->valid &= ~PNG_INFO_tRNS;
+    info_ptr->trans = NULL;
+}
+#endif
+
+#if defined(PNG_sCAL_SUPPORTED)
+/* free any sCAL entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_SCAL)
+#endif
+{
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+    png_free(png_ptr, info_ptr->scal_s_width);
+    png_free(png_ptr, info_ptr->scal_s_height);
+    info_ptr->scal_s_width = NULL;
+    info_ptr->scal_s_height = NULL;
+#endif
+    info_ptr->valid &= ~PNG_INFO_sCAL;
+}
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+/* free any pCAL entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_PCAL)
+#endif
+{
+    png_free(png_ptr, info_ptr->pcal_purpose);
+    png_free(png_ptr, info_ptr->pcal_units);
+    info_ptr->pcal_purpose = NULL;
+    info_ptr->pcal_units = NULL;
+    if (info_ptr->pcal_params != NULL)
+    {
+        int i;
+        for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
+        {
+          png_free(png_ptr, info_ptr->pcal_params[i]);
+          info_ptr->pcal_params[i]=NULL;
+        }
+        png_free(png_ptr, info_ptr->pcal_params);
+        info_ptr->pcal_params = NULL;
+    }
+    info_ptr->valid &= ~PNG_INFO_pCAL;
+}
+#endif
+
+#if defined(PNG_iCCP_SUPPORTED)
+/* free any iCCP entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_ICCP)
+#endif
+{
+    png_free(png_ptr, info_ptr->iccp_name);
+    png_free(png_ptr, info_ptr->iccp_profile);
+    info_ptr->iccp_name = NULL;
+    info_ptr->iccp_profile = NULL;
+    info_ptr->valid &= ~PNG_INFO_iCCP;
+}
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+/* free a given sPLT entry, or (if num == -1) all sPLT entries */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_SPLT)
+#endif
+{
+   if (num != -1)
+   {
+      if(info_ptr->splt_palettes)
+      {
+          png_free(png_ptr, info_ptr->splt_palettes[num].name);
+          png_free(png_ptr, info_ptr->splt_palettes[num].entries);
+          info_ptr->splt_palettes[num].name = NULL;
+          info_ptr->splt_palettes[num].entries = NULL;
+      }
+   }
+   else
+   {
+       if(info_ptr->splt_palettes_num)
+       {
+         int i;
+         for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
+            png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
+
+         png_free(png_ptr, info_ptr->splt_palettes);
+         info_ptr->splt_palettes = NULL;
+         info_ptr->splt_palettes_num = 0;
+       }
+       info_ptr->valid &= ~PNG_INFO_sPLT;
+   }
+}
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_UNKN)
+#endif
+{
+   if (num != -1)
+   {
+       if(info_ptr->unknown_chunks)
+       {
+          png_free(png_ptr, info_ptr->unknown_chunks[num].data);
+          info_ptr->unknown_chunks[num].data = NULL;
+       }
+   }
+   else
+   {
+       int i;
+
+       if(info_ptr->unknown_chunks_num)
+       {
+         for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++)
+            png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
+
+         png_free(png_ptr, info_ptr->unknown_chunks);
+         info_ptr->unknown_chunks = NULL;
+         info_ptr->unknown_chunks_num = 0;
+       }
+   }
+}
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+/* free any hIST entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_HIST)  & info_ptr->free_me)
+#else
+if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST))
+#endif
+{
+    png_free(png_ptr, info_ptr->hist);
+    info_ptr->hist = NULL;
+    info_ptr->valid &= ~PNG_INFO_hIST;
+}
+#endif
+
+/* free any PLTE entry that was internally allocated */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
+#else
+if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE))
+#endif
+{
+    png_zfree(png_ptr, info_ptr->palette);
+    info_ptr->palette = NULL;
+    info_ptr->valid &= ~PNG_INFO_PLTE;
+    info_ptr->num_palette = 0;
+}
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+/* free any image bits attached to the info structure */
+#ifdef PNG_FREE_ME_SUPPORTED
+if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
+#else
+if (mask & PNG_FREE_ROWS)
+#endif
+{
+    if(info_ptr->row_pointers)
+    {
+       int row;
+       for (row = 0; row < (int)info_ptr->height; row++)
+       {
+          png_free(png_ptr, info_ptr->row_pointers[row]);
+          info_ptr->row_pointers[row]=NULL;
+       }
+       png_free(png_ptr, info_ptr->row_pointers);
+       info_ptr->row_pointers=NULL;
+    }
+    info_ptr->valid &= ~PNG_INFO_IDAT;
+}
+#endif
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   if(num == -1)
+     info_ptr->free_me &= ~mask;
+   else
+     info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL);
+#endif
+}
+
+/* This is an internal routine to free any memory that the info struct is
+ * pointing to before re-using it or freeing the struct itself.  Recall
+ * that png_free() checks for NULL pointers for us.
+ */
+void /* PRIVATE */
+png_info_destroy(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_info_destroy\n");
+
+   png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+   if (png_ptr->num_chunk_list)
+   {
+       png_free(png_ptr, png_ptr->chunk_list);
+       png_ptr->chunk_list=(png_bytep)NULL;
+       png_ptr->num_chunk_list=0;
+   }
+#endif
+
+   png_info_init_3(&info_ptr, sizeof(png_info));
+}
+
+/* This function returns a pointer to the io_ptr associated with the user
+ * functions.  The application should free any memory associated with this
+ * pointer before png_write_destroy() or png_read_destroy() are called.
+ */
+png_voidp PNGAPI
+png_get_io_ptr(png_structp png_ptr)
+{
+   return (png_ptr->io_ptr);
+}
+
+#if !defined(PNG_NO_STDIO)
+/* Initialize the default input/output functions for the PNG file.  If you
+ * use your own read or write routines, you can call either png_set_read_fn()
+ * or png_set_write_fn() instead of png_init_io().  If you have defined
+ * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't
+ * necessarily available.
+ */
+void PNGAPI
+png_init_io(png_structp png_ptr, png_FILE_p fp)
+{
+   png_debug(1, "in png_init_io\n");
+   png_ptr->io_ptr = (png_voidp)fp;
+}
+#endif
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+/* Convert the supplied time into an RFC 1123 string suitable for use in
+ * a "Creation Time" or other text-based time string.
+ */
+png_charp PNGAPI
+png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
+{
+   static PNG_CONST char short_months[12][4] =
+        {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+   if (png_ptr->time_buffer == NULL)
+   {
+      png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29*
+         sizeof(char)));
+   }
+
+#if defined(_WIN32_WCE)
+   {
+      wchar_t time_buf[29];
+      wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"),
+          ptime->day % 32, short_months[(ptime->month - 1) % 12],
+        ptime->year, ptime->hour % 24, ptime->minute % 60,
+          ptime->second % 61);
+      WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29,
+          NULL, NULL);
+   }
+#else
+#ifdef USE_FAR_KEYWORD
+   {
+      char near_time_buf[29];
+      sprintf(near_time_buf, "%d %s %d %02d:%02d:%02d +0000",
+          ptime->day % 32, short_months[(ptime->month - 1) % 12],
+          ptime->year, ptime->hour % 24, ptime->minute % 60,
+          ptime->second % 61);
+      png_memcpy(png_ptr->time_buffer, near_time_buf,
+          29*sizeof(char));
+   }
+#else
+   sprintf(png_ptr->time_buffer, "%d %s %d %02d:%02d:%02d +0000",
+       ptime->day % 32, short_months[(ptime->month - 1) % 12],
+       ptime->year, ptime->hour % 24, ptime->minute % 60,
+       ptime->second % 61);
+#endif
+#endif /* _WIN32_WCE */
+   return ((png_charp)png_ptr->time_buffer);
+}
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+
+#if 0
+/* Signature string for a PNG file. */
+png_bytep PNGAPI
+png_sig_bytes(void)
+{
+   return ((png_bytep)"\211\120\116\107\015\012\032\012");
+}
+#endif
+
+png_charp PNGAPI
+png_get_copyright(png_structp png_ptr)
+{
+   if (png_ptr != NULL || png_ptr == NULL)  /* silence compiler warning */
+   return ((png_charp) "\n libpng version 1.2.0 - September 1, 2001\n\
+   Copyright (c) 1998-2001 Glenn Randers-Pehrson\n\
+   Copyright (c) 1996, 1997 Andreas Dilger\n\
+   Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.\n");
+   return ((png_charp) "");
+}
+
+/* The following return the library version as a short string in the
+ * format 1.0.0 through 99.99.99zz.  To get the version of *.h files used
+ * with your application, print out PNG_LIBPNG_VER_STRING, which is defined
+ * in png.h.
+ */
+
+png_charp PNGAPI
+png_get_libpng_ver(png_structp png_ptr)
+{
+   /* Version of *.c files used when building libpng */
+   if(png_ptr != NULL) /* silence compiler warning about unused png_ptr */
+      return((png_charp) "1.2.0");
+   return((png_charp) "1.2.0");
+}
+
+png_charp PNGAPI
+png_get_header_ver(png_structp png_ptr)
+{
+   /* Version of *.h files used when building libpng */
+   if(png_ptr != NULL) /* silence compiler warning about unused png_ptr */
+      return((png_charp) PNG_LIBPNG_VER_STRING);
+   return((png_charp) PNG_LIBPNG_VER_STRING);
+}
+
+png_charp PNGAPI
+png_get_header_version(png_structp png_ptr)
+{
+   /* Returns longer string containing both version and date */
+   if(png_ptr != NULL) /* silence compiler warning about unused png_ptr */
+      return((png_charp) PNG_HEADER_VERSION_STRING);
+   return((png_charp) PNG_HEADER_VERSION_STRING);
+}
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+int /* PRIVATE */
+png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name)
+{
+   /* check chunk_name and return "keep" value if it's on the list, else 0 */
+   int i;
+   png_bytep p;
+   if((png_ptr == NULL && chunk_name == NULL) || png_ptr->num_chunk_list<=0)
+      return 0;
+   p=png_ptr->chunk_list+png_ptr->num_chunk_list*5-5;
+   for (i = png_ptr->num_chunk_list; i; i--, p-=5)
+      if (!png_memcmp(chunk_name, p, 4))
+        return ((int)*(p+4));
+   return 0;
+}
+#endif
+
+/* This function, added to libpng-1.0.6g, is untested. */
+int PNGAPI
+png_reset_zstream(png_structp png_ptr)
+{
+   return (inflateReset(&png_ptr->zstream));
+}
+
+/* This function was added to libpng-1.0.7 */
+png_uint_32 PNGAPI
+png_access_version_number(void)
+{
+   /* Version of *.c files used when building libpng */
+   return((png_uint_32) 10200L);
+}
+
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+    /* GRR:  could add this:   && defined(PNG_MMX_CODE_SUPPORTED) */
+/* this INTERNAL function was added to libpng 1.2.0 */
+void /* PRIVATE */
+png_init_mmx_flags (png_structp png_ptr)
+{
+    png_ptr->mmx_rowbytes_threshold = 0;
+    png_ptr->mmx_bitdepth_threshold = 0;
+
+#  if (defined(PNG_USE_PNGVCRD) || defined(PNG_USE_PNGGCCRD))
+
+    png_ptr->asm_flags |= PNG_ASM_FLAG_MMX_SUPPORT_COMPILED;
+
+    if (png_mmx_support()) {
+        png_ptr->asm_flags |= PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU
+#    ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW
+                              | PNG_ASM_FLAG_MMX_READ_COMBINE_ROW
+#    endif
+#    ifdef PNG_HAVE_ASSEMBLER_READ_INTERLACE
+                              | PNG_ASM_FLAG_MMX_READ_INTERLACE
+#    endif
+#    ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
+                              ;
+#    else
+                              | PNG_ASM_FLAG_MMX_READ_FILTER_SUB
+                              | PNG_ASM_FLAG_MMX_READ_FILTER_UP
+                              | PNG_ASM_FLAG_MMX_READ_FILTER_AVG
+                              | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ;
+
+        png_ptr->mmx_rowbytes_threshold = PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT;
+        png_ptr->mmx_bitdepth_threshold = PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT;
+#    endif
+    } else {
+        png_ptr->asm_flags &= ~( PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU
+                               | PNG_MMX_READ_FLAGS
+                               | PNG_MMX_WRITE_FLAGS );
+    }
+
+#  else /* !((PNGVCRD || PNGGCCRD) && PNG_ASSEMBLER_CODE_SUPPORTED)) */
+
+    /* clear all MMX flags; no support is compiled in */
+    png_ptr->asm_flags &= ~( PNG_MMX_FLAGS );
+
+#  endif /* ?(PNGVCRD || PNGGCCRD) */
+}
+
+#endif /* !(PNG_ASSEMBLER_CODE_SUPPORTED) */
+
+/* this function was added to libpng 1.2.0 */
+#if !defined(PNG_USE_PNGGCCRD) && \
+    !(defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD))
+int PNGAPI
+png_mmx_support(void)
+{
+    return -1;
+}
+#endif
diff --git a/libraries/libpng-1.2.0/png.h b/libraries/libpng-1.2.0/png.h
new file mode 100644 (file)
index 0000000..f9d4cbd
--- /dev/null
@@ -0,0 +1,3156 @@
+
+/* png.h - header file for PNG reference library
+ *
+ * libpng version 1.2.0 - September 1, 2001
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * Authors and maintainers:
+ *  libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
+ *  libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
+ *  libpng versions 0.97, January 1998, through 1.2.0 - September 1, 2001: Glenn
+ *  See also "Contributing Authors", below.
+ *
+ * Note about libpng version numbers:
+ *
+ *    Due to various miscommunications, unforeseen code incompatibilities
+ *    and occasional factors outside the authors' control, version numbering
+ *    on the library has not always been consistent and straightforward.
+ *    The following table summarizes matters since version 0.89c, which was
+ *    the first widely used release:
+ *
+ *    source                 png.h  png.h  shared-lib
+ *    version                string   int  version
+ *    -------                ------ -----  ----------
+ *    0.89c "1.0 beta 3"     0.89      89  1.0.89
+ *    0.90  "1.0 beta 4"     0.90      90  0.90  [should have been 2.0.90]
+ *    0.95  "1.0 beta 5"     0.95      95  0.95  [should have been 2.0.95]
+ *    0.96  "1.0 beta 6"     0.96      96  0.96  [should have been 2.0.96]
+ *    0.97b "1.00.97 beta 7" 1.00.97   97  1.0.1 [should have been 2.0.97]
+ *    0.97c                  0.97      97  2.0.97
+ *    0.98                   0.98      98  2.0.98
+ *    0.99                   0.99      98  2.0.99
+ *    0.99a-m                0.99      99  2.0.99
+ *    1.00                   1.00     100  2.1.0 [100 should be 10000]
+ *    1.0.0      (from here on, the   100  2.1.0 [100 should be 10000]
+ *    1.0.1       png.h string is   10001  2.1.0
+ *    1.0.1a-e    identical to the  10002  from here on, the shared library
+ *    1.0.2       source version)   10002  is 2.V where V is the source code
+ *    1.0.2a-b                      10003  version, except as noted.
+ *    1.0.3                         10003
+ *    1.0.3a-d                      10004
+ *    1.0.4                         10004
+ *    1.0.4a-f                      10005
+ *    1.0.5 (+ 2 patches)           10005
+ *    1.0.5a-d                      10006
+ *    1.0.5e-r                      10100 (not source compatible)
+ *    1.0.5s-v                      10006 (not binary compatible)
+ *    1.0.6 (+ 3 patches)           10006 (still binary incompatible)
+ *    1.0.6d-f                      10007 (still binary incompatible)
+ *    1.0.6g                        10007
+ *    1.0.6h                        10007  10.6h (testing xy.z so-numbering)
+ *    1.0.6i                        10007  10.6i
+ *    1.0.6j                        10007  2.1.0.6j (incompatible with 1.0.0)
+ *    1.0.7beta11-14        DLLNUM  10007  2.1.0.7beta11-14 (binary compatible)
+ *    1.0.7beta15-18           1    10007  2.1.0.7beta15-18 (binary compatible)
+ *    1.0.7rc1-2               1    10007  2.1.0.7rc1-2 (binary compatible)
+ *    1.0.7                    1    10007  (still compatible)
+ *    1.0.8beta1-4             1    10008  2.1.0.8beta1-4
+ *    1.0.8rc1                 1    10008  2.1.0.8rc1
+ *    1.0.8                    1    10008  2.1.0.8
+ *    1.0.9beta1-6             1    10009  2.1.0.9beta1-6
+ *    1.0.9rc1                 1    10009  2.1.0.9rc1
+ *    1.0.9beta7-10            1    10009  2.1.0.9beta7-10
+ *    1.0.9rc2                 1    10009  2.1.0.9rc2
+ *    1.0.9                    1    10009  2.1.0.9
+ *    1.0.10beta1              1    10010  2.1.0.10beta1
+ *    1.0.10rc1                1    10010  2.1.0.10rc1
+ *    1.0.10                   1    10010  2.1.0.10
+ *    1.0.11beta1-3            1    10011  2.1.0.11beta1-3
+ *    1.0.11rc1                1    10011  2.1.0.11rc1
+ *    1.0.11                   1    10011  2.1.0.11
+ *    1.0.12beta1-2            2    10012  2.1.0.12beta1-2
+ *    1.0.12rc1                2    10012  2.1.0.12rc1
+ *    1.0.12                   2    10012  2.1.0.12
+ *    1.1.0a-f                 -    10100  2.1.1.0a-f (branch abandoned)
+ *    1.2.0beta1-2             2    10200  2.1.2.0beta1-2
+ *    1.2.0beta3-4             3    10200  3.1.2.0beta3-4
+ *
+ *    Henceforth the source version will match the shared-library major
+ *    and minor numbers; the shared-library major version number will be
+ *    used for changes in backward compatibility, as it is intended.  The
+ *    PNG_LIBPNG_VER macro, which is not used within libpng but is available
+ *    for applications, is an unsigned integer of the form xyyzz corresponding
+ *    to the source version x.y.z (leading zeros in y and z).  Beta versions
+ *    were given the previous public release number plus a letter, until
+ *    version 1.0.6j; from then on they were given the upcoming public
+ *    release number plus "betaNN" or "rcN".
+ *
+ *    Binary incompatibility exists only when applications make direct access
+ *    to the info_ptr or png_ptr members through png.h, and the compiled
+ *    application is loaded with a different version of the library.
+ *
+ *    DLLNUM will change each time there are forward or backward changes
+ *    in binary compatibility (e.g., when a new feature is added).
+ *
+ * See libpng.txt or libpng.3 for more information.  The PNG specification
+ * is available as RFC 2083 <ftp://ftp.uu.net/graphics/png/documents/>
+ * and as a W3C Recommendation <http://www.w3.org/TR/REC.png.html>
+ */
+
+/*
+ * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+ *
+ * If you modify libpng you may insert additional notices immediately following
+ * this sentence.
+ *
+ * libpng versions 1.0.7, July 1, 2000, through  1.2.0, September 1, 2001, are
+ * Copyright (c) 2000, 2001 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-1.0.6
+ * with the following individuals added to the list of Contributing Authors
+ *
+ *    Simon-Pierre Cadieux
+ *    Eric S. Raymond
+ *    Gilles Vollant
+ *
+ * and with the following additions to the disclaimer:
+ *
+ *    There is no warranty against interference with your enjoyment of the
+ *    library or against infringement.  There is no warranty that our
+ *    efforts or the library will fulfill any of your particular purposes
+ *    or needs.  This library is provided with all faults, and the entire
+ *    risk of satisfactory quality, performance, accuracy, and effort is with
+ *    the user.
+ *
+ * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
+ * Distributed according to the same disclaimer and license as libpng-0.96,
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ *    Tom Lane
+ *    Glenn Randers-Pehrson
+ *    Willem van Schaik
+ *
+ * libpng versions 0.89, June 1996, through 0.96, May 1997, are
+ * Copyright (c) 1996, 1997 Andreas Dilger
+ * Distributed according to the same disclaimer and license as libpng-0.88,
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ *    John Bowler
+ *    Kevin Bracey
+ *    Sam Bushell
+ *    Magnus Holmgren
+ *    Greg Roelofs
+ *    Tom Tanner
+ *
+ * libpng versions 0.5, May 1995, through 0.88, January 1996, are
+ * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+ *
+ * For the purposes of this copyright and license, "Contributing Authors"
+ * is defined as the following set of individuals:
+ *
+ *    Andreas Dilger
+ *    Dave Martindale
+ *    Guy Eric Schalnat
+ *    Paul Schmidt
+ *    Tim Wegner
+ *
+ * The PNG Reference Library is supplied "AS IS".  The Contributing Authors
+ * and Group 42, Inc. disclaim all warranties, expressed or implied,
+ * including, without limitation, the warranties of merchantability and of
+ * fitness for any purpose.  The Contributing Authors and Group 42, Inc.
+ * assume no liability for direct, indirect, incidental, special, exemplary,
+ * or consequential damages, which may result from the use of the PNG
+ * Reference Library, even if advised of the possibility of such damage.
+ *
+ * Permission is hereby granted to use, copy, modify, and distribute this
+ * source code, or portions hereof, for any purpose, without fee, subject
+ * to the following restrictions:
+ *
+ * 1. The origin of this source code must not be misrepresented.
+ *
+ * 2. Altered versions must be plainly marked as such and
+ * must not be misrepresented as being the original source.
+ *
+ * 3. This Copyright notice may not be removed or altered from
+ *    any source or altered source distribution.
+ *
+ * The Contributing Authors and Group 42, Inc. specifically permit, without
+ * fee, and encourage the use of this source code as a component to
+ * supporting the PNG file format in commercial products.  If you use this
+ * source code in a product, acknowledgment is not required but would be
+ * appreciated.
+ */
+
+/*
+ * A "png_get_copyright" function is available, for convenient use in "about"
+ * boxes and the like:
+ *
+ * printf("%s",png_get_copyright(NULL));
+ *
+ * Also, the PNG logo (in PNG format, of course) is supplied in the
+ * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+ */
+
+/*
+ * Libpng is OSI Certified Open Source Software.  OSI Certified is a
+ * certification mark of the Open Source Initiative.
+ */
+
+/*
+ * The contributing authors would like to thank all those who helped
+ * with testing, bug fixes, and patience.  This wouldn't have been
+ * possible without all of you.
+ *
+ * Thanks to Frank J. T. Wojcik for helping with the documentation.
+ */
+
+/*
+ * Y2K compliance in libpng:
+ * =========================
+ *
+ *    September 1, 2001
+ *
+ *    Since the PNG Development group is an ad-hoc body, we can't make
+ *    an official declaration.
+ *
+ *    This is your unofficial assurance that libpng from version 0.71 and
+ *    upward through 1.2.0 are Y2K compliant.  It is my belief that earlier
+ *    versions were also Y2K compliant.
+ *
+ *    Libpng only has three year fields.  One is a 2-byte unsigned integer
+ *    that will hold years up to 65535.  The other two hold the date in text
+ *    format, and will hold years up to 9999.
+ *
+ *    The integer is
+ *        "png_uint_16 year" in png_time_struct.
+ *
+ *    The strings are
+ *        "png_charp time_buffer" in png_struct and
+ *        "near_time_buffer", which is a local character string in png.c.
+ *
+ *    There are seven time-related functions:
+ *        png.c: png_convert_to_rfc_1123() in png.c
+ *          (formerly png_convert_to_rfc_1152() in error)
+ *        png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
+ *        png_convert_from_time_t() in pngwrite.c
+ *        png_get_tIME() in pngget.c
+ *        png_handle_tIME() in pngrutil.c, called in pngread.c
+ *        png_set_tIME() in pngset.c
+ *        png_write_tIME() in pngwutil.c, called in pngwrite.c
+ *
+ *    All handle dates properly in a Y2K environment.  The
+ *    png_convert_from_time_t() function calls gmtime() to convert from system
+ *    clock time, which returns (year - 1900), which we properly convert to
+ *    the full 4-digit year.  There is a possibility that applications using
+ *    libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+ *    function, or that they are incorrectly passing only a 2-digit year
+ *    instead of "year - 1900" into the png_convert_from_struct_tm() function,
+ *    but this is not under our control.  The libpng documentation has always
+ *    stated that it works with 4-digit years, and the APIs have been
+ *    documented as such.
+ *
+ *    The tIME chunk itself is also Y2K compliant.  It uses a 2-byte unsigned
+ *    integer to hold the year, and can hold years as large as 65535.
+ *
+ *    zlib, upon which libpng depends, is also Y2K compliant.  It contains
+ *    no date-related code.
+ *
+ *       Glenn Randers-Pehrson
+ *       libpng maintainer
+ *       PNG Development Group
+ */
+
+#ifndef PNG_H
+#define PNG_H
+
+/* This is not the place to learn how to use libpng.  The file libpng.txt
+ * describes how to use libpng, and the file example.c summarizes it
+ * with some code on which to build.  This file is useful for looking
+ * at the actual function definitions and structure components.
+ */
+
+/* Version information for png.h - this should match the version in png.c */
+#define PNG_LIBPNG_VER_STRING "1.2.0"
+
+#define PNG_LIBPNG_VER_SONUM   3
+#define PNG_LIBPNG_VER_DLLNUM  %DLLNUM%
+
+/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
+#define PNG_LIBPNG_VER_MAJOR   1
+#define PNG_LIBPNG_VER_MINOR   2
+#define PNG_LIBPNG_VER_RELEASE 0
+/* This should match the numeric part of the final component of
+ * PNG_LIBPNG_VER_STRING, omitting any leading zero: */
+
+#define PNG_LIBPNG_VER_BUILD  0
+
+#define PNG_LIBPNG_BUILD_ALPHA    1
+#define PNG_LIBPNG_BUILD_BETA     2
+#define PNG_LIBPNG_BUILD_RC       3
+#define PNG_LIBPNG_BUILD_STABLE   4
+#define PNG_LIBPNG_BUILD_TYPEMASK 7
+#define PNG_LIBPNG_BUILD_PATCH    8 /* Can be OR'ed with STABLE only */
+#define PNG_LIBPNG_BUILD_TYPE 4
+
+/* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
+ * We must not include leading zeros.
+ * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
+ * version 1.0.0 was mis-numbered 100 instead of 10000).  From
+ * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release */
+#define PNG_LIBPNG_VER 10200 /* 1.2.0 */
+
+#ifndef PNG_VERSION_INFO_ONLY
+
+/* include the compression library's header */
+#include "zlib.h"
+
+/* include all user configurable info, including optional assembler routines */
+#include "pngconf.h"
+
+/* Inhibit C++ name-mangling for libpng functions but not for system calls. */
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* This file is arranged in several sections.  The first section contains
+ * structure and type definitions.  The second section contains the external
+ * library functions, while the third has the internal library functions,
+ * which applications aren't expected to use directly.
+ */
+
+/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */
+#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN)
+/* Version information for C files, stored in png.c.  This had better match
+ * the version above.
+ */
+#ifdef PNG_USE_GLOBAL_ARRAYS
+PNG_EXPORT_VAR (const char) png_libpng_ver[18];
+  /* need room for 99.99.99beta99z*/
+#else
+#define png_libpng_ver png_get_header_ver(NULL)
+#endif
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+/* This was removed in version 1.0.5c */
+/* Structures to facilitate easy interlacing.  See png.c for more details */
+PNG_EXPORT_VAR (const int FARDATA) png_pass_start[7];
+PNG_EXPORT_VAR (const int FARDATA) png_pass_inc[7];
+PNG_EXPORT_VAR (const int FARDATA) png_pass_ystart[7];
+PNG_EXPORT_VAR (const int FARDATA) png_pass_yinc[7];
+PNG_EXPORT_VAR (const int FARDATA) png_pass_mask[7];
+PNG_EXPORT_VAR (const int FARDATA) png_pass_dsp_mask[7];
+#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW
+PNG_EXPORT_VAR (const int FARDATA) png_pass_width[7];
+#endif
+/* This isn't currently used.  If you need it, see png.c for more details.
+PNG_EXPORT_VAR (const int FARDATA) png_pass_height[7];
+*/
+#endif
+
+#endif /* PNG_NO_EXTERN */
+
+/* Three color definitions.  The order of the red, green, and blue, (and the
+ * exact size) is not important, although the size of the fields need to
+ * be png_byte or png_uint_16 (as defined below).
+ */
+typedef struct png_color_struct
+{
+   png_byte red;
+   png_byte green;
+   png_byte blue;
+} png_color;
+typedef png_color FAR * png_colorp;
+typedef png_color FAR * FAR * png_colorpp;
+
+typedef struct png_color_16_struct
+{
+   png_byte index;    /* used for palette files */
+   png_uint_16 red;   /* for use in red green blue files */
+   png_uint_16 green;
+   png_uint_16 blue;
+   png_uint_16 gray;  /* for use in grayscale files */
+} png_color_16;
+typedef png_color_16 FAR * png_color_16p;
+typedef png_color_16 FAR * FAR * png_color_16pp;
+
+typedef struct png_color_8_struct
+{
+   png_byte red;   /* for use in red green blue files */
+   png_byte green;
+   png_byte blue;
+   png_byte gray;  /* for use in grayscale files */
+   png_byte alpha; /* for alpha channel files */
+} png_color_8;
+typedef png_color_8 FAR * png_color_8p;
+typedef png_color_8 FAR * FAR * png_color_8pp;
+
+/*
+ * The following two structures are used for the in-core representation
+ * of sPLT chunks.
+ */
+typedef struct png_sPLT_entry_struct
+{
+   png_uint_16 red;
+   png_uint_16 green;
+   png_uint_16 blue;
+   png_uint_16 alpha;
+   png_uint_16 frequency;
+} png_sPLT_entry;
+typedef png_sPLT_entry FAR * png_sPLT_entryp;
+typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp;
+
+/*  When the depth of the sPLT palette is 8 bits, the color and alpha samples
+ *  occupy the LSB of their respective members, and the MSB of each member
+ *  is zero-filled.  The frequency member always occupies the full 16 bits.
+ */
+
+typedef struct png_sPLT_struct
+{
+   png_charp name;           /* palette name */
+   png_byte depth;           /* depth of palette samples */
+   png_sPLT_entryp entries;  /* palette entries */
+   png_int_32 nentries;      /* number of palette entries */
+} png_sPLT_t;
+typedef png_sPLT_t FAR * png_sPLT_tp;
+typedef png_sPLT_t FAR * FAR * png_sPLT_tpp;
+
+#ifdef PNG_TEXT_SUPPORTED
+/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file,
+ * and whether that contents is compressed or not.  The "key" field
+ * points to a regular zero-terminated C string.  The "text", "lang", and
+ * "lang_key" fields can be regular C strings, empty strings, or NULL pointers.
+ * However, the * structure returned by png_get_text() will always contain
+ * regular zero-terminated C strings (possibly empty), never NULL pointers,
+ * so they can be safely used in printf() and other string-handling functions.
+ */
+typedef struct png_text_struct
+{
+   int  compression;       /* compression value:
+                             -1: tEXt, none
+                              0: zTXt, deflate
+                              1: iTXt, none
+                              2: iTXt, deflate  */
+   png_charp key;          /* keyword, 1-79 character description of "text" */
+   png_charp text;         /* comment, may be an empty string (ie "")
+                              or a NULL pointer */
+   png_size_t text_length; /* length of the text string */
+#ifdef PNG_iTXt_SUPPORTED
+   png_size_t itxt_length; /* length of the itxt string */
+   png_charp lang;         /* language code, 0-79 characters
+                              or a NULL pointer */
+   png_charp lang_key;     /* keyword translated UTF-8 string, 0 or more
+                              chars or a NULL pointer */
+#endif
+} png_text;
+typedef png_text FAR * png_textp;
+typedef png_text FAR * FAR * png_textpp;
+#endif
+
+/* Supported compression types for text in PNG files (tEXt, and zTXt).
+ * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */
+#define PNG_TEXT_COMPRESSION_NONE_WR -3
+#define PNG_TEXT_COMPRESSION_zTXt_WR -2
+#define PNG_TEXT_COMPRESSION_NONE    -1
+#define PNG_TEXT_COMPRESSION_zTXt     0
+#define PNG_ITXT_COMPRESSION_NONE     1
+#define PNG_ITXT_COMPRESSION_zTXt     2
+#define PNG_TEXT_COMPRESSION_LAST     3  /* Not a valid value */
+
+/* png_time is a way to hold the time in an machine independent way.
+ * Two conversions are provided, both from time_t and struct tm.  There
+ * is no portable way to convert to either of these structures, as far
+ * as I know.  If you know of a portable way, send it to me.  As a side
+ * note - PNG has always been Year 2000 compliant!
+ */
+typedef struct png_time_struct
+{
+   png_uint_16 year; /* full year, as in, 1995 */
+   png_byte month;   /* month of year, 1 - 12 */
+   png_byte day;     /* day of month, 1 - 31 */
+   png_byte hour;    /* hour of day, 0 - 23 */
+   png_byte minute;  /* minute of hour, 0 - 59 */
+   png_byte second;  /* second of minute, 0 - 60 (for leap seconds) */
+} png_time;
+typedef png_time FAR * png_timep;
+typedef png_time FAR * FAR * png_timepp;
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+/* png_unknown_chunk is a structure to hold queued chunks for which there is
+ * no specific support.  The idea is that we can use this to queue
+ * up private chunks for output even though the library doesn't actually
+ * know about their semantics.
+ */
+typedef struct png_unknown_chunk_t
+{
+    png_byte name[5];
+    png_byte *data;
+    png_size_t size;
+
+    /* libpng-using applications should NOT directly modify this byte. */
+    png_byte location; /* mode of operation at read time */
+}
+png_unknown_chunk;
+typedef png_unknown_chunk FAR * png_unknown_chunkp;
+typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp;
+#endif
+
+/* png_info is a structure that holds the information in a PNG file so
+ * that the application can find out the characteristics of the image.
+ * If you are reading the file, this structure will tell you what is
+ * in the PNG file.  If you are writing the file, fill in the information
+ * you want to put into the PNG file, then call png_write_info().
+ * The names chosen should be very close to the PNG specification, so
+ * consult that document for information about the meaning of each field.
+ *
+ * With libpng < 0.95, it was only possible to directly set and read the
+ * the values in the png_info_struct, which meant that the contents and
+ * order of the values had to remain fixed.  With libpng 0.95 and later,
+ * however, there are now functions that abstract the contents of
+ * png_info_struct from the application, so this makes it easier to use
+ * libpng with dynamic libraries, and even makes it possible to use
+ * libraries that don't have all of the libpng ancillary chunk-handing
+ * functionality.
+ *
+ * In any case, the order of the parameters in png_info_struct should NOT
+ * be changed for as long as possible to keep compatibility with applications
+ * that use the old direct-access method with png_info_struct.
+ *
+ * The following members may have allocated storage attached that should be
+ * cleaned up before the structure is discarded: palette, trans, text,
+ * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
+ * splt_palettes, scal_unit, row_pointers, and unknowns.   By default, these
+ * are automatically freed when the info structure is deallocated, if they were
+ * allocated internally by libpng.  This behavior can be changed by means
+ * of the png_data_freer() function.
+ *
+ * More allocation details: all the chunk-reading functions that
+ * change these members go through the corresponding png_set_*
+ * functions.  A function to clear these members is available: see
+ * png_free_data().  The png_set_* functions do not depend on being
+ * able to point info structure members to any of the storage they are
+ * passed (they make their own copies), EXCEPT that the png_set_text
+ * functions use the same storage passed to them in the text_ptr or
+ * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
+ * functions do not make their own copies.
+ */
+typedef struct png_info_struct
+{
+   /* the following are necessary for every PNG file */
+   png_uint_32 width;       /* width of image in pixels (from IHDR) */
+   png_uint_32 height;      /* height of image in pixels (from IHDR) */
+   png_uint_32 valid;       /* valid chunk data (see PNG_INFO_ below) */
+   png_uint_32 rowbytes;    /* bytes needed to hold an untransformed row */
+   png_colorp palette;      /* array of color values (valid & PNG_INFO_PLTE) */
+   png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */
+   png_uint_16 num_trans;   /* number of transparent palette color (tRNS) */
+   png_byte bit_depth;      /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */
+   png_byte color_type;     /* see PNG_COLOR_TYPE_ below (from IHDR) */
+   /* The following three should have been named *_method not *_type */
+   png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */
+   png_byte filter_type;    /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
+   png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
+
+   /* The following is informational only on read, and not used on writes. */
+   png_byte channels;       /* number of data channels per pixel (1, 2, 3, 4)*/
+   png_byte pixel_depth;    /* number of bits per pixel */
+   png_byte spare_byte;     /* to align the data, and for future use */
+   png_byte signature[8];   /* magic bytes read by libpng from start of file */
+
+   /* The rest of the data is optional.  If you are reading, check the
+    * valid field to see if the information in these are valid.  If you
+    * are writing, set the valid field to those chunks you want written,
+    * and initialize the appropriate fields below.
+    */
+
+#if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+   /* The gAMA chunk describes the gamma characteristics of the system
+    * on which the image was created, normally in the range [1.0, 2.5].
+    * Data is valid if (valid & PNG_INFO_gAMA) is non-zero.
+    */
+   float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */
+#endif
+
+#if defined(PNG_sRGB_SUPPORTED)
+    /* GR-P, 0.96a */
+    /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */
+   png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */
+#endif
+
+#if defined(PNG_TEXT_SUPPORTED)
+   /* The tEXt, and zTXt chunks contain human-readable textual data in
+    * uncompressed, compressed, and optionally compressed forms, respectively.
+    * The data in "text" is an array of pointers to uncompressed,
+    * null-terminated C strings. Each chunk has a keyword that describes the
+    * textual data contained in that chunk.  Keywords are not required to be
+    * unique, and the text string may be empty.  Any number of text chunks may
+    * be in an image.
+    */
+   int num_text; /* number of comments read/to write */
+   int max_text; /* current size of text array */
+   png_textp text; /* array of comments read/to write */
+#endif /* PNG_TEXT_SUPPORTED */
+
+#if defined(PNG_tIME_SUPPORTED)
+   /* The tIME chunk holds the last time the displayed image data was
+    * modified.  See the png_time struct for the contents of this struct.
+    */
+   png_time mod_time;
+#endif
+
+#if defined(PNG_sBIT_SUPPORTED)
+   /* The sBIT chunk specifies the number of significant high-order bits
+    * in the pixel data.  Values are in the range [1, bit_depth], and are
+    * only specified for the channels in the pixel data.  The contents of
+    * the low-order bits is not specified.  Data is valid if
+    * (valid & PNG_INFO_sBIT) is non-zero.
+    */
+   png_color_8 sig_bit; /* significant bits in color channels */
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \
+defined(PNG_READ_BACKGROUND_SUPPORTED)
+   /* The tRNS chunk supplies transparency data for paletted images and
+    * other image types that don't need a full alpha channel.  There are
+    * "num_trans" transparency values for a paletted image, stored in the
+    * same order as the palette colors, starting from index 0.  Values
+    * for the data are in the range [0, 255], ranging from fully transparent
+    * to fully opaque, respectively.  For non-paletted images, there is a
+    * single color specified that should be treated as fully transparent.
+    * Data is valid if (valid & PNG_INFO_tRNS) is non-zero.
+    */
+   png_bytep trans; /* transparent values for paletted image */
+   png_color_16 trans_values; /* transparent color for non-palette image */
+#endif
+
+#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+   /* The bKGD chunk gives the suggested image background color if the
+    * display program does not have its own background color and the image
+    * is needs to composited onto a background before display.  The colors
+    * in "background" are normally in the same color space/depth as the
+    * pixel data.  Data is valid if (valid & PNG_INFO_bKGD) is non-zero.
+    */
+   png_color_16 background;
+#endif
+
+#if defined(PNG_oFFs_SUPPORTED)
+   /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards
+    * and downwards from the top-left corner of the display, page, or other
+    * application-specific co-ordinate space.  See the PNG_OFFSET_ defines
+    * below for the unit types.  Valid if (valid & PNG_INFO_oFFs) non-zero.
+    */
+   png_int_32 x_offset; /* x offset on page */
+   png_int_32 y_offset; /* y offset on page */
+   png_byte offset_unit_type; /* offset units type */
+#endif
+
+#if defined(PNG_pHYs_SUPPORTED)
+   /* The pHYs chunk gives the physical pixel density of the image for
+    * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_
+    * defines below).  Data is valid if (valid & PNG_INFO_pHYs) is non-zero.
+    */
+   png_uint_32 x_pixels_per_unit; /* horizontal pixel density */
+   png_uint_32 y_pixels_per_unit; /* vertical pixel density */
+   png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+   /* The hIST chunk contains the relative frequency or importance of the
+    * various palette entries, so that a viewer can intelligently select a
+    * reduced-color palette, if required.  Data is an array of "num_palette"
+    * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST)
+    * is non-zero.
+    */
+   png_uint_16p hist;
+#endif
+
+#ifdef PNG_cHRM_SUPPORTED
+   /* The cHRM chunk describes the CIE color characteristics of the monitor
+    * on which the PNG was created.  This data allows the viewer to do gamut
+    * mapping of the input image to ensure that the viewer sees the same
+    * colors in the image as the creator.  Values are in the range
+    * [0.0, 0.8].  Data valid if (valid & PNG_INFO_cHRM) non-zero.
+    */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float x_white;
+   float y_white;
+   float x_red;
+   float y_red;
+   float x_green;
+   float y_green;
+   float x_blue;
+   float y_blue;
+#endif
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+   /* The pCAL chunk describes a transformation between the stored pixel
+    * values and original physical data values used to create the image.
+    * The integer range [0, 2^bit_depth - 1] maps to the floating-point
+    * range given by [pcal_X0, pcal_X1], and are further transformed by a
+    * (possibly non-linear) transformation function given by "pcal_type"
+    * and "pcal_params" into "pcal_units".  Please see the PNG_EQUATION_
+    * defines below, and the PNG-Group's PNG extensions document for a
+    * complete description of the transformations and how they should be
+    * implemented, and for a description of the ASCII parameter strings.
+    * Data values are valid if (valid & PNG_INFO_pCAL) non-zero.
+    */
+   png_charp pcal_purpose;  /* pCAL chunk description string */
+   png_int_32 pcal_X0;      /* minimum value */
+   png_int_32 pcal_X1;      /* maximum value */
+   png_charp pcal_units;    /* Latin-1 string giving physical units */
+   png_charpp pcal_params;  /* ASCII strings containing parameter values */
+   png_byte pcal_type;      /* equation type (see PNG_EQUATION_ below) */
+   png_byte pcal_nparams;   /* number of parameters given in pcal_params */
+#endif
+
+/* New members added in libpng-1.0.6 */
+#ifdef PNG_FREE_ME_SUPPORTED
+   png_uint_32 free_me;     /* flags items libpng is responsible for freeing */
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+   /* storage for unknown chunks that the library doesn't recognize. */
+   png_unknown_chunkp unknown_chunks;
+   png_size_t unknown_chunks_num;
+#endif
+
+#if defined(PNG_iCCP_SUPPORTED)
+   /* iCCP chunk data. */
+   png_charp iccp_name;     /* profile name */
+   png_charp iccp_profile;  /* International Color Consortium profile data */
+                            /* Note to maintainer: should be png_bytep */
+   png_uint_32 iccp_proflen;  /* ICC profile data length */
+   png_byte iccp_compression; /* Always zero */
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+   /* data on sPLT chunks (there may be more than one). */
+   png_sPLT_tp splt_palettes;
+   png_uint_32 splt_palettes_num;
+#endif
+
+#if defined(PNG_sCAL_SUPPORTED)
+   /* The sCAL chunk describes the actual physical dimensions of the
+    * subject matter of the graphic.  The chunk contains a unit specification
+    * a byte value, and two ASCII strings representing floating-point
+    * values.  The values are width and height corresponsing to one pixel
+    * in the image.  This external representation is converted to double
+    * here.  Data values are valid if (valid & PNG_INFO_sCAL) is non-zero.
+    */
+   png_byte scal_unit;         /* unit of physical scale */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   double scal_pixel_width;    /* width of one pixel */
+   double scal_pixel_height;   /* height of one pixel */
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_charp scal_s_width;     /* string containing height */
+   png_charp scal_s_height;    /* string containing width */
+#endif
+#endif
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+   /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */
+   /* Data valid if (valid & PNG_INFO_IDAT) non-zero */
+   png_bytepp row_pointers;        /* the image bits */
+#endif
+
+#if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED)
+   png_fixed_point int_gamma; /* gamma of image, if (valid & PNG_INFO_gAMA) */
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED)
+   png_fixed_point int_x_white;
+   png_fixed_point int_y_white;
+   png_fixed_point int_x_red;
+   png_fixed_point int_y_red;
+   png_fixed_point int_x_green;
+   png_fixed_point int_y_green;
+   png_fixed_point int_x_blue;
+   png_fixed_point int_y_blue;
+#endif
+
+} png_info;
+
+typedef png_info FAR * png_infop;
+typedef png_info FAR * FAR * png_infopp;
+
+/* Maximum positive integer used in PNG is (2^31)-1 */
+#define PNG_MAX_UINT ((png_uint_32)0x7fffffffL)
+
+/* These describe the color_type field in png_info. */
+/* color type masks */
+#define PNG_COLOR_MASK_PALETTE    1
+#define PNG_COLOR_MASK_COLOR      2
+#define PNG_COLOR_MASK_ALPHA      4
+
+/* color types.  Note that not all combinations are legal */
+#define PNG_COLOR_TYPE_GRAY 0
+#define PNG_COLOR_TYPE_PALETTE  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
+#define PNG_COLOR_TYPE_RGB        (PNG_COLOR_MASK_COLOR)
+#define PNG_COLOR_TYPE_RGB_ALPHA  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
+#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
+/* aliases */
+#define PNG_COLOR_TYPE_RGBA  PNG_COLOR_TYPE_RGB_ALPHA
+#define PNG_COLOR_TYPE_GA  PNG_COLOR_TYPE_GRAY_ALPHA
+
+/* This is for compression type. PNG 1.0-1.2 only define the single type. */
+#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */
+#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE
+
+/* This is for filter type. PNG 1.0-1.2 only define the single type. */
+#define PNG_FILTER_TYPE_BASE      0 /* Single row per-byte filtering */
+#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */
+#define PNG_FILTER_TYPE_DEFAULT   PNG_FILTER_TYPE_BASE
+
+/* These are for the interlacing type.  These values should NOT be changed. */
+#define PNG_INTERLACE_NONE        0 /* Non-interlaced image */
+#define PNG_INTERLACE_ADAM7       1 /* Adam7 interlacing */
+#define PNG_INTERLACE_LAST        2 /* Not a valid value */
+
+/* These are for the oFFs chunk.  These values should NOT be changed. */
+#define PNG_OFFSET_PIXEL          0 /* Offset in pixels */
+#define PNG_OFFSET_MICROMETER     1 /* Offset in micrometers (1/10^6 meter) */
+#define PNG_OFFSET_LAST           2 /* Not a valid value */
+
+/* These are for the pCAL chunk.  These values should NOT be changed. */
+#define PNG_EQUATION_LINEAR       0 /* Linear transformation */
+#define PNG_EQUATION_BASE_E       1 /* Exponential base e transform */
+#define PNG_EQUATION_ARBITRARY    2 /* Arbitrary base exponential transform */
+#define PNG_EQUATION_HYPERBOLIC   3 /* Hyperbolic sine transformation */
+#define PNG_EQUATION_LAST         4 /* Not a valid value */
+
+/* These are for the sCAL chunk.  These values should NOT be changed. */
+#define PNG_SCALE_UNKNOWN         0 /* unknown unit (image scale) */
+#define PNG_SCALE_METER           1 /* meters per pixel */
+#define PNG_SCALE_RADIAN          2 /* radians per pixel */
+#define PNG_SCALE_LAST            3 /* Not a valid value */
+
+/* These are for the pHYs chunk.  These values should NOT be changed. */
+#define PNG_RESOLUTION_UNKNOWN    0 /* pixels/unknown unit (aspect ratio) */
+#define PNG_RESOLUTION_METER      1 /* pixels/meter */
+#define PNG_RESOLUTION_LAST       2 /* Not a valid value */
+
+/* These are for the sRGB chunk.  These values should NOT be changed. */
+#define PNG_sRGB_INTENT_PERCEPTUAL 0
+#define PNG_sRGB_INTENT_RELATIVE   1
+#define PNG_sRGB_INTENT_SATURATION 2
+#define PNG_sRGB_INTENT_ABSOLUTE   3
+#define PNG_sRGB_INTENT_LAST       4 /* Not a valid value */
+
+/* This is for text chunks */
+#define PNG_KEYWORD_MAX_LENGTH     79
+
+/* Maximum number of entries in PLTE/sPLT/tRNS arrays */
+#define PNG_MAX_PALETTE_LENGTH    256
+
+/* These determine if an ancillary chunk's data has been successfully read
+ * from the PNG header, or if the application has filled in the corresponding
+ * data in the info_struct to be written into the output file.  The values
+ * of the PNG_INFO_<chunk> defines should NOT be changed.
+ */
+#define PNG_INFO_gAMA 0x0001
+#define PNG_INFO_sBIT 0x0002
+#define PNG_INFO_cHRM 0x0004
+#define PNG_INFO_PLTE 0x0008
+#define PNG_INFO_tRNS 0x0010
+#define PNG_INFO_bKGD 0x0020
+#define PNG_INFO_hIST 0x0040
+#define PNG_INFO_pHYs 0x0080
+#define PNG_INFO_oFFs 0x0100
+#define PNG_INFO_tIME 0x0200
+#define PNG_INFO_pCAL 0x0400
+#define PNG_INFO_sRGB 0x0800   /* GR-P, 0.96a */
+#define PNG_INFO_iCCP 0x1000   /* ESR, 1.0.6 */
+#define PNG_INFO_sPLT 0x2000   /* ESR, 1.0.6 */
+#define PNG_INFO_sCAL 0x4000   /* ESR, 1.0.6 */
+#define PNG_INFO_IDAT 0x8000L  /* ESR, 1.0.6 */
+
+/* This is used for the transformation routines, as some of them
+ * change these values for the row.  It also should enable using
+ * the routines for other purposes.
+ */
+typedef struct png_row_info_struct
+{
+   png_uint_32 width; /* width of row */
+   png_uint_32 rowbytes; /* number of bytes in row */
+   png_byte color_type; /* color type of row */
+   png_byte bit_depth; /* bit depth of row */
+   png_byte channels; /* number of channels (1, 2, 3, or 4) */
+   png_byte pixel_depth; /* bits per pixel (depth * channels) */
+} png_row_info;
+
+typedef png_row_info FAR * png_row_infop;
+typedef png_row_info FAR * FAR * png_row_infopp;
+
+/* These are the function types for the I/O functions and for the functions
+ * that allow the user to override the default I/O functions with his or her
+ * own.  The png_error_ptr type should match that of user-supplied warning
+ * and error functions, while the png_rw_ptr type should match that of the
+ * user read/write data functions.
+ */
+typedef struct png_struct_def png_struct;
+typedef png_struct FAR * png_structp;
+
+typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp));
+typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t));
+typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp));
+typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32,
+   int));
+typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32,
+   int));
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop));
+typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop));
+typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep,
+   png_uint_32, int));
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp,
+    png_row_infop, png_bytep));
+#endif
+
+#if defined(PNG_USER_CHUNKS_SUPPORTED)
+typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp));
+#endif
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp));
+#endif
+
+/* Transform masks for the high-level interface */
+#define PNG_TRANSFORM_IDENTITY       0x0000    /* read and write */
+#define PNG_TRANSFORM_STRIP_16       0x0001    /* read only */
+#define PNG_TRANSFORM_STRIP_ALPHA    0x0002    /* read only */
+#define PNG_TRANSFORM_PACKING        0x0004    /* read and write */
+#define PNG_TRANSFORM_PACKSWAP       0x0008    /* read and write */
+#define PNG_TRANSFORM_EXPAND         0x0010    /* read only */
+#define PNG_TRANSFORM_INVERT_MONO    0x0020    /* read and write */
+#define PNG_TRANSFORM_SHIFT          0x0040    /* read and write */
+#define PNG_TRANSFORM_BGR            0x0080    /* read and write */
+#define PNG_TRANSFORM_SWAP_ALPHA     0x0100    /* read and write */
+#define PNG_TRANSFORM_SWAP_ENDIAN    0x0200    /* read and write */
+#define PNG_TRANSFORM_INVERT_ALPHA   0x0400    /* read and write */
+#define PNG_TRANSFORM_STRIP_FILLER   0x0800    /* WRITE only */
+
+/* Flags for MNG supported features */
+#define PNG_FLAG_MNG_EMPTY_PLTE     0x01
+#define PNG_FLAG_MNG_FILTER_64      0x04
+#define PNG_ALL_MNG_FEATURES        0x05
+
+typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t));
+typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp));
+
+/* The structure that holds the information to read and write PNG files.
+ * The only people who need to care about what is inside of this are the
+ * people who will be modifying the library for their own special needs.
+ * It should NOT be accessed directly by an application, except to store
+ * the jmp_buf.
+ */
+
+struct png_struct_def
+{
+#ifdef PNG_SETJMP_SUPPORTED
+   jmp_buf jmpbuf;            /* used in png_error */
+#endif
+   png_error_ptr error_fn;    /* function for printing errors and aborting */
+   png_error_ptr warning_fn;  /* function for printing warnings */
+   png_voidp error_ptr;       /* user supplied struct for error functions */
+   png_rw_ptr write_data_fn;  /* function for writing output data */
+   png_rw_ptr read_data_fn;   /* function for reading input data */
+   png_voidp io_ptr;          /* ptr to application struct for I/O functions*/
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   png_user_transform_ptr read_user_transform_fn; /* user read transform */
+#endif
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+   png_user_transform_ptr write_user_transform_fn; /* user write transform */
+#endif
+
+/* These were added in libpng-1.0.2 */
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+   png_voidp user_transform_ptr; /* user supplied struct for user transform */
+   png_byte user_transform_depth;    /* bit depth of user transformed pixels */
+   png_byte user_transform_channels; /* channels in user transformed pixels */
+#endif
+#endif
+
+   png_uint_32 mode;          /* tells us where we are in the PNG file */
+   png_uint_32 flags;         /* flags indicating various things to libpng */
+   png_uint_32 transformations; /* which transformations to perform */
+
+   z_stream zstream;          /* pointer to decompression structure (below) */
+   png_bytep zbuf;            /* buffer for zlib */
+   png_size_t zbuf_size;      /* size of zbuf */
+   int zlib_level;            /* holds zlib compression level */
+   int zlib_method;           /* holds zlib compression method */
+   int zlib_window_bits;      /* holds zlib compression window bits */
+   int zlib_mem_level;        /* holds zlib compression memory level */
+   int zlib_strategy;         /* holds zlib compression strategy */
+
+   png_uint_32 width;         /* width of image in pixels */
+   png_uint_32 height;        /* height of image in pixels */
+   png_uint_32 num_rows;      /* number of rows in current pass */
+   png_uint_32 usr_width;     /* width of row at start of write */
+   png_uint_32 rowbytes;      /* size of row in bytes */
+   png_uint_32 irowbytes;     /* size of current interlaced row in bytes */
+   png_uint_32 iwidth;        /* width of current interlaced row in pixels */
+   png_uint_32 row_number;    /* current row in interlace pass */
+   png_bytep prev_row;        /* buffer to save previous (unfiltered) row */
+   png_bytep row_buf;         /* buffer to save current (unfiltered) row */
+   png_bytep sub_row;         /* buffer to save "sub" row when filtering */
+   png_bytep up_row;          /* buffer to save "up" row when filtering */
+   png_bytep avg_row;         /* buffer to save "avg" row when filtering */
+   png_bytep paeth_row;       /* buffer to save "Paeth" row when filtering */
+   png_row_info row_info;     /* used for transformation routines */
+
+   png_uint_32 idat_size;     /* current IDAT size for read */
+   png_uint_32 crc;           /* current chunk CRC value */
+   png_colorp palette;        /* palette from the input file */
+   png_uint_16 num_palette;   /* number of color entries in palette */
+   png_uint_16 num_trans;     /* number of transparency values */
+   png_byte chunk_name[5];    /* null-terminated name of current chunk */
+   png_byte compression;      /* file compression type (always 0) */
+   png_byte filter;           /* file filter type (always 0) */
+   png_byte interlaced;       /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
+   png_byte pass;             /* current interlace pass (0 - 6) */
+   png_byte do_filter;        /* row filter flags (see PNG_FILTER_ below ) */
+   png_byte color_type;       /* color type of file */
+   png_byte bit_depth;        /* bit depth of file */
+   png_byte usr_bit_depth;    /* bit depth of users row */
+   png_byte pixel_depth;      /* number of bits per pixel */
+   png_byte channels;         /* number of channels in file */
+   png_byte usr_channels;     /* channels at start of write */
+   png_byte sig_bytes;        /* magic bytes read/written from start of file */
+
+#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
+#ifdef PNG_LEGACY_SUPPORTED
+   png_byte filler;           /* filler byte for pixel expansion */
+#else
+   png_uint_16 filler;           /* filler bytes for pixel expansion */
+#endif
+#endif
+
+#if defined(PNG_bKGD_SUPPORTED)
+   png_byte background_gamma_type;
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+   float background_gamma;
+#  endif
+   png_color_16 background;   /* background color in screen gamma space */
+#  if defined(PNG_READ_GAMMA_SUPPORTED)
+     png_color_16 background_1; /* background normalized to gamma 1.0 */
+#  endif /* PNG_READ_GAMMA && PNG_bKGD_SUPPORTED */
+#endif /* PNG_bKGD_SUPPORTED */
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+   png_flush_ptr output_flush_fn;/* Function for flushing output */
+   png_uint_32 flush_dist;    /* how many rows apart to flush, 0 - no flush */
+   png_uint_32 flush_rows;    /* number of rows written since last flush */
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+   int gamma_shift;      /* number of "insignificant" bits 16-bit gamma */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float gamma;          /* file gamma value */
+   float screen_gamma;   /* screen gamma value (display_exponent) */
+#endif
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+   png_bytep gamma_table;     /* gamma table for 8-bit depth files */
+   png_bytep gamma_from_1;    /* converts from 1.0 to screen */
+   png_bytep gamma_to_1;      /* converts from file to 1.0 */
+   png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */
+   png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */
+   png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED)
+   png_color_8 sig_bit;       /* significant bits in each available channel */
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
+   png_color_8 shift;         /* shift for significant bit tranformation */
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \
+ || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+   png_bytep trans;           /* transparency values for paletted files */
+   png_color_16 trans_values; /* transparency values for non-paletted files */
+#endif
+
+   png_read_status_ptr read_row_fn;   /* called after each row is decoded */
+   png_write_status_ptr write_row_fn; /* called after each row is encoded */
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+   png_progressive_info_ptr info_fn; /* called after header data fully read */
+   png_progressive_row_ptr row_fn;   /* called after each prog. row is decoded */
+   png_progressive_end_ptr end_fn;   /* called after image is complete */
+   png_bytep save_buffer_ptr;        /* current location in save_buffer */
+   png_bytep save_buffer;            /* buffer for previously read data */
+   png_bytep current_buffer_ptr;     /* current location in current_buffer */
+   png_bytep current_buffer;         /* buffer for recently used data */
+   png_uint_32 push_length;          /* size of current input chunk */
+   png_uint_32 skip_length;          /* bytes to skip in input data */
+   png_size_t save_buffer_size;      /* amount of data now in save_buffer */
+   png_size_t save_buffer_max;       /* total size of save_buffer */
+   png_size_t buffer_size;           /* total amount of available input data */
+   png_size_t current_buffer_size;   /* amount of data now in current_buffer */
+   int process_mode;                 /* what push library is currently doing */
+   int cur_palette;                  /* current push library palette index */
+
+#  if defined(PNG_TEXT_SUPPORTED)
+     png_size_t current_text_size;   /* current size of text input data */
+     png_size_t current_text_left;   /* how much text left to read in input */
+     png_charp current_text;         /* current text chunk buffer */
+     png_charp current_text_ptr;     /* current location in current_text */
+#  endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */
+
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+
+#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
+/* for the Borland special 64K segment handler */
+   png_bytepp offset_table_ptr;
+   png_bytep offset_table;
+   png_uint_16 offset_table_number;
+   png_uint_16 offset_table_count;
+   png_uint_16 offset_table_count_free;
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+   png_bytep palette_lookup;         /* lookup table for dithering */
+   png_bytep dither_index;           /* index translation for palette files */
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED)
+   png_uint_16p hist;                /* histogram */
+#endif
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   png_byte heuristic_method;        /* heuristic for row filter selection */
+   png_byte num_prev_filters;        /* number of weights for previous rows */
+   png_bytep prev_filters;           /* filter type(s) of previous row(s) */
+   png_uint_16p filter_weights;      /* weight(s) for previous line(s) */
+   png_uint_16p inv_filter_weights;  /* 1/weight(s) for previous line(s) */
+   png_uint_16p filter_costs;        /* relative filter calculation cost */
+   png_uint_16p inv_filter_costs;    /* 1/relative filter calculation cost */
+#endif
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+   png_charp time_buffer;            /* String to hold RFC 1123 time text */
+#endif
+
+/* New members added in libpng-1.0.6 */
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   png_uint_32 free_me;       /* flags items libpng is responsible for freeing */
+#endif
+
+#if defined(PNG_USER_CHUNKS_SUPPORTED)
+   png_voidp user_chunk_ptr;
+   png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+   int num_chunk_list;
+   png_bytep chunk_list;
+#endif
+
+/* New members added in libpng-1.0.3 */
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+   png_byte rgb_to_gray_status;
+   /* These were changed from png_byte in libpng-1.0.6 */
+   png_uint_16 rgb_to_gray_red_coeff;
+   png_uint_16 rgb_to_gray_green_coeff;
+   png_uint_16 rgb_to_gray_blue_coeff;
+#endif
+
+/* New member added in libpng-1.0.4 (renamed in 1.0.9) */
+#if defined(PNG_MNG_FEATURES_SUPPORTED) || \
+    defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
+    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+/* changed from png_byte to png_uint_32 at version 1.2.0 */
+   png_uint_32 mng_features_permitted;
+#endif
+
+/* New member added in libpng-1.0.7 */
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+   png_fixed_point int_gamma;
+#endif
+
+/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   png_byte filter_type;
+#endif
+
+#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
+/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */
+   png_uint_32 row_buf_size;
+#endif
+
+/* New members added in libpng-1.2.0 */
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+   png_byte     mmx_bitdepth_threshold;
+   png_uint_32  mmx_rowbytes_threshold;
+   png_uint_32  asm_flags;
+#endif
+
+/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_voidp mem_ptr;                /* user supplied struct for mem functions */
+   png_malloc_ptr malloc_fn;         /* function for allocating memory */
+   png_free_ptr free_fn;             /* function for freeing memory */
+#endif
+
+   png_bytep big_row_buf;         /* buffer to save current (unfiltered) row */
+
+};
+
+
+/* This prevents a compiler error in png_get_copyright() in png.c if png.c
+   and png.h are both at version 1.2.0
+ */
+typedef png_structp version_1_2_0;
+
+typedef png_struct FAR * FAR * png_structpp;
+
+/* Here are the function definitions most commonly used.  This is not
+ * the place to find out how to use libpng.  See libpng.txt for the
+ * full explanation, see example.c for the summary.  This just provides
+ * a simple one line description of the use of each function.
+ */
+
+/* Returns the version number of the library */
+extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void));
+
+/* Tell lib we have already handled the first <num_bytes> magic bytes.
+ * Handling more than 8 bytes from the beginning of the file is an error.
+ */
+extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr,
+   int num_bytes));
+
+/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
+ * PNG file.  Returns zero if the supplied bytes match the 8-byte PNG
+ * signature, and non-zero otherwise.  Having num_to_check == 0 or
+ * start > 7 will always fail (ie return non-zero).
+ */
+extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start,
+   png_size_t num_to_check));
+
+/* Simple signature checking function.  This is the same as calling
+ * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
+ */
+extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num));
+
+/* Allocate and initialize png_ptr struct for reading, and any other memory. */
+extern PNG_EXPORT(png_structp,png_create_read_struct)
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn));
+
+/* Allocate and initialize png_ptr struct for writing, and any other memory */
+extern PNG_EXPORT(png_structp,png_create_write_struct)
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn));
+
+extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size)
+   PNGARG((png_structp png_ptr));
+
+extern PNG_EXPORT(void,png_set_compression_buffer_size)
+   PNGARG((png_structp png_ptr, png_uint_32 size));
+
+/* Reset the compression stream */
+extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr));
+
+/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */
+#ifdef PNG_USER_MEM_SUPPORTED
+extern PNG_EXPORT(png_structp,png_create_read_struct_2)
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+extern PNG_EXPORT(png_structp,png_create_write_struct_2)
+   PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+#endif
+
+/* Write a PNG chunk - size, type, (optional) data, CRC. */
+extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr,
+   png_bytep chunk_name, png_bytep data, png_size_t length));
+
+/* Write the start of a PNG chunk - length and chunk name. */
+extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr,
+   png_bytep chunk_name, png_uint_32 length));
+
+/* Write the data of a PNG chunk started with png_write_chunk_start(). */
+extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr,
+   png_bytep data, png_size_t length));
+
+/* Finish a chunk started with png_write_chunk_start() (includes CRC). */
+extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr));
+
+/* Allocate and initialize the info structure */
+extern PNG_EXPORT(png_infop,png_create_info_struct)
+   PNGARG((png_structp png_ptr));
+
+/* Initialize the info structure (old interface - DEPRECATED) */
+extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr));
+#define png_info_init(info_ptr) png_info_init_3(&info_ptr, sizeof(png_info));
+extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr,
+    png_size_t png_info_struct_size));
+
+/* Writes all the PNG information before the image. */
+extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* read the information before the actual image data. */
+extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+extern PNG_EXPORT(png_charp,png_convert_to_rfc1123)
+   PNGARG((png_structp png_ptr, png_timep ptime));
+#endif
+
+#if !defined(_WIN32_WCE)
+/* "time.h" functions are not supported on WindowsCE */
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+/* convert from a struct tm to png_time */
+extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime,
+   struct tm FAR * ttime));
+
+/* convert from time_t to png_time.  Uses gmtime() */
+extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime,
+   time_t ttime));
+#endif /* PNG_WRITE_tIME_SUPPORTED */
+#endif /* _WIN32_WCE */
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */
+extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+/* Use blue, green, red order for pixels. */
+extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+/* Expand the grayscale to 24-bit RGB if necessary. */
+extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+/* Reduce RGB to grayscale. */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr,
+   int error_action, double red, double green ));
+#endif
+extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr,
+   int error_action, png_fixed_point red, png_fixed_point green ));
+extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp
+   png_ptr));
+#endif
+
+extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth,
+   png_colorp palette));
+
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
+    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
+    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
+/* Add a filler byte to 24-bit RGB images. */
+extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr,
+   png_uint_32 filler, int flags));
+/* The values of the PNG_FILLER_ defines should NOT be changed */
+#define PNG_FILLER_BEFORE 0
+#define PNG_FILLER_AFTER 1
+#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+/* Swap bytes in 16-bit depth files. */
+extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
+/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
+extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+/* Swap packing order of pixels in bytes. */
+extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
+/* Converts files to legal bit depths. */
+extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr,
+   png_color_8p true_bits));
+#endif
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
+    defined(PNG_WRITE_INTERLACING_SUPPORTED)
+/* Have the code handle the interlacing.  Returns the number of passes. */
+extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
+/* Invert monochrome files */
+extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+/* Handle alpha and tRNS by replacing with a background color. */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr,
+   png_color_16p background_color, int background_gamma_code,
+   int need_expand, double background_gamma));
+#endif
+#define PNG_BACKGROUND_GAMMA_UNKNOWN 0
+#define PNG_BACKGROUND_GAMMA_SCREEN  1
+#define PNG_BACKGROUND_GAMMA_FILE    2
+#define PNG_BACKGROUND_GAMMA_UNIQUE  3
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+/* strip the second byte of information from a 16-bit depth file. */
+extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+/* Turn on dithering, and reduce the palette to the number of colors available. */
+extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr,
+   png_colorp palette, int num_palette, int maximum_colors,
+   png_uint_16p histogram, int full_dither));
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+/* Handle gamma correction. Screen_gamma=(display_exponent) */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr,
+   double screen_gamma, double default_file_gamma));
+#endif
+#endif
+
+#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
+    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */
+/* Deprecated and will be removed.  Use png_permit_mng_features() instead. */
+extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr,
+   int empty_plte_permitted));
+#endif
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+/* Set how many lines between output flushes - 0 for no flushing */
+extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows));
+/* Flush the current PNG output buffer */
+extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr));
+#endif
+
+/* optional update palette with requested transformations */
+extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr));
+
+/* optional call to update the users info structure */
+extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* read a one or more rows of image data.*/
+extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr,
+   png_bytepp row, png_bytepp display_row, png_uint_32 num_rows));
+
+/* read a row of data.*/
+extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr,
+   png_bytep row,
+   png_bytep display_row));
+
+/* read the whole image into memory at once. */
+extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr,
+   png_bytepp image));
+
+/* write a row of image data */
+extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr,
+   png_bytep row));
+
+/* write a few rows of image data */
+extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr,
+   png_bytepp row, png_uint_32 num_rows));
+
+/* write the image data */
+extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr,
+   png_bytepp image));
+
+/* writes the end of the PNG file. */
+extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* read the end of the PNG file. */
+extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* free any memory associated with the png_info_struct */
+extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr,
+   png_infopp info_ptr_ptr));
+
+/* free any memory associated with the png_struct and the png_info_structs */
+extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp
+   png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr));
+
+/* free all memory used by the read (old method - NOT DLL EXPORTED) */
+extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_infop end_info_ptr));
+
+/* free any memory associated with the png_struct and the png_info_structs */
+extern PNG_EXPORT(void,png_destroy_write_struct)
+   PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr));
+
+/* free any memory used in info_ptr struct (old method - NOT DLL EXPORTED) */
+extern void png_write_destroy_info PNGARG((png_infop info_ptr));
+
+/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */
+extern void png_write_destroy PNGARG((png_structp png_ptr));
+
+/* set the libpng method of handling chunk CRC errors */
+extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr,
+   int crit_action, int ancil_action));
+
+/* Values for png_set_crc_action() to say how to handle CRC errors in
+ * ancillary and critical chunks, and whether to use the data contained
+ * therein.  Note that it is impossible to "discard" data in a critical
+ * chunk.  For versions prior to 0.90, the action was always error/quit,
+ * whereas in version 0.90 and later, the action for CRC errors in ancillary
+ * chunks is warn/discard.  These values should NOT be changed.
+ *
+ *      value                       action:critical     action:ancillary
+ */
+#define PNG_CRC_DEFAULT       0  /* error/quit          warn/discard data */
+#define PNG_CRC_ERROR_QUIT    1  /* error/quit          error/quit        */
+#define PNG_CRC_WARN_DISCARD  2  /* (INVALID)           warn/discard data */
+#define PNG_CRC_WARN_USE      3  /* warn/use data       warn/use data     */
+#define PNG_CRC_QUIET_USE     4  /* quiet/use data      quiet/use data    */
+#define PNG_CRC_NO_CHANGE     5  /* use current value   use current value */
+
+/* These functions give the user control over the scan-line filtering in
+ * libpng and the compression methods used by zlib.  These functions are
+ * mainly useful for testing, as the defaults should work with most users.
+ * Those users who are tight on memory or want faster performance at the
+ * expense of compression can modify them.  See the compression library
+ * header file (zlib.h) for an explination of the compression functions.
+ */
+
+/* set the filtering method(s) used by libpng.  Currently, the only valid
+ * value for "method" is 0.
+ */
+extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method,
+   int filters));
+
+/* Flags for png_set_filter() to say which filters to use.  The flags
+ * are chosen so that they don't conflict with real filter types
+ * below, in case they are supplied instead of the #defined constants.
+ * These values should NOT be changed.
+ */
+#define PNG_NO_FILTERS     0x00
+#define PNG_FILTER_NONE    0x08
+#define PNG_FILTER_SUB     0x10
+#define PNG_FILTER_UP      0x20
+#define PNG_FILTER_AVG     0x40
+#define PNG_FILTER_PAETH   0x80
+#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \
+                         PNG_FILTER_AVG | PNG_FILTER_PAETH)
+
+/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
+ * These defines should NOT be changed.
+ */
+#define PNG_FILTER_VALUE_NONE  0
+#define PNG_FILTER_VALUE_SUB   1
+#define PNG_FILTER_VALUE_UP    2
+#define PNG_FILTER_VALUE_AVG   3
+#define PNG_FILTER_VALUE_PAETH 4
+#define PNG_FILTER_VALUE_LAST  5
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */
+/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_
+ * defines, either the default (minimum-sum-of-absolute-differences), or
+ * the experimental method (weighted-minimum-sum-of-absolute-differences).
+ *
+ * Weights are factors >= 1.0, indicating how important it is to keep the
+ * filter type consistent between rows.  Larger numbers mean the current
+ * filter is that many times as likely to be the same as the "num_weights"
+ * previous filters.  This is cumulative for each previous row with a weight.
+ * There needs to be "num_weights" values in "filter_weights", or it can be
+ * NULL if the weights aren't being specified.  Weights have no influence on
+ * the selection of the first row filter.  Well chosen weights can (in theory)
+ * improve the compression for a given image.
+ *
+ * Costs are factors >= 1.0 indicating the relative decoding costs of a
+ * filter type.  Higher costs indicate more decoding expense, and are
+ * therefore less likely to be selected over a filter with lower computational
+ * costs.  There needs to be a value in "filter_costs" for each valid filter
+ * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't
+ * setting the costs.  Costs try to improve the speed of decompression without
+ * unduly increasing the compressed image size.
+ *
+ * A negative weight or cost indicates the default value is to be used, and
+ * values in the range [0.0, 1.0) indicate the value is to remain unchanged.
+ * The default values for both weights and costs are currently 1.0, but may
+ * change if good general weighting/cost heuristics can be found.  If both
+ * the weights and costs are set to 1.0, this degenerates the WEIGHTED method
+ * to the UNWEIGHTED method, but with added encoding time/computation.
+ */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr,
+   int heuristic_method, int num_weights, png_doublep filter_weights,
+   png_doublep filter_costs));
+#endif
+#endif /*  PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+
+/* Heuristic used for row filter selection.  These defines should NOT be
+ * changed.
+ */
+#define PNG_FILTER_HEURISTIC_DEFAULT    0  /* Currently "UNWEIGHTED" */
+#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1  /* Used by libpng < 0.95 */
+#define PNG_FILTER_HEURISTIC_WEIGHTED   2  /* Experimental feature */
+#define PNG_FILTER_HEURISTIC_LAST       3  /* Not a valid value */
+
+/* Set the library compression level.  Currently, valid values range from
+ * 0 - 9, corresponding directly to the zlib compression levels 0 - 9
+ * (0 - no compression, 9 - "maximal" compression).  Note that tests have
+ * shown that zlib compression levels 3-6 usually perform as well as level 9
+ * for PNG images, and do considerably fewer caclulations.  In the future,
+ * these values may not correspond directly to the zlib compression levels.
+ */
+extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr,
+   int level));
+
+extern PNG_EXPORT(void,png_set_compression_mem_level)
+   PNGARG((png_structp png_ptr, int mem_level));
+
+extern PNG_EXPORT(void,png_set_compression_strategy)
+   PNGARG((png_structp png_ptr, int strategy));
+
+extern PNG_EXPORT(void,png_set_compression_window_bits)
+   PNGARG((png_structp png_ptr, int window_bits));
+
+extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr,
+   int method));
+
+/* These next functions are called for input/output, memory, and error
+ * handling.  They are in the file pngrio.c, pngwio.c, and pngerror.c,
+ * and call standard C I/O routines such as fread(), fwrite(), and
+ * fprintf().  These functions can be made to use other I/O routines
+ * at run time for those applications that need to handle I/O in a
+ * different manner by calling png_set_???_fn().  See libpng.txt for
+ * more information.
+ */
+
+#if !defined(PNG_NO_STDIO)
+/* Initialize the input/output for the PNG file to the default functions. */
+extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp));
+#endif
+
+/* Replace the (error and abort), and warning functions with user
+ * supplied functions.  If no messages are to be printed you must still
+ * write and use replacement functions. The replacement error_fn should
+ * still do a longjmp to the last setjmp location if you are using this
+ * method of error handling.  If error_fn or warning_fn is NULL, the
+ * default function will be used.
+ */
+
+extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr,
+   png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn));
+
+/* Return the user pointer associated with the error functions */
+extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr));
+
+/* Replace the default data output functions with a user supplied one(s).
+ * If buffered output is not used, then output_flush_fn can be set to NULL.
+ * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time
+ * output_flush_fn will be ignored (and thus can be NULL).
+ */
+extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr,
+   png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn));
+
+/* Replace the default data input function with a user supplied one. */
+extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr,
+   png_voidp io_ptr, png_rw_ptr read_data_fn));
+
+/* Return the user pointer associated with the I/O functions */
+extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr));
+
+extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr,
+   png_read_status_ptr read_row_fn));
+
+extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr,
+   png_write_status_ptr write_row_fn));
+
+#ifdef PNG_USER_MEM_SUPPORTED
+/* Replace the default memory allocation functions with user supplied one(s). */
+extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr,
+   png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+/* Return the user pointer associated with the memory functions */
+extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp
+   png_ptr, png_user_transform_ptr read_user_transform_fn));
+#endif
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp
+   png_ptr, png_user_transform_ptr write_user_transform_fn));
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp
+   png_ptr, png_voidp user_transform_ptr, int user_transform_depth,
+   int user_transform_channels));
+/* Return the user pointer associated with the user transform functions */
+extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr)
+   PNGARG((png_structp png_ptr));
+#endif
+
+#ifdef PNG_USER_CHUNKS_SUPPORTED
+extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr,
+   png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn));
+extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp
+   png_ptr));
+#endif
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+/* Sets the function callbacks for the push reader, and a pointer to a
+ * user-defined structure available to the callback functions.
+ */
+extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr,
+   png_voidp progressive_ptr,
+   png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
+   png_progressive_end_ptr end_fn));
+
+/* returns the user pointer associated with the push read functions */
+extern PNG_EXPORT(png_voidp,png_get_progressive_ptr)
+   PNGARG((png_structp png_ptr));
+
+/* function to be called when data becomes available */
+extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_bytep buffer, png_size_t buffer_size));
+
+/* function that combines rows.  Not very much different than the
+ * png_combine_row() call.  Is this even used?????
+ */
+extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr,
+   png_bytep old_row, png_bytep new_row));
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+
+extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr,
+   png_uint_32 size));
+
+/* frees a pointer allocated by png_malloc() */
+extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr));
+
+/* Free data that was allocated internally */
+extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 free_me, int num));
+#ifdef PNG_FREE_ME_SUPPORTED
+/* Reassign responsibility for freeing existing data, whether allocated
+ * by libpng or by the application */
+extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int freer, png_uint_32 mask));
+#endif
+/* assignments for png_data_freer */
+#define PNG_DESTROY_WILL_FREE_DATA 1
+#define PNG_SET_WILL_FREE_DATA 1
+#define PNG_USER_WILL_FREE_DATA 2
+/* Flags for png_ptr->free_me and info_ptr->free_me */
+#define PNG_FREE_HIST 0x0008
+#define PNG_FREE_ICCP 0x0010
+#define PNG_FREE_SPLT 0x0020
+#define PNG_FREE_ROWS 0x0040
+#define PNG_FREE_PCAL 0x0080
+#define PNG_FREE_SCAL 0x0100
+#define PNG_FREE_UNKN 0x0200
+#define PNG_FREE_LIST 0x0400
+#define PNG_FREE_PLTE 0x1000
+#define PNG_FREE_TRNS 0x2000
+#define PNG_FREE_TEXT 0x4000
+#define PNG_FREE_ALL  0x7fff
+#define PNG_FREE_MUL  0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
+
+#ifdef PNG_USER_MEM_SUPPORTED
+extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr,
+   png_uint_32 size));
+extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr,
+   png_voidp ptr));
+#endif
+
+extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr,
+   png_voidp s1, png_voidp s2, png_uint_32 size));
+
+extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr,
+   png_voidp s1, int value, png_uint_32 size));
+
+#if defined(USE_FAR_KEYWORD)  /* memory model conversion function */
+extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr,
+   int check));
+#endif /* USE_FAR_KEYWORD */
+
+/* Fatal error in PNG image of libpng - can't continue */
+extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr,
+   png_const_charp error));
+
+/* The same, but the chunk name is prepended to the error string. */
+extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr,
+   png_const_charp error));
+
+/* Non-fatal error in libpng.  Can continue, but may have a problem. */
+extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr,
+   png_const_charp message));
+
+/* Non-fatal error in libpng, chunk name is prepended to message. */
+extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr,
+   png_const_charp message));
+
+/* The png_set_<chunk> functions are for storing values in the png_info_struct.
+ * Similarly, the png_get_<chunk> calls are used to read values from the
+ * png_info_struct, either storing the parameters in the passed variables, or
+ * setting pointers into the png_info_struct where the data is stored.  The
+ * png_get_<chunk> functions return a non-zero value if the data was available
+ * in info_ptr, or return zero and do not change any of the parameters if the
+ * data was not available.
+ *
+ * These functions should be used instead of directly accessing png_info
+ * to avoid problems with future changes in the size and internal layout of
+ * png_info_struct.
+ */
+/* Returns "flag" if chunk data is valid in info_ptr. */
+extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr,
+png_infop info_ptr, png_uint_32 flag));
+
+/* Returns number of bytes needed to hold a transformed row. */
+extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+/* Returns row_pointers, which is an array of pointers to scanlines that was
+returned from png_read_png(). */
+extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+/* Set row_pointers, which is an array of pointers to scanlines for use
+by png_write_png(). */
+extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_bytepp row_pointers));
+#endif
+
+/* Returns number of color channels in image. */
+extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+#ifdef PNG_EASY_ACCESS_SUPPORTED
+/* Returns image width in pixels. */
+extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image height in pixels. */
+extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image bit_depth. */
+extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image color_type. */
+extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image filter_type. */
+extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image interlace_type. */
+extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image compression_type. */
+extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image resolution in pixels per meter, from pHYs chunk data. */
+extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns pixel aspect ratio, computed from pHYs chunk data.  */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+#endif
+
+/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
+extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+#endif /* PNG_EASY_ACCESS_SUPPORTED */
+
+/* Returns pointer to signature string read from PNG header */
+extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+#if defined(PNG_bKGD_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_color_16p *background));
+#endif
+
+#if defined(PNG_bKGD_SUPPORTED)
+extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_color_16p background));
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, double *white_x, double *white_y, double *red_x,
+   double *red_y, double *green_x, double *green_y, double *blue_x,
+   double *blue_y));
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point
+   *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y,
+   png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point
+   *int_blue_x, png_fixed_point *int_blue_y));
+#endif
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, double white_x, double white_y, double red_x,
+   double red_y, double green_x, double green_y, double blue_x, double blue_y));
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y,
+   png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
+   int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
+   png_fixed_point int_blue_y));
+#endif
+#endif
+
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, double *file_gamma));
+#endif
+extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_fixed_point *int_file_gamma));
+#endif
+
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, double file_gamma));
+#endif
+extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_fixed_point int_file_gamma));
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_16p *hist));
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_16p hist));
+#endif
+
+extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 *width, png_uint_32 *height,
+   int *bit_depth, int *color_type, int *interlace_method,
+   int *compression_method, int *filter_method));
+
+extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth,
+   int color_type, int interlace_method, int compression_method,
+   int filter_method));
+
+#if defined(PNG_oFFs_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
+   int *unit_type));
+#endif
+
+#if defined(PNG_oFFs_SUPPORTED)
+extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y,
+   int unit_type));
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1,
+   int *type, int *nparams, png_charp *units, png_charpp *params));
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1,
+   int type, int nparams, png_charp units, png_charpp params));
+#endif
+
+#if defined(PNG_pHYs_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
+#endif
+
+#if defined(PNG_pHYs_SUPPORTED)
+extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type));
+#endif
+
+extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_colorp *palette, int *num_palette));
+
+extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_colorp palette, int num_palette));
+
+#if defined(PNG_sBIT_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_color_8p *sig_bit));
+#endif
+
+#if defined(PNG_sBIT_SUPPORTED)
+extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_color_8p sig_bit));
+#endif
+
+#if defined(PNG_sRGB_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int *intent));
+#endif
+
+#if defined(PNG_sRGB_SUPPORTED)
+extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int intent));
+extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int intent));
+#endif
+
+#if defined(PNG_iCCP_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_charpp name, int *compression_type,
+   png_charpp profile, png_uint_32 *proflen));
+   /* Note to maintainer: profile should be png_bytepp */
+#endif
+
+#if defined(PNG_iCCP_SUPPORTED)
+extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_charp name, int compression_type,
+   png_charp profile, png_uint_32 proflen));
+   /* Note to maintainer: profile should be png_bytep */
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_sPLT_tpp entries));
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_sPLT_tp entries, int nentries));
+#endif
+
+#if defined(PNG_TEXT_SUPPORTED)
+/* png_get_text also returns the number of text chunks in *num_text */
+extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_textp *text_ptr, int *num_text));
+#endif
+
+/*
+ *  Note while png_set_text() will accept a structure whose text,
+ *  language, and  translated keywords are NULL pointers, the structure
+ *  returned by png_get_text will always contain regular
+ *  zero-terminated C strings.  They might be empty strings but
+ *  they will never be NULL pointers.
+ */
+
+#if defined(PNG_TEXT_SUPPORTED)
+extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_textp text_ptr, int num_text));
+#endif
+
+#if defined(PNG_tIME_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_timep *mod_time));
+#endif
+
+#if defined(PNG_tIME_SUPPORTED)
+extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_timep mod_time));
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_bytep *trans, int *num_trans,
+   png_color_16p *trans_values));
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_bytep trans, int num_trans,
+   png_color_16p trans_values));
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+#endif
+
+#if defined(PNG_sCAL_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int *unit, double *width, double *height));
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight));
+#endif
+#endif
+#endif /* PNG_sCAL_SUPPORTED */
+
+#if defined(PNG_sCAL_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int unit, double width, double height));
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int unit, png_charp swidth, png_charp sheight));
+#endif
+#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+/* provide a list of chunks and how they are to be handled, if the built-in
+   handling or default unknown chunk handling is not desired.  Any chunks not
+   listed will be handled in the default manner.  The IHDR and IEND chunks
+   must not be listed.
+      keep = 0: follow default behavour
+           = 1: do not keep
+           = 2: keep only if safe-to-copy
+           = 3: keep even if unsafe-to-copy
+*/
+extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp
+   png_ptr, int keep, png_bytep chunk_list, int num_chunks));
+extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns));
+extern PNG_EXPORT(void, png_set_unknown_chunk_location)
+   PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location));
+extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp
+   png_ptr, png_infop info_ptr, png_unknown_chunkpp entries));
+#endif
+
+/* Png_free_data() will turn off the "valid" flag for anything it frees.
+   If you need to turn it off for a chunk that your application has freed,
+   you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */
+extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr,
+   png_infop info_ptr, int mask));
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+/* The "params" pointer is currently not used and is for future expansion. */
+extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr,
+                        png_infop info_ptr,
+                        int transforms,
+                        png_voidp params));
+extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr,
+                        png_infop info_ptr,
+                        int transforms,
+                        png_voidp params));
+#endif
+
+/* Define PNG_DEBUG at compile time for debugging information.  Higher
+ * numbers for PNG_DEBUG mean more debugging information.  This has
+ * only been added since version 0.95 so it is not implemented throughout
+ * libpng yet, but more support will be added as needed.
+ */
+#ifdef PNG_DEBUG
+#if (PNG_DEBUG > 0)
+#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER)
+#include <crtdbg.h>
+#if (PNG_DEBUG > 1)
+#define png_debug(l,m)  _RPT0(_CRT_WARN,m)
+#define png_debug1(l,m,p1)  _RPT1(_CRT_WARN,m,p1)
+#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2)
+#endif
+#else /* PNG_DEBUG_FILE || !_MSC_VER */
+#ifndef PNG_DEBUG_FILE
+#define PNG_DEBUG_FILE stderr
+#endif /* PNG_DEBUG_FILE */
+#if (PNG_DEBUG > 1)
+#define png_debug(l,m) \
+{ \
+     int num_tabs=l; \
+     fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \
+       (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \
+}
+#define png_debug1(l,m,p1) \
+{ \
+     int num_tabs=l; \
+     fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \
+       (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \
+}
+#define png_debug2(l,m,p1,p2) \
+{ \
+     int num_tabs=l; \
+     fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \
+       (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \
+}
+#endif /* (PNG_DEBUG > 1) */
+#endif /* _MSC_VER */
+#endif /* (PNG_DEBUG > 0) */
+#endif /* PNG_DEBUG */
+#ifndef png_debug
+#define png_debug(l, m)
+#endif
+#ifndef png_debug1
+#define png_debug1(l, m, p1)
+#endif
+#ifndef png_debug2
+#define png_debug2(l, m, p1, p2)
+#endif
+
+extern PNG_EXPORT(png_bytep,png_sig_bytes) PNGARG((void));
+
+extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr));
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp
+   png_ptr, png_uint_32 mng_features_permitted));
+#endif
+
+/* Added to version 1.2.0 */
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED  0x01                /* not user-settable */
+#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU    0x02                /* not user-settable */
+#define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  0x04
+#define PNG_ASM_FLAG_MMX_READ_INTERLACE    0x08
+#define PNG_ASM_FLAG_MMX_READ_FILTER_SUB   0x10
+#define PNG_ASM_FLAG_MMX_READ_FILTER_UP    0x20
+#define PNG_ASM_FLAG_MMX_READ_FILTER_AVG   0x40
+#define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80
+#define PNG_ASM_FLAGS_INITIALIZED          0x80000000  /* not user-settable */
+
+#define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  \
+                           | PNG_ASM_FLAG_MMX_READ_INTERLACE    \
+                           | PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
+                           | PNG_ASM_FLAG_MMX_READ_FILTER_UP    \
+                           | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
+                           | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH )
+#define PNG_MMX_WRITE_FLAGS ( 0 )
+
+#define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \
+                      | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU   \
+                      | PNG_MMX_READ_FLAGS                \
+                      | PNG_MMX_WRITE_FLAGS )
+
+#define PNG_SELECT_READ   1
+#define PNG_SELECT_WRITE  2
+
+
+/* pngget.c */
+extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask)
+   PNGARG((int flag_select, int *compilerID));
+
+/* pngget.c */
+extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask)
+   PNGARG((int flag_select));
+
+/* pngget.c */
+extern PNG_EXPORT(png_uint_32,png_get_asm_flags)
+   PNGARG((png_structp png_ptr));
+
+/* pngget.c */
+extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold)
+   PNGARG((png_structp png_ptr));
+
+/* pngget.c */
+extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold)
+   PNGARG((png_structp png_ptr));
+
+/* pngset.c */
+extern PNG_EXPORT(void,png_set_asm_flags)
+   PNGARG((png_structp png_ptr, png_uint_32 asm_flags));
+
+/* pngset.c */
+extern PNG_EXPORT(void,png_set_mmx_thresholds)
+   PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold,
+   png_uint_32 mmx_rowbytes_threshold));
+
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+
+/* png.c, pnggccrd.c, or pngvcrd.c */
+extern PNG_EXPORT(int,png_mmx_support) PNGARG((void));
+
+/* Strip the prepended error numbers ("#nnn ") from error and warning
+ * messages before passing them to the error or warning handler. */
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp
+   png_ptr, png_uint_32 strip_mode));
+#endif
+
+/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */
+
+#define PNG_HEADER_VERSION_STRING \
+   " libpng version 1.2.0 - September 1, 2001 (header)\n"
+
+#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
+/* With these routines we avoid an integer divide, which will be slower on
+ * most machines.  However, it does take more operations than the corresponding
+ * divide method, so it may be slower on a few RISC systems.  There are two
+ * shifts (by 8 or 16 bits) and an addition, versus a single integer divide.
+ *
+ * Note that the rounding factors are NOT supposed to be the same!  128 and
+ * 32768 are correct for the NODIV code; 127 and 32767 are correct for the
+ * standard method.
+ *
+ * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
+ */
+
+ /* fg and bg should be in `gamma 1.0' space; alpha is the opacity          */
+
+#  define png_composite(composite, fg, alpha, bg)                            \
+     { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \
+                        +        (png_uint_16)(bg)*(png_uint_16)(255 -       \
+                        (png_uint_16)(alpha)) + (png_uint_16)128);           \
+       (composite) = (png_byte)((temp + (temp >> 8)) >> 8); }
+
+#  define png_composite_16(composite, fg, alpha, bg)                         \
+     { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \
+                        + (png_uint_32)(bg)*(png_uint_32)(65535L -           \
+                        (png_uint_32)(alpha)) + (png_uint_32)32768L);        \
+       (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); }
+
+#else  /* standard method using integer division */
+
+#  define png_composite(composite, fg, alpha, bg)                            \
+     (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) +    \
+       (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) +       \
+       (png_uint_16)127) / 255)
+
+#  define png_composite_16(composite, fg, alpha, bg)                         \
+     (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \
+       (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) +      \
+       (png_uint_32)32767) / (png_uint_32)65535L)
+
+#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */
+
+/* These next functions are used internally in the code.  They generally
+ * shouldn't be used unless you are writing code to add or replace some
+ * functionality in libpng.  More information about most functions can
+ * be found in the files where the functions are located.
+ */
+
+#if defined(PNG_INTERNAL)
+
+/* Various modes of operation.  Note that after an init, mode is set to
+ * zero automatically when the structure is created.
+ */
+#define PNG_HAVE_IHDR               0x01
+#define PNG_HAVE_PLTE               0x02
+#define PNG_HAVE_IDAT               0x04
+#define PNG_AFTER_IDAT              0x08
+#define PNG_HAVE_IEND               0x10
+#define PNG_HAVE_gAMA               0x20
+#define PNG_HAVE_cHRM               0x40
+#define PNG_HAVE_sRGB               0x80
+#define PNG_HAVE_CHUNK_HEADER      0x100
+#define PNG_WROTE_tIME             0x200
+#define PNG_WROTE_INFO_BEFORE_PLTE 0x400
+#define PNG_BACKGROUND_IS_GRAY     0x800
+#define PNG_HAVE_PNG_SIGNATURE    0x1000
+
+/* flags for the transformations the PNG library does on the image data */
+#define PNG_BGR                0x0001
+#define PNG_INTERLACE          0x0002
+#define PNG_PACK               0x0004
+#define PNG_SHIFT              0x0008
+#define PNG_SWAP_BYTES         0x0010
+#define PNG_INVERT_MONO        0x0020
+#define PNG_DITHER             0x0040
+#define PNG_BACKGROUND         0x0080
+#define PNG_BACKGROUND_EXPAND  0x0100
+                          /*   0x0200 unused */
+#define PNG_16_TO_8            0x0400
+#define PNG_RGBA               0x0800
+#define PNG_EXPAND             0x1000
+#define PNG_GAMMA              0x2000
+#define PNG_GRAY_TO_RGB        0x4000
+#define PNG_FILLER             0x8000L
+#define PNG_PACKSWAP          0x10000L
+#define PNG_SWAP_ALPHA        0x20000L
+#define PNG_STRIP_ALPHA       0x40000L
+#define PNG_INVERT_ALPHA      0x80000L
+#define PNG_USER_TRANSFORM   0x100000L
+#define PNG_RGB_TO_GRAY_ERR  0x200000L
+#define PNG_RGB_TO_GRAY_WARN 0x400000L
+#define PNG_RGB_TO_GRAY      0x600000L  /* two bits, RGB_TO_GRAY_ERR|WARN */
+
+/* flags for png_create_struct */
+#define PNG_STRUCT_PNG   0x0001
+#define PNG_STRUCT_INFO  0x0002
+
+/* Scaling factor for filter heuristic weighting calculations */
+#define PNG_WEIGHT_SHIFT 8
+#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT))
+#define PNG_COST_SHIFT 3
+#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT))
+
+/* flags for the png_ptr->flags rather than declaring a byte for each one */
+#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY     0x0001
+#define PNG_FLAG_ZLIB_CUSTOM_LEVEL        0x0002
+#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL    0x0004
+#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS  0x0008
+#define PNG_FLAG_ZLIB_CUSTOM_METHOD       0x0010
+#define PNG_FLAG_ZLIB_FINISHED            0x0020
+#define PNG_FLAG_ROW_INIT                 0x0040
+#define PNG_FLAG_FILLER_AFTER             0x0080
+#define PNG_FLAG_CRC_ANCILLARY_USE        0x0100
+#define PNG_FLAG_CRC_ANCILLARY_NOWARN     0x0200
+#define PNG_FLAG_CRC_CRITICAL_USE         0x0400
+#define PNG_FLAG_CRC_CRITICAL_IGNORE      0x0800
+#define PNG_FLAG_FREE_PLTE                0x1000
+#define PNG_FLAG_FREE_TRNS                0x2000
+#define PNG_FLAG_FREE_HIST                0x4000
+#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS      0x8000L
+#define PNG_FLAG_KEEP_UNSAFE_CHUNKS       0x10000L
+#define PNG_FLAG_LIBRARY_MISMATCH         0x20000L
+#define PNG_FLAG_STRIP_ERROR_NUMBERS      0x40000L
+#define PNG_FLAG_STRIP_ERROR_TEXT         0x80000L
+
+/* For use in png_set_keep_unknown, png_handle_as_unknown */
+#define HANDLE_CHUNK_AS_DEFAULT   0
+#define HANDLE_CHUNK_NEVER        1
+#define HANDLE_CHUNK_IF_SAFE      2
+#define HANDLE_CHUNK_ALWAYS       3
+
+#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \
+                                     PNG_FLAG_CRC_ANCILLARY_NOWARN)
+
+#define PNG_FLAG_CRC_CRITICAL_MASK  (PNG_FLAG_CRC_CRITICAL_USE | \
+                                     PNG_FLAG_CRC_CRITICAL_IGNORE)
+
+#define PNG_FLAG_CRC_MASK           (PNG_FLAG_CRC_ANCILLARY_MASK | \
+                                     PNG_FLAG_CRC_CRITICAL_MASK)
+
+/* save typing and make code easier to understand */
+#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
+   abs((int)((c1).green) - (int)((c2).green)) + \
+   abs((int)((c1).blue) - (int)((c2).blue)))
+
+/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */
+#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN)
+/* place to hold the signature string for a PNG file. */
+#ifdef PNG_USE_GLOBAL_ARRAYS
+   PNG_EXPORT_VAR (const png_byte FARDATA) png_sig[8];
+#else
+#define png_sig png_sig_bytes(NULL)
+#endif
+#endif /* PNG_NO_EXTERN */
+
+/* Constant strings for known chunk types.  If you need to add a chunk,
+ * define the name here, and add an invocation of the macro in png.c and
+ * wherever it's needed.
+ */
+#define PNG_IHDR const png_byte png_IHDR[5] = { 73,  72,  68,  82, '\0'}
+#define PNG_IDAT const png_byte png_IDAT[5] = { 73,  68,  65,  84, '\0'}
+#define PNG_IEND const png_byte png_IEND[5] = { 73,  69,  78,  68, '\0'}
+#define PNG_PLTE const png_byte png_PLTE[5] = { 80,  76,  84,  69, '\0'}
+#define PNG_bKGD const png_byte png_bKGD[5] = { 98,  75,  71,  68, '\0'}
+#define PNG_cHRM const png_byte png_cHRM[5] = { 99,  72,  82,  77, '\0'}
+#define PNG_gAMA const png_byte png_gAMA[5] = {103,  65,  77,  65, '\0'}
+#define PNG_hIST const png_byte png_hIST[5] = {104,  73,  83,  84, '\0'}
+#define PNG_iCCP const png_byte png_iCCP[5] = {105,  67,  67,  80, '\0'}
+#define PNG_iTXt const png_byte png_iTXt[5] = {105,  84,  88, 116, '\0'}
+#define PNG_oFFs const png_byte png_oFFs[5] = {111,  70,  70, 115, '\0'}
+#define PNG_pCAL const png_byte png_pCAL[5] = {112,  67,  65,  76, '\0'}
+#define PNG_sCAL const png_byte png_sCAL[5] = {115,  67,  65,  76, '\0'}
+#define PNG_pHYs const png_byte png_pHYs[5] = {112,  72,  89, 115, '\0'}
+#define PNG_sBIT const png_byte png_sBIT[5] = {115,  66,  73,  84, '\0'}
+#define PNG_sPLT const png_byte png_sPLT[5] = {115,  80,  76,  84, '\0'}
+#define PNG_sRGB const png_byte png_sRGB[5] = {115,  82,  71,  66, '\0'}
+#define PNG_tEXt const png_byte png_tEXt[5] = {116,  69,  88, 116, '\0'}
+#define PNG_tIME const png_byte png_tIME[5] = {116,  73,  77,  69, '\0'}
+#define PNG_tRNS const png_byte png_tRNS[5] = {116,  82,  78,  83, '\0'}
+#define PNG_zTXt const png_byte png_zTXt[5] = {122,  84,  88, 116, '\0'}
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+PNG_EXPORT_VAR (const png_byte FARDATA) png_IHDR[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_IDAT[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_IEND[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_PLTE[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_bKGD[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_cHRM[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_gAMA[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_hIST[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_iCCP[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_iTXt[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_oFFs[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_pCAL[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_sCAL[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_pHYs[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_sBIT[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_sPLT[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_sRGB[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_tEXt[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_tIME[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_tRNS[5];
+PNG_EXPORT_VAR (const png_byte FARDATA) png_zTXt[5];
+#endif /* PNG_USE_GLOBAL_ARRAYS */
+
+
+/* Inline macros to do direct reads of bytes from the input buffer.  These
+ * require that you are using an architecture that uses PNG byte ordering
+ * (MSB first) and supports unaligned data storage.  I think that PowerPC
+ * in big-endian mode and 680x0 are the only ones that will support this.
+ * The x86 line of processors definitely do not.  The png_get_int_32()
+ * routine also assumes we are using two's complement format for negative
+ * values, which is almost certainly true.
+ */
+#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED)
+#  if defined(PNG_pCAL_SUPPORTED) || defined(PNG_oFFs_SUPPORTED)
+#    define png_get_int_32(buf) ( *((png_int_32p) (buf)))
+#  endif
+#  define png_get_uint_32(buf) ( *((png_uint_32p) (buf)))
+#  define png_get_uint_16(buf) ( *((png_uint_16p) (buf)))
+#else
+#  if defined(PNG_pCAL_SUPPORTED) || defined(PNG_oFFs_SUPPORTED)
+PNG_EXTERN png_int_32 png_get_int_32 PNGARG((png_bytep buf));
+#  endif
+PNG_EXTERN png_uint_32 png_get_uint_32 PNGARG((png_bytep buf));
+PNG_EXTERN png_uint_16 png_get_uint_16 PNGARG((png_bytep buf));
+#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */
+
+/* Initialize png_ptr struct for reading, and allocate any other memory.
+ * (old interface - DEPRECATED - use png_create_read_struct instead).
+ */
+extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr));
+#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \
+    PNG_LIBPNG_VER_STRING,  sizeof(png_struct));
+extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr,
+    png_const_charp user_png_ver, png_size_t png_struct_size));
+extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr,
+    png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t
+    png_info_size));
+
+/* Initialize png_ptr struct for writing, and allocate any other memory.
+ * (old interface - DEPRECATED - use png_create_write_struct instead).
+ */
+extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr));
+#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \
+    PNG_LIBPNG_VER_STRING, sizeof(png_struct));
+extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr,
+    png_const_charp user_png_ver, png_size_t png_struct_size));
+extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr,
+    png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t
+    png_info_size));
+
+/* Allocate memory for an internal libpng struct */
+PNG_EXTERN png_voidp png_create_struct PNGARG((int type));
+
+/* Free memory from internal libpng struct */
+PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr));
+
+PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr
+  malloc_fn, png_voidp mem_ptr));
+PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr,
+   png_free_ptr free_fn, png_voidp mem_ptr));
+
+/* Free any memory that info_ptr points to and reset struct. */
+PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* Function to allocate memory for zlib. */
+PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size));
+
+/* Function to free memory for zlib */
+PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr));
+
+/* Reset the CRC variable */
+PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr));
+
+/* Write the "data" buffer to whatever output you are using. */
+PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data,
+   png_size_t length));
+
+/* Read data from whatever input you are using into the "data" buffer */
+PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data,
+   png_size_t length));
+
+/* Read bytes into buf, and update png_ptr->crc */
+PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf,
+   png_size_t length));
+
+/* Decompress data in a chunk that uses compression */
+#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \
+    defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
+PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr,
+   int comp_type, png_charp chunkdata, png_size_t chunklength,
+   png_size_t prefix_length, png_size_t *data_length));
+#endif
+
+/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */
+PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip));
+
+/* Read the CRC from the file and compare it to the libpng calculated CRC */
+PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr));
+
+/* Calculate the CRC over a section of data.  Note that we are only
+ * passing a maximum of 64K on systems that have this as a memory limit,
+ * since this is the maximum buffer size we can specify.
+ */
+PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr,
+   png_size_t length));
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+PNG_EXTERN void png_flush PNGARG((png_structp png_ptr));
+#endif
+
+/* Place a 32-bit number into a buffer in PNG byte order (big-endian).
+ * The only currently known PNG chunks that use signed numbers are
+ * the ancillary extension chunks, oFFs and pCAL.
+ */
+PNG_EXTERN void png_save_uint_32 PNGARG((png_bytep buf, png_uint_32 i));
+
+#if defined(PNG_WRITE_pCAL_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED)
+PNG_EXTERN void png_save_int_32 PNGARG((png_bytep buf, png_int_32 i));
+#endif
+
+/* Place a 16-bit number into a buffer in PNG byte order.
+ * The parameter is declared unsigned int, not png_uint_16,
+ * just to avoid potential problems on pre-ANSI C compilers.
+ */
+PNG_EXTERN void png_save_uint_16 PNGARG((png_bytep buf, unsigned int i));
+
+/* simple function to write the signature */
+PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr));
+
+/* write various chunks */
+
+/* Write the IHDR chunk, and update the png_struct with the necessary
+ * information.
+ */
+PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width,
+   png_uint_32 height,
+   int bit_depth, int color_type, int compression_method, int filter_method,
+   int interlace_method));
+
+PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette,
+   png_uint_32 num_pal));
+
+PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data,
+   png_size_t length));
+
+PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr));
+
+#if defined(PNG_WRITE_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma));
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point
+    file_gamma));
+#endif
+#endif
+
+#if defined(PNG_WRITE_sBIT_SUPPORTED)
+PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit,
+   int color_type));
+#endif
+
+#if defined(PNG_WRITE_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr,
+   double white_x, double white_y,
+   double red_x, double red_y, double green_x, double green_y,
+   double blue_x, double blue_y));
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr,
+   png_fixed_point int_white_x, png_fixed_point int_white_y,
+   png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
+   int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
+   png_fixed_point int_blue_y));
+#endif
+#endif
+
+#if defined(PNG_WRITE_sRGB_SUPPORTED)
+PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr,
+   int intent));
+#endif
+
+#if defined(PNG_WRITE_iCCP_SUPPORTED)
+PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr,
+   png_charp name, int compression_type,
+   png_charp profile, int proflen));
+   /* Note to maintainer: profile should be png_bytep */
+#endif
+
+#if defined(PNG_WRITE_sPLT_SUPPORTED)
+PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr,
+   png_sPLT_tp palette));
+#endif
+
+#if defined(PNG_WRITE_tRNS_SUPPORTED)
+PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans,
+   png_color_16p values, int number, int color_type));
+#endif
+
+#if defined(PNG_WRITE_bKGD_SUPPORTED)
+PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr,
+   png_color_16p values, int color_type));
+#endif
+
+#if defined(PNG_WRITE_hIST_SUPPORTED)
+PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist,
+   int num_hist));
+#endif
+
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
+    defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
+PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr,
+   png_charp key, png_charpp new_key));
+#endif
+
+#if defined(PNG_WRITE_tEXt_SUPPORTED)
+PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key,
+   png_charp text, png_size_t text_len));
+#endif
+
+#if defined(PNG_WRITE_zTXt_SUPPORTED)
+PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key,
+   png_charp text, png_size_t text_len, int compression));
+#endif
+
+#if defined(PNG_WRITE_iTXt_SUPPORTED)
+PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr,
+   int compression, png_charp key, png_charp lang, png_charp lang_key,
+   png_charp text));
+#endif
+
+#if defined(PNG_WRITE_oFFs_SUPPORTED)
+PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr,
+   png_int_32 x_offset, png_int_32 y_offset, int unit_type));
+#endif
+
+#if defined(PNG_WRITE_pCAL_SUPPORTED)
+PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose,
+   png_int_32 X0, png_int_32 X1, int type, int nparams,
+   png_charp units, png_charpp params));
+#endif
+
+#if defined(PNG_WRITE_pHYs_SUPPORTED)
+PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr,
+   png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit,
+   int unit_type));
+#endif
+
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr,
+   png_timep mod_time));
+#endif
+
+#if defined(PNG_WRITE_sCAL_SUPPORTED)
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
+PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr,
+   int unit, double width, double height));
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr,
+   int unit, png_charp width, png_charp height));
+#endif
+#endif
+#endif
+
+/* Called when finished processing a row of data */
+PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr));
+
+/* Internal use only.   Called before first row of data */
+PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr));
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr));
+#endif
+
+/* combine a row of data, dealing with alpha, etc. if requested */
+PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row,
+   int mask));
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+/* expand an interlaced row */
+/* OLD pre-1.0.9 interface:
+PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info,
+   png_bytep row, int pass, png_uint_32 transformations));
+ */
+PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr));
+#endif
+
+/* GRR TO DO (2.0 or whenever):  simplify other internal calling interfaces */
+
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+/* grab pixels out of a row for an interlaced pass */
+PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info,
+   png_bytep row, int pass));
+#endif
+
+/* unfilter a row */
+PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr,
+   png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter));
+
+/* Choose the best filter to use and filter the row data */
+PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr,
+   png_row_infop row_info));
+
+/* Write out the filtered row. */
+PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr,
+   png_bytep filtered_row));
+/* finish a row while reading, dealing with interlacing passes, etc. */
+PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr));
+
+/* initialize the row buffers, etc. */
+PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr));
+/* optional call to update the users info structure */
+PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+
+/* these are the functions that do the transformations */
+#if defined(PNG_READ_FILLER_SUPPORTED)
+PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info,
+   png_bytep row, png_uint_32 filler, png_uint_32 flags));
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
+    defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info,
+   png_bytep row, png_uint_32 flags));
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop
+   row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED)
+PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row,
+   png_color_8p sig_bits));
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
+PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info,
+   png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup));
+
+#  if defined(PNG_CORRECT_PALETTE_SUPPORTED)
+PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr,
+   png_colorp palette, int num_palette));
+#  endif
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row));
+#endif
+
+#if defined(PNG_WRITE_PACK_SUPPORTED)
+PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info,
+   png_bytep row, png_uint_32 bit_depth));
+#endif
+
+#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row,
+   png_color_8p bit_depth));
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row,
+   png_color_16p trans_values, png_color_16p background,
+   png_color_16p background_1,
+   png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
+   png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
+   png_uint_16pp gamma_16_to_1, int gamma_shift));
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row,
+   png_bytep gamma_table, png_uint_16pp gamma_16_table,
+   int gamma_shift));
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info,
+   png_bytep row, png_colorp palette, png_bytep trans, int num_trans));
+PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info,
+   png_bytep row, png_color_16p trans_value));
+#endif
+
+/* The following decodes the appropriate chunks, and does error correction,
+ * then calls the appropriate callback for the chunk if it is valid.
+ */
+
+/* decode the IHDR chunk */
+PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+
+#if defined(PNG_READ_bKGD_SUPPORTED)
+PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_cHRM_SUPPORTED)
+PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_gAMA_SUPPORTED)
+PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_hIST_SUPPORTED)
+PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_iCCP_SUPPORTED)
+extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif /* PNG_READ_iCCP_SUPPORTED */
+
+#if defined(PNG_READ_iTXt_SUPPORTED)
+PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_oFFs_SUPPORTED)
+PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_pCAL_SUPPORTED)
+PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_pHYs_SUPPORTED)
+PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_sBIT_SUPPORTED)
+PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_sCAL_SUPPORTED)
+PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_sPLT_SUPPORTED)
+extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif /* PNG_READ_sPLT_SUPPORTED */
+
+#if defined(PNG_READ_sRGB_SUPPORTED)
+PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_tEXt_SUPPORTED)
+PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_tIME_SUPPORTED)
+PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_tRNS_SUPPORTED)
+PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#if defined(PNG_READ_zTXt_SUPPORTED)
+PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 length));
+#endif
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+PNG_EXTERN int png_handle_as_unknown PNGARG((png_structp png_ptr, png_bytep
+   chunk_name));
+#endif
+
+PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 length));
+
+PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr,
+   png_bytep chunk_name));
+
+/* handle the transformations for reading and writing */
+PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr));
+
+PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr));
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr,
+   png_uint_32 length));
+PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr,
+   png_bytep buffer, png_size_t length));
+PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr,
+   png_bytep buffer, png_size_t buffer_length));
+PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr,
+   png_bytep buffer, png_size_t buffer_length));
+PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr));
+PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 length));
+PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row));
+PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr));
+#if defined(PNG_READ_tEXt_SUPPORTED)
+PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 length));
+PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 length));
+PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr, png_uint_32 length));
+PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr,
+   png_infop info_ptr));
+#endif
+
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info,
+   png_bytep row));
+PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info,
+   png_bytep row));
+#endif
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+/* png.c */ /* PRIVATE */
+PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr));
+#endif
+/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
+
+#endif /* PNG_INTERNAL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PNG_VERSION_INFO_ONLY */
+/* do not put anything past this line */
+#endif /* PNG_H */
diff --git a/libraries/libpng-1.2.0/pngasmrd.h b/libraries/libpng-1.2.0/pngasmrd.h
new file mode 100644 (file)
index 0000000..420f5fe
--- /dev/null
@@ -0,0 +1,11 @@
+/* pngasmrd.h - assembler version of utilities to read a PNG file
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 2001 Glenn Randers-Pehrson
+ *
+ */
+
+/* This file is obsolete in libpng-1.0.9 and later; its contents now appear
+ * at the end of pngconf.h.
+ */
diff --git a/libraries/libpng-1.2.0/pngbar.jpg b/libraries/libpng-1.2.0/pngbar.jpg
new file mode 100644 (file)
index 0000000..e4dcbfd
Binary files /dev/null and b/libraries/libpng-1.2.0/pngbar.jpg differ
diff --git a/libraries/libpng-1.2.0/pngbar.png b/libraries/libpng-1.2.0/pngbar.png
new file mode 100644 (file)
index 0000000..d3f7221
Binary files /dev/null and b/libraries/libpng-1.2.0/pngbar.png differ
diff --git a/libraries/libpng-1.2.0/pngconf.h b/libraries/libpng-1.2.0/pngconf.h
new file mode 100644 (file)
index 0000000..18d6f65
--- /dev/null
@@ -0,0 +1,1322 @@
+/* pngconf.h - machine configurable file for libpng
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+/* Any machine specific code is near the front of this file, so if you
+ * are configuring libpng for a machine, you may want to read the section
+ * starting here down to where it starts to typedef png_color, png_text,
+ * and png_info.
+ */
+
+#ifndef PNGCONF_H
+#define PNGCONF_H
+
+/* This is the size of the compression buffer, and thus the size of
+ * an IDAT chunk.  Make this whatever size you feel is best for your
+ * machine.  One of these will be allocated per png_struct.  When this
+ * is full, it writes the data to the disk, and does some other
+ * calculations.  Making this an extremely small size will slow
+ * the library down, but you may want to experiment to determine
+ * where it becomes significant, if you are concerned with memory
+ * usage.  Note that zlib allocates at least 32Kb also.  For readers,
+ * this describes the size of the buffer available to read the data in.
+ * Unless this gets smaller than the size of a row (compressed),
+ * it should not make much difference how big this is.
+ */
+
+#ifndef PNG_ZBUF_SIZE
+#  define PNG_ZBUF_SIZE 8192
+#endif
+
+/* Enable if you want a write-only libpng */
+
+#ifndef PNG_NO_READ_SUPPORTED
+#  define PNG_READ_SUPPORTED
+#endif
+
+/* Enable if you want a read-only libpng */
+
+#ifndef PNG_NO_WRITE_SUPPORTED
+#  define PNG_WRITE_SUPPORTED
+#endif
+
+/* Enabled by default in 1.2.0.  You can disable this if you don't need to
+   support PNGs that are embedded in MNG datastreams */
+#ifndef PNG_NO_MNG_FEATURES
+#  ifndef PNG_MNG_FEATURES_SUPPORTED
+#    define PNG_MNG_FEATURES_SUPPORTED
+#  endif
+#endif
+
+#ifndef PNG_NO_FLOATING_POINT_SUPPORTED
+#  ifndef PNG_FLOATING_POINT_SUPPORTED
+#    define PNG_FLOATING_POINT_SUPPORTED
+#  endif
+#endif
+
+/* If you are running on a machine where you cannot allocate more
+ * than 64K of memory at once, uncomment this.  While libpng will not
+ * normally need that much memory in a chunk (unless you load up a very
+ * large file), zlib needs to know how big of a chunk it can use, and
+ * libpng thus makes sure to check any memory allocation to verify it
+ * will fit into memory.
+#define PNG_MAX_MALLOC_64K
+ */
+#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
+#  define PNG_MAX_MALLOC_64K
+#endif
+
+/* Special munging to support doing things the 'cygwin' way:
+ * 'Normal' png-on-win32 defines/defaults:
+ *   PNG_BUILD_DLL -- building dll
+ *   PNG_USE_DLL   -- building an application, linking to dll
+ *   (no define)   -- building static library, or building an
+ *                    application and linking to the static lib
+ * 'Cygwin' defines/defaults:
+ *   PNG_BUILD_DLL -- building the dll
+ *   (no define)   -- building an application, linking to the dll
+ *   PNG_STATIC    -- building the static lib, or building an application
+ *                    that links to the static lib.
+ *   ALL_STATIC    -- building various static libs, or building an application
+ *                    that links to the static libs.
+ * Thus,
+ * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and
+ * this bit of #ifdefs will define the 'correct' config variables based on
+ * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but
+ * unnecessary.
+ *
+ * Also, the precedence order is:
+ *   ALL_STATIC (since we can't #undef something outside our namespace)
+ *   PNG_BUILD_DLL
+ *   PNG_STATIC
+ *   (nothing) == PNG_USE_DLL 
+ */
+#if defined(__CYGWIN__)
+#  if defined(ALL_STATIC)
+#    if defined(PNG_BUILD_DLL)
+#      undef PNG_BUILD_DLL
+#    endif
+#    if defined(PNG_USE_DLL)
+#      undef PNG_USE_DLL
+#    endif
+#    if defined(PNG_DLL)
+#      undef PNG_DLL
+#    endif
+#    if !defined(PNG_STATIC)
+#      define PNG_STATIC
+#    endif
+#  else
+#    if defined (PNG_BUILD_DLL)
+#      if defined(PNG_STATIC)
+#        undef PNG_STATIC
+#      endif
+#      if defined(PNG_USE_DLL)
+#        undef PNG_USE_DLL
+#      endif
+#      if !defined(PNG_DLL)
+#        define PNG_DLL
+#      endif
+#    else
+#      if defined(PNG_STATIC)
+#        if defined(PNG_USE_DLL)
+#          undef PNG_USE_DLL
+#        endif
+#        if defined(PNG_DLL)
+#          undef PNG_DLL
+#        endif
+#      else
+#        if !defined(PNG_USE_DLL)
+#          define PNG_USE_DLL
+#        endif
+#        if !defined(PNG_DLL)
+#          define PNG_DLL
+#        endif
+#      endif  
+#    endif  
+#  endif
+#endif
+
+/* This protects us against compilers that run on a windowing system
+ * and thus don't have or would rather us not use the stdio types:
+ * stdin, stdout, and stderr.  The only one currently used is stderr
+ * in png_error() and png_warning().  #defining PNG_NO_CONSOLE_IO will
+ * prevent these from being compiled and used. #defining PNG_NO_STDIO
+ * will also prevent these, plus will prevent the entire set of stdio
+ * macros and functions (FILE *, printf, etc.) from being compiled and used,
+ * unless (PNG_DEBUG > 0) has been #defined.
+ *
+ * #define PNG_NO_CONSOLE_IO
+ * #define PNG_NO_STDIO
+ */
+
+#if defined(_WIN32_WCE)
+#  include <windows.h>
+   /* Console I/O functions are not supported on WindowsCE */
+#  define PNG_NO_CONSOLE_IO
+#  ifdef PNG_DEBUG
+#    undef PNG_DEBUG
+#  endif
+#endif
+
+#ifdef PNG_BUILD_DLL
+#  ifndef PNG_CONSOLE_IO_SUPPORTED
+#    ifndef PNG_NO_CONSOLE_IO
+#      define PNG_NO_CONSOLE_IO
+#    endif
+#  endif
+#endif
+
+#  ifdef PNG_NO_STDIO
+#    ifndef PNG_NO_CONSOLE_IO
+#      define PNG_NO_CONSOLE_IO
+#    endif
+#    ifdef PNG_DEBUG
+#      if (PNG_DEBUG > 0)
+#        include <stdio.h>
+#      endif
+#    endif
+#  else
+#    if !defined(_WIN32_WCE)
+/* "stdio.h" functions are not supported on WindowsCE */
+#      include <stdio.h>
+#    endif
+#  endif
+
+/* This macro protects us against machines that don't have function
+ * prototypes (ie K&R style headers).  If your compiler does not handle
+ * function prototypes, define this macro and use the included ansi2knr.
+ * I've always been able to use _NO_PROTO as the indicator, but you may
+ * need to drag the empty declaration out in front of here, or change the
+ * ifdef to suit your own needs.
+ */
+#ifndef PNGARG
+
+#ifdef OF /* zlib prototype munger */
+#  define PNGARG(arglist) OF(arglist)
+#else
+
+#ifdef _NO_PROTO
+#  define PNGARG(arglist) ()
+#else
+#  define PNGARG(arglist) arglist
+#endif /* _NO_PROTO */
+
+#endif /* OF */
+
+#endif /* PNGARG */
+
+/* Try to determine if we are compiling on a Mac.  Note that testing for
+ * just __MWERKS__ is not good enough, because the Codewarrior is now used
+ * on non-Mac platforms.
+ */
+#ifndef MACOS
+#  if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \
+      defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC)
+#    define MACOS
+#  endif
+#endif
+
+/* enough people need this for various reasons to include it here */
+#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE)
+#  include <sys/types.h>
+#endif
+
+#if !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED)
+#  define PNG_SETJMP_SUPPORTED
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+/* This is an attempt to force a single setjmp behaviour on Linux.  If
+ * the X config stuff didn't define _BSD_SOURCE we wouldn't need this.
+ */
+
+#  ifdef __linux__
+#    ifdef _BSD_SOURCE
+#      define PNG_SAVE_BSD_SOURCE
+#      undef _BSD_SOURCE
+#    endif
+#    ifdef _SETJMP_H
+      __png.h__ already includes setjmp.h;
+      __dont__ include it again.;
+#    endif
+#  endif /* __linux__ */
+
+   /* include setjmp.h for error handling */
+#  include <setjmp.h>
+
+#  ifdef __linux__
+#    ifdef PNG_SAVE_BSD_SOURCE
+#      define _BSD_SOURCE
+#      undef PNG_SAVE_BSD_SOURCE
+#    endif
+#  endif /* __linux__ */
+#endif /* PNG_SETJMP_SUPPORTED */
+
+#ifdef BSD
+#  include <strings.h>
+#else
+#  include <string.h>
+#endif
+
+/* Other defines for things like memory and the like can go here.  */
+#ifdef PNG_INTERNAL
+
+#include <stdlib.h>
+
+/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which
+ * aren't usually used outside the library (as far as I know), so it is
+ * debatable if they should be exported at all.  In the future, when it is
+ * possible to have run-time registry of chunk-handling functions, some of
+ * these will be made available again.
+#define PNG_EXTERN extern
+ */
+#define PNG_EXTERN
+
+/* Other defines specific to compilers can go here.  Try to keep
+ * them inside an appropriate ifdef/endif pair for portability.
+ */
+
+#if defined(PNG_FLOATING_POINT_SUPPORTED)
+#  if defined(MACOS)
+     /* We need to check that <math.h> hasn't already been included earlier
+      * as it seems it doesn't agree with <fp.h>, yet we should really use
+      * <fp.h> if possible.
+      */
+#    if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__)
+#      include <fp.h>
+#    endif
+#  else
+#    include <math.h>
+#  endif
+#  if defined(_AMIGA) && defined(__SASC) && defined(_M68881)
+     /* Amiga SAS/C: We must include builtin FPU functions when compiling using
+      * MATH=68881
+      */
+#    include <m68881.h>
+#  endif
+#endif
+
+/* Codewarrior on NT has linking problems without this. */
+#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__)
+#  define PNG_ALWAYS_EXTERN
+#endif
+
+/* For some reason, Borland C++ defines memcmp, etc. in mem.h, not
+ * stdlib.h like it should (I think).  Or perhaps this is a C++
+ * "feature"?
+ */
+#ifdef __TURBOC__
+#  include <mem.h>
+#  include "alloc.h"
+#endif
+
+#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \
+    defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__))
+#  include <malloc.h>
+#endif
+
+/* This controls how fine the dithering gets.  As this allocates
+ * a largish chunk of memory (32K), those who are not as concerned
+ * with dithering quality can decrease some or all of these.
+ */
+#ifndef PNG_DITHER_RED_BITS
+#  define PNG_DITHER_RED_BITS 5
+#endif
+#ifndef PNG_DITHER_GREEN_BITS
+#  define PNG_DITHER_GREEN_BITS 5
+#endif
+#ifndef PNG_DITHER_BLUE_BITS
+#  define PNG_DITHER_BLUE_BITS 5
+#endif
+
+/* This controls how fine the gamma correction becomes when you
+ * are only interested in 8 bits anyway.  Increasing this value
+ * results in more memory being used, and more pow() functions
+ * being called to fill in the gamma tables.  Don't set this value
+ * less then 8, and even that may not work (I haven't tested it).
+ */
+
+#ifndef PNG_MAX_GAMMA_8
+#  define PNG_MAX_GAMMA_8 11
+#endif
+
+/* This controls how much a difference in gamma we can tolerate before
+ * we actually start doing gamma conversion.
+ */
+#ifndef PNG_GAMMA_THRESHOLD
+#  define PNG_GAMMA_THRESHOLD 0.05
+#endif
+
+#endif /* PNG_INTERNAL */
+
+/* The following uses const char * instead of char * for error
+ * and warning message functions, so some compilers won't complain.
+ * If you do not want to use const, define PNG_NO_CONST here.
+ */
+
+#ifndef PNG_NO_CONST
+#  define PNG_CONST const
+#else
+#  define PNG_CONST
+#endif
+
+/* The following defines give you the ability to remove code from the
+ * library that you will not be using.  I wish I could figure out how to
+ * automate this, but I can't do that without making it seriously hard
+ * on the users.  So if you are not using an ability, change the #define
+ * to and #undef, and that part of the library will not be compiled.  If
+ * your linker can't find a function, you may want to make sure the
+ * ability is defined here.  Some of these depend upon some others being
+ * defined.  I haven't figured out all the interactions here, so you may
+ * have to experiment awhile to get everything to compile.  If you are
+ * creating or using a shared library, you probably shouldn't touch this,
+ * as it will affect the size of the structures, and this will cause bad
+ * things to happen if the library and/or application ever change.
+ */
+
+/* Any features you will not be using can be undef'ed here */
+
+/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user
+ * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS
+ * on the compile line, then pick and choose which ones to define without
+ * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED
+ * if you only want to have a png-compliant reader/writer but don't need
+ * any of the extra transformations.  This saves about 80 kbytes in a
+ * typical installation of the library. (PNG_NO_* form added in version
+ * 1.0.1c, for consistency)
+ */
+
+/* The size of the png_text structure changed in libpng-1.0.6 when
+ * iTXt is supported.  It is turned off by default, to support old apps
+ * that malloc the png_text structure instead of calling png_set_text()
+ * and letting libpng malloc it.  It will be turned on by default in
+ * libpng-1.3.0.
+ */
+
+#ifndef PNG_iTXt_SUPPORTED
+#  ifndef PNG_READ_iTXt_SUPPORTED
+#    define PNG_NO_READ_iTXt
+#  endif
+#  ifndef PNG_WRITE_iTXt_SUPPORTED
+#    define PNG_NO_WRITE_iTXt
+#  endif
+#endif
+
+/* The following support, added after version 1.0.0, can be turned off here en
+ * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility
+ * with old applications that require the length of png_struct and png_info
+ * to remain unchanged.
+ */
+
+#ifdef PNG_LEGACY_SUPPORTED
+#  define PNG_NO_FREE_ME
+#  define PNG_NO_READ_UNKNOWN_CHUNKS
+#  define PNG_NO_WRITE_UNKNOWN_CHUNKS
+#  define PNG_NO_READ_USER_CHUNKS
+#  define PNG_NO_READ_iCCP
+#  define PNG_NO_WRITE_iCCP
+#  define PNG_NO_READ_iTXt
+#  define PNG_NO_WRITE_iTXt
+#  define PNG_NO_READ_sCAL
+#  define PNG_NO_WRITE_sCAL
+#  define PNG_NO_READ_sPLT
+#  define PNG_NO_WRITE_sPLT
+#  define PNG_NO_INFO_IMAGE
+#  define PNG_NO_READ_RGB_TO_GRAY
+#  define PNG_NO_READ_USER_TRANSFORM
+#  define PNG_NO_WRITE_USER_TRANSFORM
+#  define PNG_NO_USER_MEM
+#  define PNG_NO_READ_EMPTY_PLTE
+#  define PNG_NO_MNG_FEATURES
+#  define PNG_NO_FIXED_POINT_SUPPORTED
+#endif
+
+/* Ignore attempt to turn off both floating and fixed point support */
+#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \
+    !defined(PNG_NO_FIXED_POINT_SUPPORTED)
+#  define PNG_FIXED_POINT_SUPPORTED
+#endif
+
+#ifndef PNG_NO_FREE_ME
+#  define PNG_FREE_ME_SUPPORTED
+#endif
+
+#if defined(PNG_READ_SUPPORTED)
+
+#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \
+      !defined(PNG_NO_READ_TRANSFORMS)
+#  define PNG_READ_TRANSFORMS_SUPPORTED
+#endif
+
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
+#  ifndef PNG_NO_READ_EXPAND
+#    define PNG_READ_EXPAND_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_SHIFT
+#    define PNG_READ_SHIFT_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_PACK
+#    define PNG_READ_PACK_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_BGR
+#    define PNG_READ_BGR_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_SWAP
+#    define PNG_READ_SWAP_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_PACKSWAP
+#    define PNG_READ_PACKSWAP_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_INVERT
+#    define PNG_READ_INVERT_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_DITHER
+#    define PNG_READ_DITHER_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_BACKGROUND
+#    define PNG_READ_BACKGROUND_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_16_TO_8
+#    define PNG_READ_16_TO_8_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_FILLER
+#    define PNG_READ_FILLER_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_GAMMA
+#    define PNG_READ_GAMMA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_GRAY_TO_RGB
+#    define PNG_READ_GRAY_TO_RGB_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_SWAP_ALPHA
+#    define PNG_READ_SWAP_ALPHA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_INVERT_ALPHA
+#    define PNG_READ_INVERT_ALPHA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_STRIP_ALPHA
+#    define PNG_READ_STRIP_ALPHA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_USER_TRANSFORM
+#    define PNG_READ_USER_TRANSFORM_SUPPORTED
+#  endif
+#  ifndef PNG_NO_READ_RGB_TO_GRAY
+#    define PNG_READ_RGB_TO_GRAY_SUPPORTED
+#  endif
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
+
+#if !defined(PNG_NO_PROGRESSIVE_READ) && \
+ !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED)  /* if you don't do progressive */
+#  define PNG_PROGRESSIVE_READ_SUPPORTED     /* reading.  This is not talking */
+#endif                               /* about interlacing capability!  You'll */
+              /* still have interlacing unless you change the following line: */
+
+#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */
+
+#ifndef PNG_NO_READ_COMPOSITE_NODIV
+#  ifndef PNG_NO_READ_COMPOSITED_NODIV  /* libpng-1.0.x misspelling */
+#    define PNG_READ_COMPOSITE_NODIV_SUPPORTED   /* well tested on Intel, SGI */
+#  endif
+#endif
+
+/* Deprecated, will be removed from version 2.0.0.
+   Use PNG_MNG_FEATURES_SUPPORTED instead. */
+#ifndef PNG_NO_READ_EMPTY_PLTE
+#  define PNG_READ_EMPTY_PLTE_SUPPORTED
+#endif
+
+#endif /* PNG_READ_SUPPORTED */
+
+#if defined(PNG_WRITE_SUPPORTED)
+
+# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \
+    !defined(PNG_NO_WRITE_TRANSFORMS)
+#  define PNG_WRITE_TRANSFORMS_SUPPORTED
+#endif
+
+#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
+#  ifndef PNG_NO_WRITE_SHIFT
+#    define PNG_WRITE_SHIFT_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_PACK
+#    define PNG_WRITE_PACK_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_BGR
+#    define PNG_WRITE_BGR_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_SWAP
+#    define PNG_WRITE_SWAP_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_PACKSWAP
+#    define PNG_WRITE_PACKSWAP_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_INVERT
+#    define PNG_WRITE_INVERT_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_FILLER
+#    define PNG_WRITE_FILLER_SUPPORTED   /* same as WRITE_STRIP_ALPHA */
+#  endif
+#  ifndef PNG_NO_WRITE_SWAP_ALPHA
+#    define PNG_WRITE_SWAP_ALPHA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_INVERT_ALPHA
+#    define PNG_WRITE_INVERT_ALPHA_SUPPORTED
+#  endif
+#  ifndef PNG_NO_WRITE_USER_TRANSFORM
+#    define PNG_WRITE_USER_TRANSFORM_SUPPORTED
+#  endif
+#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+#  ifndef PNG_NO_USER_TRANSFORM_PTR
+#    define PNG_USER_TRANSFORM_PTR_SUPPORTED
+#  endif
+#endif
+
+#define PNG_WRITE_INTERLACING_SUPPORTED  /* not required for PNG-compliant
+                                            encoders, but can cause trouble
+                                            if left undefined */
+
+#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \
+     defined(PNG_FLOATING_POINT_SUPPORTED)
+#  define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+#endif
+
+#ifndef PNG_NO_ERROR_NUMBERS
+#define PNG_ERROR_NUMBERS_SUPPORTED
+#endif
+
+#ifndef PNG_NO_WRITE_FLUSH
+#  define PNG_WRITE_FLUSH_SUPPORTED
+#endif
+
+/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */
+#ifndef PNG_NO_WRITE_EMPTY_PLTE
+#  define PNG_WRITE_EMPTY_PLTE_SUPPORTED
+#endif
+
+#endif /* PNG_WRITE_SUPPORTED */
+
+#ifndef PNG_NO_STDIO
+#  define PNG_TIME_RFC1123_SUPPORTED
+#endif
+
+/* This adds extra functions in pngget.c for accessing data from the
+ * info pointer (added in version 0.99)
+ * png_get_image_width()
+ * png_get_image_height()
+ * png_get_bit_depth()
+ * png_get_color_type()
+ * png_get_compression_type()
+ * png_get_filter_type()
+ * png_get_interlace_type()
+ * png_get_pixel_aspect_ratio()
+ * png_get_pixels_per_meter()
+ * png_get_x_offset_pixels()
+ * png_get_y_offset_pixels()
+ * png_get_x_offset_microns()
+ * png_get_y_offset_microns()
+ */
+#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED)
+#  define PNG_EASY_ACCESS_SUPPORTED
+#endif
+
+/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 
+   even when PNG_USE_PNGVCRD or PNG_USE_PNGGCCRD is not defined */
+#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE)
+#  ifndef PNG_ASSEMBLER_CODE_SUPPORTED
+#    define PNG_ASSEMBLER_CODE_SUPPORTED
+#  endif
+#  if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE)
+#    define PNG_MMX_CODE_SUPPORTED
+#  endif
+#endif
+
+/* If you are sure that you don't need thread safety and you are compiling
+   with PNG_USE_PNGCCRD for an MMX application, you can define this for
+   faster execution.  See pnggccrd.c.
+#define PNG_THREAD_UNSAFE_OK
+*/
+
+#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED)
+#  define PNG_USER_MEM_SUPPORTED
+#endif
+
+/* These are currently experimental features, define them if you want */
+
+/* very little testing */
+/*
+#ifdef PNG_READ_SUPPORTED
+#  ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+#    define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+#  endif
+#endif
+*/
+
+/* This is only for PowerPC big-endian and 680x0 systems */
+/* some testing */
+/*
+#ifdef PNG_READ_SUPPORTED
+#  ifndef PNG_PNG_READ_BIG_ENDIAN_SUPPORTED
+#    define PNG_READ_BIG_ENDIAN_SUPPORTED
+#  endif
+#endif
+*/
+
+/* Buggy compilers (e.g., gcc 2.7.2.2) need this */
+/*
+#define PNG_NO_POINTER_INDEXING
+*/
+
+/* These functions are turned off by default, as they will be phased out. */
+/*
+#define  PNG_USELESS_TESTS_SUPPORTED
+#define  PNG_CORRECT_PALETTE_SUPPORTED
+*/
+
+/* Any chunks you are not interested in, you can undef here.  The
+ * ones that allocate memory may be expecially important (hIST,
+ * tEXt, zTXt, tRNS, pCAL).  Others will just save time and make png_info
+ * a bit smaller.
+ */
+
+#if defined(PNG_READ_SUPPORTED) && \
+    !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \
+    !defined(PNG_NO_READ_ANCILLARY_CHUNKS)
+#  define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
+#endif
+
+#if defined(PNG_WRITE_SUPPORTED) && \
+    !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \
+    !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS)
+#  define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
+#endif
+
+#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
+
+#ifdef PNG_NO_READ_TEXT
+#  define PNG_NO_READ_iTXt
+#  define PNG_NO_READ_tEXt
+#  define PNG_NO_READ_zTXt
+#endif
+#ifndef PNG_NO_READ_bKGD
+#  define PNG_READ_bKGD_SUPPORTED
+#  define PNG_bKGD_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_cHRM
+#  define PNG_READ_cHRM_SUPPORTED
+#  define PNG_cHRM_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_gAMA
+#  define PNG_READ_gAMA_SUPPORTED
+#  define PNG_gAMA_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_hIST
+#  define PNG_READ_hIST_SUPPORTED
+#  define PNG_hIST_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_iCCP
+#  define PNG_READ_iCCP_SUPPORTED
+#  define PNG_iCCP_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_iTXt
+#  define PNG_READ_iTXt_SUPPORTED
+#  define PNG_iTXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_oFFs
+#  define PNG_READ_oFFs_SUPPORTED
+#  define PNG_oFFs_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_pCAL
+#  define PNG_READ_pCAL_SUPPORTED
+#  define PNG_pCAL_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sCAL
+#  define PNG_READ_sCAL_SUPPORTED
+#  define PNG_sCAL_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_pHYs
+#  define PNG_READ_pHYs_SUPPORTED
+#  define PNG_pHYs_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sBIT
+#  define PNG_READ_sBIT_SUPPORTED
+#  define PNG_sBIT_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sPLT
+#  define PNG_READ_sPLT_SUPPORTED
+#  define PNG_sPLT_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sRGB
+#  define PNG_READ_sRGB_SUPPORTED
+#  define PNG_sRGB_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tEXt
+#  define PNG_READ_tEXt_SUPPORTED
+#  define PNG_tEXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tIME
+#  define PNG_READ_tIME_SUPPORTED
+#  define PNG_tIME_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tRNS
+#  define PNG_READ_tRNS_SUPPORTED
+#  define PNG_tRNS_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_zTXt
+#  define PNG_READ_zTXt_SUPPORTED
+#  define PNG_zTXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_UNKNOWN_CHUNKS
+#  define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+#  ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
+#    define PNG_UNKNOWN_CHUNKS_SUPPORTED
+#  endif
+#  ifndef PNG_NO_HANDLE_AS_UNKNOWN
+#    define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#  endif
+#endif
+#if !defined(PNG_NO_READ_USER_CHUNKS) && \
+     defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+#  define PNG_READ_USER_CHUNKS_SUPPORTED
+#  define PNG_USER_CHUNKS_SUPPORTED
+#  ifdef PNG_NO_READ_UNKNOWN_CHUNKS
+#    undef PNG_NO_READ_UNKNOWN_CHUNKS
+#  endif
+#  ifdef PNG_NO_HANDLE_AS_UNKNOWN
+#    undef PNG_NO_HANDLE_AS_UNKNOWN
+#  endif
+#endif
+#ifndef PNG_NO_READ_OPT_PLTE
+#  define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */
+#endif                      /* optional PLTE chunk in RGB and RGBA images */
+#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \
+    defined(PNG_READ_zTXt_SUPPORTED)
+#  define PNG_READ_TEXT_SUPPORTED
+#  define PNG_TEXT_SUPPORTED
+#endif
+
+#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */
+
+#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
+
+#ifdef PNG_NO_WRITE_TEXT
+#  define PNG_NO_WRITE_iTXt
+#  define PNG_NO_WRITE_tEXt
+#  define PNG_NO_WRITE_zTXt
+#endif
+#ifndef PNG_NO_WRITE_bKGD
+#  define PNG_WRITE_bKGD_SUPPORTED
+#  ifndef PNG_bKGD_SUPPORTED
+#    define PNG_bKGD_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_cHRM
+#  define PNG_WRITE_cHRM_SUPPORTED
+#  ifndef PNG_cHRM_SUPPORTED
+#    define PNG_cHRM_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_gAMA
+#  define PNG_WRITE_gAMA_SUPPORTED
+#  ifndef PNG_gAMA_SUPPORTED
+#    define PNG_gAMA_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_hIST
+#  define PNG_WRITE_hIST_SUPPORTED
+#  ifndef PNG_hIST_SUPPORTED
+#    define PNG_hIST_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_iCCP
+#  define PNG_WRITE_iCCP_SUPPORTED
+#  ifndef PNG_iCCP_SUPPORTED
+#    define PNG_iCCP_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_iTXt
+#  define PNG_WRITE_iTXt_SUPPORTED
+#  ifndef PNG_iTXt_SUPPORTED
+#    define PNG_iTXt_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_oFFs
+#  define PNG_WRITE_oFFs_SUPPORTED
+#  ifndef PNG_oFFs_SUPPORTED
+#    define PNG_oFFs_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_pCAL
+#  define PNG_WRITE_pCAL_SUPPORTED
+#  ifndef PNG_pCAL_SUPPORTED
+#    define PNG_pCAL_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_sCAL
+#  define PNG_WRITE_sCAL_SUPPORTED
+#  ifndef PNG_sCAL_SUPPORTED
+#    define PNG_sCAL_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_pHYs
+#  define PNG_WRITE_pHYs_SUPPORTED
+#  ifndef PNG_pHYs_SUPPORTED
+#    define PNG_pHYs_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_sBIT
+#  define PNG_WRITE_sBIT_SUPPORTED
+#  ifndef PNG_sBIT_SUPPORTED
+#    define PNG_sBIT_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_sPLT
+#  define PNG_WRITE_sPLT_SUPPORTED
+#  ifndef PNG_sPLT_SUPPORTED
+#    define PNG_sPLT_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_sRGB
+#  define PNG_WRITE_sRGB_SUPPORTED
+#  ifndef PNG_sRGB_SUPPORTED
+#    define PNG_sRGB_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_tEXt
+#  define PNG_WRITE_tEXt_SUPPORTED
+#  ifndef PNG_tEXt_SUPPORTED
+#    define PNG_tEXt_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_tIME
+#  define PNG_WRITE_tIME_SUPPORTED
+#  ifndef PNG_tIME_SUPPORTED
+#    define PNG_tIME_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_tRNS
+#  define PNG_WRITE_tRNS_SUPPORTED
+#  ifndef PNG_tRNS_SUPPORTED
+#    define PNG_tRNS_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_zTXt
+#  define PNG_WRITE_zTXt_SUPPORTED
+#  ifndef PNG_zTXt_SUPPORTED
+#    define PNG_zTXt_SUPPORTED
+#  endif
+#endif
+#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS
+#  define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+#  ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
+#    define PNG_UNKNOWN_CHUNKS_SUPPORTED
+#  endif
+#  ifndef PNG_NO_HANDLE_AS_UNKNOWN
+#     ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#       define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#     endif
+#  endif
+#endif
+#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \
+    defined(PNG_WRITE_zTXt_SUPPORTED)
+#  define PNG_WRITE_TEXT_SUPPORTED
+#  ifndef PNG_TEXT_SUPPORTED
+#    define PNG_TEXT_SUPPORTED
+#  endif
+#endif
+
+#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */
+
+/* Turn this off to disable png_read_png() and
+ * png_write_png() and leave the row_pointers member
+ * out of the info structure.
+ */
+#ifndef PNG_NO_INFO_IMAGE
+#  define PNG_INFO_IMAGE_SUPPORTED
+#endif
+
+/* need the time information for reading tIME chunks */
+#if defined(PNG_tIME_SUPPORTED)
+#  if !defined(_WIN32_WCE)
+     /* "time.h" functions are not supported on WindowsCE */
+#    include <time.h>
+#  endif
+#endif
+
+/* Some typedefs to get us started.  These should be safe on most of the
+ * common platforms.  The typedefs should be at least as large as the
+ * numbers suggest (a png_uint_32 must be at least 32 bits long), but they
+ * don't have to be exactly that size.  Some compilers dislike passing
+ * unsigned shorts as function parameters, so you may be better off using
+ * unsigned int for png_uint_16.  Likewise, for 64-bit systems, you may
+ * want to have unsigned int for png_uint_32 instead of unsigned long.
+ */
+
+typedef unsigned long png_uint_32;
+typedef long png_int_32;
+typedef unsigned short png_uint_16;
+typedef short png_int_16;
+typedef unsigned char png_byte;
+
+/* This is usually size_t.  It is typedef'ed just in case you need it to
+   change (I'm not sure if you will or not, so I thought I'd be safe) */
+typedef size_t png_size_t;
+
+/* The following is needed for medium model support.  It cannot be in the
+ * PNG_INTERNAL section.  Needs modification for other compilers besides
+ * MSC.  Model independent support declares all arrays and pointers to be
+ * large using the far keyword.  The zlib version used must also support
+ * model independent data.  As of version zlib 1.0.4, the necessary changes
+ * have been made in zlib.  The USE_FAR_KEYWORD define triggers other
+ * changes that are needed. (Tim Wegner)
+ */
+
+/* Separate compiler dependencies (problem here is that zlib.h always
+   defines FAR. (SJT) */
+#ifdef __BORLANDC__
+#  if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
+#    define LDATA 1
+#  else
+#    define LDATA 0
+#  endif
+   /* GRR:  why is Cygwin in here?  Cygwin is not Borland C... */
+#  if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__)
+#    define PNG_MAX_MALLOC_64K
+#    if (LDATA != 1)
+#      ifndef FAR
+#        define FAR __far
+#      endif
+#      define USE_FAR_KEYWORD
+#    endif   /* LDATA != 1 */
+     /* Possibly useful for moving data out of default segment.
+      * Uncomment it if you want. Could also define FARDATA as
+      * const if your compiler supports it. (SJT)
+#    define FARDATA FAR
+      */
+#  endif  /* __WIN32__, __FLAT__, __CYGWIN__ */
+#endif   /* __BORLANDC__ */
+
+
+/* Suggest testing for specific compiler first before testing for
+ * FAR.  The Watcom compiler defines both __MEDIUM__ and M_I86MM,
+ * making reliance oncertain keywords suspect. (SJT)
+ */
+
+/* MSC Medium model */
+#if defined(FAR)
+#  if defined(M_I86MM)
+#    define USE_FAR_KEYWORD
+#    define FARDATA FAR
+#    include <dos.h>
+#  endif
+#endif
+
+/* SJT: default case */
+#ifndef FAR
+#  define FAR
+#endif
+
+/* At this point FAR is always defined */
+#ifndef FARDATA
+#  define FARDATA
+#endif
+
+/* Typedef for floating-point numbers that are converted
+   to fixed-point with a multiple of 100,000, e.g., int_gamma */
+typedef png_int_32 png_fixed_point;
+
+/* Add typedefs for pointers */
+typedef void            FAR * png_voidp;
+typedef png_byte        FAR * png_bytep;
+typedef png_uint_32     FAR * png_uint_32p;
+typedef png_int_32      FAR * png_int_32p;
+typedef png_uint_16     FAR * png_uint_16p;
+typedef png_int_16      FAR * png_int_16p;
+typedef PNG_CONST char  FAR * png_const_charp;
+typedef char            FAR * png_charp;
+typedef png_fixed_point FAR * png_fixed_point_p;
+
+#ifndef PNG_NO_STDIO
+#if defined(_WIN32_WCE)
+typedef HANDLE                png_FILE_p;
+#else
+typedef FILE                * png_FILE_p;
+#endif
+#endif
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+typedef double          FAR * png_doublep;
+#endif
+
+/* Pointers to pointers; i.e. arrays */
+typedef png_byte        FAR * FAR * png_bytepp;
+typedef png_uint_32     FAR * FAR * png_uint_32pp;
+typedef png_int_32      FAR * FAR * png_int_32pp;
+typedef png_uint_16     FAR * FAR * png_uint_16pp;
+typedef png_int_16      FAR * FAR * png_int_16pp;
+typedef PNG_CONST char  FAR * FAR * png_const_charpp;
+typedef char            FAR * FAR * png_charpp;
+typedef png_fixed_point FAR * FAR * png_fixed_point_pp;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+typedef double          FAR * FAR * png_doublepp;
+#endif
+
+/* Pointers to pointers to pointers; i.e., pointer to array */
+typedef char            FAR * FAR * FAR * png_charppp;
+
+/* libpng typedefs for types in zlib. If zlib changes
+ * or another compression library is used, then change these.
+ * Eliminates need to change all the source files.
+ */
+typedef charf *         png_zcharp;
+typedef charf * FAR *   png_zcharpp;
+typedef z_stream FAR *  png_zstreamp;
+
+/*
+ * Define PNG_BUILD_DLL if the module being built is a Windows
+ * LIBPNG DLL.
+ *
+ * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL.
+ * It is equivalent to Microsoft predefined macro _DLL that is
+ * automatically defined when you compile using the share
+ * version of the CRT (C Run-Time library)
+ *
+ * The cygwin mods make this behavior a little different:
+ * Define PNG_BUILD_DLL if you are building a dll for use with cygwin
+ * Define PNG_STATIC if you are building a static library for use with cygwin,
+ *   -or- if you are building an application that you want to link to the
+ *   static library.
+ * PNG_USE_DLL is defined by default (no user action needed) unless one of
+ *   the other flags is defined.
+ */
+
+#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL))
+#  define PNG_DLL
+#endif
+/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib.
+ * When building a static lib, default to no GLOBAL ARRAYS, but allow
+ * command-line override
+ */
+#if defined(__CYGWIN__)
+#  if !defined(PNG_STATIC)
+#    if defined(PNG_USE_GLOBAL_ARRAYS)
+#      undef PNG_USE_GLOBAL_ARRAYS
+#    endif
+#    if !defined(PNG_USE_LOCAL_ARRAYS)
+#      define PNG_USE_LOCAL_ARRAYS
+#    endif
+#  else
+#    if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS)
+#      if defined(PNG_USE_GLOBAL_ARRAYS)
+#        undef PNG_USE_GLOBAL_ARRAYS
+#      endif
+#    endif
+#  endif
+#  if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS)
+#    define PNG_USE_LOCAL_ARRAYS
+#  endif
+#endif
+
+/* Do not use global arrays (helps with building DLL's)
+ * They are no longer used in libpng itself, since version 1.0.5c,
+ * but might be required for some pre-1.0.5c applications.
+ */
+#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS)
+#  if defined(PNG_NO_GLOBAL_ARRAYS) || (defined(__GNUC__) && defined(PNG_DLL))
+#    define PNG_USE_LOCAL_ARRAYS
+#  else
+#    define PNG_USE_GLOBAL_ARRAYS
+#  endif
+#endif
+
+
+#ifndef PNGAPI
+
+#if defined(__MINGW32__) || defined(__CYGWIN__) && !defined(PNG_MODULEDEF)
+#  ifndef PNG_NO_MODULEDEF
+#    define PNG_NO_MODULEDEF
+#  endif
+#endif
+
+#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF)
+#  define PNG_IMPEXP
+#endif
+
+#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \
+    (( defined(_Windows) || defined(_WINDOWS) || \
+       defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
+         ) && !defined(__CYGWIN__))
+
+#  if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
+#    define PNGAPI __cdecl
+#  else
+#    define PNGAPI _cdecl
+#  endif
+
+#  if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \
+       0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */)
+#     define PNG_IMPEXP
+#  endif
+
+#  if !defined(PNG_IMPEXP)
+
+#     define PNG_EXPORT_TYPE1(type,symbol)  PNG_IMPEXP type PNGAPI symbol
+#     define PNG_EXPORT_TYPE2(type,symbol)  type PNG_IMPEXP PNGAPI symbol
+
+      /* Borland/Microsoft */
+#     if defined(_MSC_VER) || defined(__BORLANDC__)
+#        if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500)
+#           define PNG_EXPORT PNG_EXPORT_TYPE1
+#        else
+#           define PNG_EXPORT PNG_EXPORT_TYPE2
+#           if defined(PNG_BUILD_DLL)
+#              define PNG_IMPEXP __export
+#           else
+#              define PNG_IMPEXP /*__import*/ /* doesn't exist AFAIK in
+                                                 VC++*/
+#           endif                             /* Exists in Borland C++ for
+                                                 C++ classes (== huge) */
+#        endif
+#     endif
+
+#     if !defined(PNG_IMPEXP)
+#        if defined(PNG_BUILD_DLL)
+#           define PNG_IMPEXP __declspec(dllexport)
+#        else
+#           define PNG_IMPEXP __declspec(dllimport)
+#        endif
+#     endif
+#  endif  /* PNG_IMPEXP */
+#else /* !(DLL || non-cygwin WINDOWS) */
+#  if defined(__CYGWIN__) && !defined(PNG_DLL)
+#    if !defined(PNG_IMPEXP)
+#      define PNG_IMPEXP
+#    endif
+#    define PNGAPI __cdecl
+#  else
+#    if (defined(__IBMC__) || defined(IBMCPP__)) && defined(__OS2__)
+#      define PNGAPI _System
+#      define PNG_IMPEXP
+#    else
+#      if 0 /* ... other platforms, with other meanings */
+#      else
+#        define PNGAPI
+#        define PNG_IMPEXP
+#      endif
+#    endif
+#  endif
+#endif
+#endif
+
+#ifndef PNGAPI
+#  define PNGAPI
+#endif
+#ifndef PNG_IMPEXP
+#  define PNG_IMPEXP
+#endif
+
+#ifndef PNG_EXPORT
+#  define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol
+#endif
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+#  ifndef PNG_EXPORT_VAR
+#    define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type
+#  endif
+#endif
+
+/* User may want to use these so they are not in PNG_INTERNAL. Any library
+ * functions that are passed far data must be model independent.
+ */
+
+#ifndef PNG_ABORT
+#  define PNG_ABORT() abort()
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+#  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#else
+#  define png_jmpbuf(png_ptr) \
+   (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED)
+#endif
+
+#if defined(USE_FAR_KEYWORD)  /* memory model independent fns */
+/* use this to make far-to-near assignments */
+#  define CHECK   1
+#  define NOCHECK 0
+#  define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK))
+#  define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK))
+#  define png_strcpy _fstrcpy
+#  define png_strlen _fstrlen
+#  define png_memcmp _fmemcmp      /* SJT: added */
+#  define png_memcpy _fmemcpy
+#  define png_memset _fmemset
+#else /* use the usual functions */
+#  define CVT_PTR(ptr)         (ptr)
+#  define CVT_PTR_NOCHECK(ptr) (ptr)
+#  define png_strcpy strcpy
+#  define png_strlen strlen
+#  define png_memcmp memcmp     /* SJT: added */
+#  define png_memcpy memcpy
+#  define png_memset memset
+#endif
+/* End of memory model independent support */
+
+/* Just a little check that someone hasn't tried to define something
+ * contradictory.
+ */
+#if (PNG_ZBUF_SIZE > 65536) && defined(PNG_MAX_MALLOC_64K)
+#  undef PNG_ZBUF_SIZE
+#  define PNG_ZBUF_SIZE 65536
+#endif
+
+#ifdef PNG_READ_SUPPORTED
+/* Prior to libpng-1.0.9, this block was in pngasmrd.h */
+#if defined(PNG_INTERNAL)
+
+/* These are the default thresholds before the MMX code kicks in; if either
+ * rowbytes or bitdepth is below the threshold, plain C code is used.  These
+ * can be overridden at runtime via the png_set_mmx_thresholds() call in
+ * libpng 1.2.0 and later.  The values below were chosen by Intel.
+ */
+
+#ifndef PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT
+#  define PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT  128  /*  >=  */
+#endif
+#ifndef PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT
+#  define PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT  9    /*  >=  */   
+#endif
+
+/* Set this in the makefile for VC++ on Pentium, not here. */
+/* Platform must be Pentium.  Makefile must assemble and load pngvcrd.c .
+ * MMX will be detected at run time and used if present.
+ */
+#ifdef PNG_USE_PNGVCRD
+#  define PNG_HAVE_ASSEMBLER_COMBINE_ROW
+#  define PNG_HAVE_ASSEMBLER_READ_INTERLACE
+#  define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
+#endif
+
+/* Set this in the makefile for gcc/as on Pentium, not here. */
+/* Platform must be Pentium.  Makefile must assemble and load pnggccrd.c .
+ * MMX will be detected at run time and used if present.
+ */
+#ifdef PNG_USE_PNGGCCRD
+#  define PNG_HAVE_ASSEMBLER_COMBINE_ROW
+#  define PNG_HAVE_ASSEMBLER_READ_INTERLACE
+#  define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
+#endif
+/* - see pnggccrd.c for info about what is currently enabled */
+
+#endif /* PNG_INTERNAL */
+#endif /* PNG_READ_SUPPORTED */
+
+#endif /* PNGCONF_H */
+
diff --git a/libraries/libpng-1.2.0/pngerror.c b/libraries/libpng-1.2.0/pngerror.c
new file mode 100644 (file)
index 0000000..cf04c91
--- /dev/null
@@ -0,0 +1,289 @@
+
+/* pngerror.c - stub functions for i/o and memory allocation
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file provides a location for all error handling.  Users who
+ * need special error handling are expected to write replacement functions
+ * and use png_set_error_fn() to use those functions.  See the instructions
+ * at each function.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+static void /* PRIVATE */
+png_default_error PNGARG((png_structp png_ptr,
+                                      png_const_charp message));
+static void /* PRIVATE */
+png_default_warning PNGARG((png_structp png_ptr,
+                                        png_const_charp message));
+
+/* This function is called whenever there is a fatal error.  This function
+ * should not be changed.  If there is a need to handle errors differently,
+ * you should supply a replacement error function and use png_set_error_fn()
+ * to replace the error function at run-time.
+ */
+void PNGAPI
+png_error(png_structp png_ptr, png_const_charp message)
+{
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+   char msg[16];
+   if (png_ptr->flags&(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
+   {
+     int offset = 0;
+     if (*message == '#')
+     {
+         for (offset=1; offset<15; offset++)
+            if (*(message+offset) == ' ')
+                break;
+         if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
+         {
+            int i;
+            for (i=0; i<offset-1; i++)
+               msg[i]=message[i+1];
+            msg[i]='\0';
+            message=msg;
+         }
+         else
+            message+=offset;
+     }
+     else
+     {
+         if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
+         {
+            msg[0]='0';        
+            msg[1]='\0';
+            message=msg;
+         }
+     }
+   }
+#endif
+   if (png_ptr->error_fn != NULL)
+      (*(png_ptr->error_fn))(png_ptr, message);
+
+   /* if the following returns or doesn't exist, use the default function,
+      which will not return */
+   png_default_error(png_ptr, message);
+}
+
+/* This function is called whenever there is a non-fatal error.  This function
+ * should not be changed.  If there is a need to handle warnings differently,
+ * you should supply a replacement warning function and use
+ * png_set_error_fn() to replace the warning function at run-time.
+ */
+void PNGAPI
+png_warning(png_structp png_ptr, png_const_charp message)
+{
+     int offset = 0;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+   if (png_ptr->flags&(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
+#endif
+   {
+     if (*message == '#')
+     {
+         for (offset=1; offset<15; offset++)
+            if (*(message+offset) == ' ')
+                break;
+     }
+   }
+   if (png_ptr->warning_fn != NULL)
+      (*(png_ptr->warning_fn))(png_ptr, (png_const_charp)(message+offset));
+   else
+      png_default_warning(png_ptr, (png_const_charp)(message+offset));
+}
+
+/* These utilities are used internally to build an error message that relates
+ * to the current chunk.  The chunk name comes from png_ptr->chunk_name,
+ * this is used to prefix the message.  The message is limited in length
+ * to 63 bytes, the name characters are output as hex digits wrapped in []
+ * if the character is invalid.
+ */
+#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
+static PNG_CONST char png_digit[16] = {
+   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
+   'F' };
+
+static void /* PRIVATE */
+png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
+   message)
+{
+   int iout = 0, iin = 0;
+
+   while (iin < 4)
+   {
+      int c = png_ptr->chunk_name[iin++];
+      if (isnonalpha(c))
+      {
+         buffer[iout++] = '[';
+         buffer[iout++] = png_digit[(c & 0xf0) >> 4];
+         buffer[iout++] = png_digit[c & 0x0f];
+         buffer[iout++] = ']';
+      }
+      else
+      {
+         buffer[iout++] = (png_byte)c;
+      }
+   }
+
+   if (message == NULL)
+      buffer[iout] = 0;
+   else
+   {
+      buffer[iout++] = ':';
+      buffer[iout++] = ' ';
+      png_memcpy(buffer+iout, message, 64);
+      buffer[iout+63] = 0;
+   }
+}
+
+void PNGAPI
+png_chunk_error(png_structp png_ptr, png_const_charp message)
+{
+   char msg[18+64];
+   png_format_buffer(png_ptr, msg, message);
+   png_error(png_ptr, msg);
+}
+
+void PNGAPI
+png_chunk_warning(png_structp png_ptr, png_const_charp message)
+{
+   char msg[18+64];
+   png_format_buffer(png_ptr, msg, message);
+   png_warning(png_ptr, msg);
+}
+
+/* This is the default error handling function.  Note that replacements for
+ * this function MUST NOT RETURN, or the program will likely crash.  This
+ * function is used by default, or if the program supplies NULL for the
+ * error function pointer in png_set_error_fn().
+ */
+static void /* PRIVATE */
+png_default_error(png_structp png_ptr, png_const_charp message)
+{
+#ifndef PNG_NO_CONSOLE_IO
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+   if (*message == '#')
+   {
+     int offset;
+     char error_number[16];
+     for (offset=0; offset<15; offset++)
+     {
+         error_number[offset] = *(message+offset+1);
+         if (*(message+offset) == ' ')
+             break;
+     }
+     if((offset > 1) && (offset < 15))
+     {
+       error_number[offset-1]='\0';
+       fprintf(stderr, "libpng error no. %s: %s\n", error_number, message+offset);
+     }
+     else
+       fprintf(stderr, "libpng error: %s, offset=%d\n", message,offset);
+   }
+   else
+#endif
+   fprintf(stderr, "libpng error: %s\n", message);
+#else
+   if (message)
+     /* make compiler happy */ ;
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+#  ifdef USE_FAR_KEYWORD
+   {
+      jmp_buf jmpbuf;
+      png_memcpy(jmpbuf,png_ptr->jmpbuf,sizeof(jmp_buf));
+      longjmp(jmpbuf, 1);
+   }
+#  else
+   longjmp(png_ptr->jmpbuf, 1);
+# endif
+#else
+   if (png_ptr)
+     /* make compiler happy */ ;
+   PNG_ABORT();
+#endif
+}
+
+/* This function is called when there is a warning, but the library thinks
+ * it can continue anyway.  Replacement functions don't have to do anything
+ * here if you don't want them to.  In the default configuration, png_ptr is
+ * not used, but it is passed in case it may be useful.
+ */
+static void /* PRIVATE */
+png_default_warning(png_structp png_ptr, png_const_charp message)
+{
+#ifndef PNG_NO_CONSOLE_IO
+#  ifdef PNG_ERROR_NUMBERS_SUPPORTED
+   if (*message == '#')
+   {
+     int offset;
+     char warning_number[16];
+     for (offset=0; offset<15; offset++)
+     {
+        warning_number[offset]=*(message+offset+1);
+        if (*(message+offset) == ' ')
+            break;
+     }
+     if((offset > 1) && (offset < 15))
+     {
+       warning_number[offset-1]='\0';
+       fprintf(stderr, "libpng warning no. %s: %s\n", warning_number,
+          message+offset);
+     }
+     else
+       fprintf(stderr, "libpng warning: %s\n", message);
+   }
+   else
+#  endif
+     fprintf(stderr, "libpng warning: %s\n", message);
+#else
+   if (message)
+     /* appease compiler */ ;
+#endif
+   if (png_ptr)
+      return;
+}
+
+/* This function is called when the application wants to use another method
+ * of handling errors and warnings.  Note that the error function MUST NOT
+ * return to the calling routine or serious problems will occur.  The return
+ * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1)
+ */
+void PNGAPI
+png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warning_fn)
+{
+   png_ptr->error_ptr = error_ptr;
+   png_ptr->error_fn = error_fn;
+   png_ptr->warning_fn = warning_fn;
+}
+
+
+/* This function returns a pointer to the error_ptr associated with the user
+ * functions.  The application should free any memory associated with this
+ * pointer before png_write_destroy and png_read_destroy are called.
+ */
+png_voidp PNGAPI
+png_get_error_ptr(png_structp png_ptr)
+{
+   return ((png_voidp)png_ptr->error_ptr);
+}
+
+
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+void
+png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
+{
+   if(png_ptr != NULL)
+   {
+     png_ptr->flags &=
+       ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
+   }
+}
+#endif
diff --git a/libraries/libpng-1.2.0/pnggccrd.c b/libraries/libpng-1.2.0/pnggccrd.c
new file mode 100644 (file)
index 0000000..ce519c5
--- /dev/null
@@ -0,0 +1,5338 @@
+/* pnggccrd.c - mixed C/assembler version of utilities to read a PNG file
+ *
+ * For Intel x86 CPU (Pentium-MMX or later) and GNU C compiler.
+ *
+ *     See http://www.intel.com/drg/pentiumII/appnotes/916/916.htm
+ *     and http://www.intel.com/drg/pentiumII/appnotes/923/923.htm
+ *     for Intel's performance analysis of the MMX vs. non-MMX code.
+ *
+ * libpng version 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * Copyright (c) 1998, Intel Corporation
+ *
+ * Based on MSVC code contributed by Nirav Chhatrapati, Intel Corp., 1998.
+ * Interface to libpng contributed by Gilles Vollant, 1999.
+ * GNU C port by Greg Roelofs, 1999-2001.
+ *
+ * Lines 2350-4300 converted in place with intel2gas 1.3.1:
+ *
+ *   intel2gas -mdI pnggccrd.c.partially-msvc -o pnggccrd.c
+ *
+ * and then cleaned up by hand.  See http://hermes.terminal.at/intel2gas/ .
+ *
+ * NOTE:  A sufficiently recent version of GNU as (or as.exe under DOS/Windows)
+ *        is required to assemble the newer MMX instructions such as movq.
+ *        For djgpp, see
+ *
+ *           ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bnu281b.zip
+ *
+ *        (or a later version in the same directory).  For Linux, check your
+ *        distribution's web site(s) or try these links:
+ *
+ *           http://rufus.w3.org/linux/RPM/binutils.html
+ *           http://www.debian.org/Packages/stable/devel/binutils.html
+ *           ftp://ftp.slackware.com/pub/linux/slackware/slackware/slakware/d1/
+ *             binutils.tgz
+ *
+ *        For other platforms, see the main GNU site:
+ *
+ *           ftp://ftp.gnu.org/pub/gnu/binutils/
+ *
+ *        Version 2.5.2l.15 is definitely too old...
+ */
+
+/*
+ * TEMPORARY PORTING NOTES AND CHANGELOG (mostly by Greg Roelofs)
+ * =====================================
+ *
+ * 19991006:
+ *  - fixed sign error in post-MMX cleanup code (16- & 32-bit cases)
+ *
+ * 19991007:
+ *  - additional optimizations (possible or definite):
+ *     x [DONE] write MMX code for 64-bit case (pixel_bytes == 8) [not tested]
+ *     - write MMX code for 48-bit case (pixel_bytes == 6)
+ *     - figure out what's up with 24-bit case (pixel_bytes == 3):
+ *        why subtract 8 from width_mmx in the pass 4/5 case?
+ *        (only width_mmx case) (near line 1606)
+ *     x [DONE] replace pixel_bytes within each block with the true
+ *        constant value (or are compilers smart enough to do that?)
+ *     - rewrite all MMX interlacing code so it's aligned with
+ *        the *beginning* of the row buffer, not the end.  This
+ *        would not only allow one to eliminate half of the memory
+ *        writes for odd passes (that is, pass == odd), it may also
+ *        eliminate some unaligned-data-access exceptions (assuming
+ *        there's a penalty for not aligning 64-bit accesses on
+ *        64-bit boundaries).  The only catch is that the "leftover"
+ *        pixel(s) at the end of the row would have to be saved,
+ *        but there are enough unused MMX registers in every case,
+ *        so this is not a problem.  A further benefit is that the
+ *        post-MMX cleanup code (C code) in at least some of the
+ *        cases could be done within the assembler block.
+ *  x [DONE] the "v3 v2 v1 v0 v7 v6 v5 v4" comments are confusing,
+ *     inconsistent, and don't match the MMX Programmer's Reference
+ *     Manual conventions anyway.  They should be changed to
+ *     "b7 b6 b5 b4 b3 b2 b1 b0," where b0 indicates the byte that
+ *     was lowest in memory (e.g., corresponding to a left pixel)
+ *     and b7 is the byte that was highest (e.g., a right pixel).
+ *
+ * 19991016:
+ *  - Brennan's Guide notwithstanding, gcc under Linux does *not*
+ *     want globals prefixed by underscores when referencing them--
+ *     i.e., if the variable is const4, then refer to it as const4,
+ *     not _const4.  This seems to be a djgpp-specific requirement.
+ *     Also, such variables apparently *must* be declared outside
+ *     of functions; neither static nor automatic variables work if
+ *     defined within the scope of a single function, but both
+ *     static and truly global (multi-module) variables work fine.
+ *
+ * 19991023:
+ *  - fixed png_combine_row() non-MMX replication bug (odd passes only?)
+ *  - switched from string-concatenation-with-macros to cleaner method of
+ *     renaming global variables for djgpp--i.e., always use prefixes in
+ *     inlined assembler code (== strings) and conditionally rename the
+ *     variables, not the other way around.  Hence _const4, _mask8_0, etc.
+ *
+ * 19991024:
+ *  - fixed mmxsupport()/png_do_read_interlace() first-row bug
+ *     This one was severely weird:  even though mmxsupport() doesn't touch
+ *     ebx (where "row" pointer was stored), it nevertheless managed to zero
+ *     the register (even in static/non-fPIC code--see below), which in turn
+ *     caused png_do_read_interlace() to return prematurely on the first row of
+ *     interlaced images (i.e., without expanding the interlaced pixels).
+ *     Inspection of the generated assembly code didn't turn up any clues,
+ *     although it did point at a minor optimization (i.e., get rid of
+ *     mmx_supported_local variable and just use eax).  Possibly the CPUID
+ *     instruction is more destructive than it looks?  (Not yet checked.)
+ *  - "info gcc" was next to useless, so compared fPIC and non-fPIC assembly
+ *     listings...  Apparently register spillage has to do with ebx, since
+ *     it's used to index the global offset table.  Commenting it out of the
+ *     input-reg lists in png_combine_row() eliminated compiler barfage, so
+ *     ifdef'd with __PIC__ macro:  if defined, use a global for unmask
+ *
+ * 19991107:
+ *  - verified CPUID clobberage:  12-char string constant ("GenuineIntel",
+ *     "AuthenticAMD", etc.) placed in ebx:ecx:edx.  Still need to polish.
+ *
+ * 19991120:
+ *  - made "diff" variable (now "_dif") global to simplify conversion of
+ *     filtering routines (running out of regs, sigh).  "diff" is still used
+ *     in interlacing routines, however.
+ *  - fixed up both versions of mmxsupport() (ORIG_THAT_USED_TO_CLOBBER_EBX
+ *     macro determines which is used); original not yet tested.
+ *
+ * 20000213:
+ *  - when compiling with gcc, be sure to use  -fomit-frame-pointer
+ *
+ * 20000319:
+ *  - fixed a register-name typo in png_do_read_interlace(), default (MMX) case,
+ *     pass == 4 or 5, that caused visible corruption of interlaced images
+ *
+ * 20000623:
+ *  - Various problems were reported with gcc 2.95.2 in the Cygwin environment,
+ *     many of the form "forbidden register 0 (ax) was spilled for class AREG."
+ *     This is explained at http://gcc.gnu.org/fom_serv/cache/23.html, and
+ *     Chuck Wilson supplied a patch involving dummy output registers.  See
+ *     http://sourceforge.net/bugs/?func=detailbug&bug_id=108741&group_id=5624
+ *     for the original (anonymous) SourceForge bug report.
+ *
+ * 20000706:
+ *  - Chuck Wilson passed along these remaining gcc 2.95.2 errors:
+ *       pnggccrd.c: In function `png_combine_row':
+ *       pnggccrd.c:525: more than 10 operands in `asm'
+ *       pnggccrd.c:669: more than 10 operands in `asm'
+ *       pnggccrd.c:828: more than 10 operands in `asm'
+ *       pnggccrd.c:994: more than 10 operands in `asm'
+ *       pnggccrd.c:1177: more than 10 operands in `asm'
+ *     They are all the same problem and can be worked around by using the
+ *     global _unmask variable unconditionally, not just in the -fPIC case.
+ *     Reportedly earlier versions of gcc also have the problem with more than
+ *     10 operands; they just don't report it.  Much strangeness ensues, etc.
+ *
+ * 20000729:
+ *  - enabled png_read_filter_row_mmx_up() (shortest remaining unconverted
+ *     MMX routine); began converting png_read_filter_row_mmx_sub()
+ *  - to finish remaining sections:
+ *     - clean up indentation and comments
+ *     - preload local variables
+ *     - add output and input regs (order of former determines numerical
+ *        mapping of latter)
+ *     - avoid all usage of ebx (including bx, bh, bl) register [20000823]
+ *     - remove "$" from addressing of Shift and Mask variables [20000823]
+ *
+ * 20000731:
+ *  - global union vars causing segfaults in png_read_filter_row_mmx_sub()?
+ *
+ * 20000822:
+ *  - ARGH, stupid png_read_filter_row_mmx_sub() segfault only happens with
+ *     shared-library (-fPIC) version!  Code works just fine as part of static
+ *     library.  Damn damn damn damn damn, should have tested that sooner.
+ *     ebx is getting clobbered again (explicitly this time); need to save it
+ *     on stack or rewrite asm code to avoid using it altogether.  Blargh!
+ *
+ * 20000823:
+ *  - first section was trickiest; all remaining sections have ebx -> edx now.
+ *     (-fPIC works again.)  Also added missing underscores to various Shift*
+ *     and *Mask* globals and got rid of leading "$" signs.
+ *
+ * 20000826:
+ *  - added visual separators to help navigate microscopic printed copies
+ *     (http://pobox.com/~newt/code/gpr-latest.zip, mode 10); started working
+ *     on png_read_filter_row_mmx_avg()
+ *
+ * 20000828:
+ *  - finished png_read_filter_row_mmx_avg():  only Paeth left! (930 lines...)
+ *     What the hell, did png_read_filter_row_mmx_paeth(), too.  Comments not
+ *     cleaned up/shortened in either routine, but functionality is complete
+ *     and seems to be working fine.
+ *
+ * 20000829:
+ *  - ahhh, figured out last(?) bit of gcc/gas asm-fu:  if register is listed
+ *     as an input reg (with dummy output variables, etc.), then it *cannot*
+ *     also appear in the clobber list or gcc 2.95.2 will barf.  The solution
+ *     is simple enough...
+ *
+ * 20000914:
+ *  - bug in png_read_filter_row_mmx_avg():  16-bit grayscale not handled
+ *     correctly (but 48-bit RGB just fine)
+ *
+ * 20000916:
+ *  - fixed bug in png_read_filter_row_mmx_avg(), bpp == 2 case; three errors:
+ *     - "_ShiftBpp.use = 24;"      should have been   "_ShiftBpp.use = 16;"
+ *     - "_ShiftRem.use = 40;"      should have been   "_ShiftRem.use = 48;"
+ *     - "psllq _ShiftRem, %%mm2"   should have been   "psrlq _ShiftRem, %%mm2"
+ *
+ * 20010101:
+ *  - added new png_init_mmx_flags() function (here only because it needs to
+ *     call mmxsupport(), which should probably become global png_mmxsupport());
+ *     modified other MMX routines to run conditionally (png_ptr->asm_flags)
+ *
+ * 20010103:
+ *  - renamed mmxsupport() to png_mmx_support(), with auto-set of mmx_supported,
+ *     and made it public; moved png_init_mmx_flags() to png.c as internal func
+ *
+ * 20010104:
+ *  - removed dependency on png_read_filter_row_c() (C code already duplicated
+ *     within MMX version of png_read_filter_row()) so no longer necessary to
+ *     compile it into pngrutil.o
+ *
+ * 20010310:
+ *  - fixed buffer-overrun bug in png_combine_row() C code (non-MMX)
+ *
+ * STILL TO DO:
+ *     - test png_do_read_interlace() 64-bit case (pixel_bytes == 8)
+ *     - write MMX code for 48-bit case (pixel_bytes == 6)
+ *     - figure out what's up with 24-bit case (pixel_bytes == 3):
+ *        why subtract 8 from width_mmx in the pass 4/5 case?
+ *        (only width_mmx case) (near line 1606)
+ *     - rewrite all MMX interlacing code so it's aligned with beginning
+ *        of the row buffer, not the end (see 19991007 for details)
+ *     x pick one version of mmxsupport() and get rid of the other
+ *     - add error messages to any remaining bogus default cases
+ *     - enable pixel_depth == 8 cases in png_read_filter_row()? (test speed)
+ *     x add support for runtime enable/disable/query of various MMX routines
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(PNG_USE_PNGGCCRD)
+
+int PNGAPI png_mmx_support(void);
+
+#ifdef PNG_USE_LOCAL_ARRAYS
+static const int FARDATA png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+static const int FARDATA png_pass_inc[7]   = {8, 8, 4, 4, 2, 2, 1};
+static const int FARDATA png_pass_width[7] = {8, 4, 4, 2, 2, 1, 1};
+#endif
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+/* djgpp, Win32, and Cygwin add their own underscores to global variables,
+ * so define them without: */
+#if defined(__DJGPP__) || defined(WIN32) || defined(__CYGWIN__)
+#  define _mmx_supported  mmx_supported
+#  define _const4         const4
+#  define _const6         const6
+#  define _mask8_0        mask8_0
+#  define _mask16_1       mask16_1
+#  define _mask16_0       mask16_0
+#  define _mask24_2       mask24_2
+#  define _mask24_1       mask24_1
+#  define _mask24_0       mask24_0
+#  define _mask32_3       mask32_3
+#  define _mask32_2       mask32_2
+#  define _mask32_1       mask32_1
+#  define _mask32_0       mask32_0
+#  define _mask48_5       mask48_5
+#  define _mask48_4       mask48_4
+#  define _mask48_3       mask48_3
+#  define _mask48_2       mask48_2
+#  define _mask48_1       mask48_1
+#  define _mask48_0       mask48_0
+#  define _LBCarryMask    LBCarryMask
+#  define _HBClearMask    HBClearMask
+#  define _ActiveMask     ActiveMask
+#  define _ActiveMask2    ActiveMask2
+#  define _ActiveMaskEnd  ActiveMaskEnd
+#  define _ShiftBpp       ShiftBpp
+#  define _ShiftRem       ShiftRem
+#ifdef PNG_THREAD_UNSAFE_OK
+#  define _unmask         unmask
+#  define _FullLength     FullLength
+#  define _MMXLength      MMXLength
+#  define _dif            dif
+#  define _patemp         patemp
+#  define _pbtemp         pbtemp
+#  define _pctemp         pctemp
+#endif
+#endif
+
+
+/* These constants are used in the inlined MMX assembly code.
+   Ignore gcc's "At top level: defined but not used" warnings. */
+
+/* GRR 20000706:  originally _unmask was needed only when compiling with -fPIC,
+ *  since that case uses the %ebx register for indexing the Global Offset Table
+ *  and there were no other registers available.  But gcc 2.95 and later emit
+ *  "more than 10 operands in `asm'" errors when %ebx is used to preload unmask
+ *  in the non-PIC case, so we'll just use the global unconditionally now.
+ */
+#ifdef PNG_THREAD_UNSAFE_OK
+static int _unmask;
+#endif
+
+static unsigned long long _mask8_0  = 0x0102040810204080LL;
+
+static unsigned long long _mask16_1 = 0x0101020204040808LL;
+static unsigned long long _mask16_0 = 0x1010202040408080LL;
+
+static unsigned long long _mask24_2 = 0x0101010202020404LL;
+static unsigned long long _mask24_1 = 0x0408080810101020LL;
+static unsigned long long _mask24_0 = 0x2020404040808080LL;
+
+static unsigned long long _mask32_3 = 0x0101010102020202LL;
+static unsigned long long _mask32_2 = 0x0404040408080808LL;
+static unsigned long long _mask32_1 = 0x1010101020202020LL;
+static unsigned long long _mask32_0 = 0x4040404080808080LL;
+
+static unsigned long long _mask48_5 = 0x0101010101010202LL;
+static unsigned long long _mask48_4 = 0x0202020204040404LL;
+static unsigned long long _mask48_3 = 0x0404080808080808LL;
+static unsigned long long _mask48_2 = 0x1010101010102020LL;
+static unsigned long long _mask48_1 = 0x2020202040404040LL;
+static unsigned long long _mask48_0 = 0x4040808080808080LL;
+
+static unsigned long long _const4   = 0x0000000000FFFFFFLL;
+//static unsigned long long _const5 = 0x000000FFFFFF0000LL;     // NOT USED
+static unsigned long long _const6   = 0x00000000000000FFLL;
+
+// These are used in the row-filter routines and should/would be local
+//  variables if not for gcc addressing limitations.
+// WARNING: Their presence probably defeats the thread safety of libpng.
+
+#ifdef PNG_THREAD_UNSAFE_OK
+static png_uint_32  _FullLength;
+static png_uint_32  _MMXLength;
+static int          _dif;
+static int          _patemp;   // temp variables for Paeth routine
+static int          _pbtemp;
+static int          _pctemp;
+#endif
+
+void /* PRIVATE */
+png_squelch_warnings(void)
+{
+#ifdef PNG_THREAD_UNSAFE_OK
+   _dif = _dif;
+   _patemp = _patemp;
+   _pbtemp = _pbtemp;
+   _pctemp = _pctemp;
+   _MMXLength = _MMXLength;
+#endif
+   _const4  = _const4;
+   _const6  = _const6;
+   _mask8_0  = _mask8_0;
+   _mask16_1 = _mask16_1;
+   _mask16_0 = _mask16_0;
+   _mask24_2 = _mask24_2;
+   _mask24_1 = _mask24_1;
+   _mask24_0 = _mask24_0;
+   _mask32_3 = _mask32_3;
+   _mask32_2 = _mask32_2;
+   _mask32_1 = _mask32_1;
+   _mask32_0 = _mask32_0;
+   _mask48_5 = _mask48_5;
+   _mask48_4 = _mask48_4;
+   _mask48_3 = _mask48_3;
+   _mask48_2 = _mask48_2;
+   _mask48_1 = _mask48_1;
+   _mask48_0 = _mask48_0;
+}
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+
+
+static int _mmx_supported = 2;
+
+/*===========================================================================*/
+/*                                                                           */
+/*                       P N G _ C O M B I N E _ R O W                       */
+/*                                                                           */
+/*===========================================================================*/
+
+#if defined(PNG_HAVE_ASSEMBLER_COMBINE_ROW)
+
+#define BPP2  2
+#define BPP3  3                /* bytes per pixel (a.k.a. pixel_bytes) */
+#define BPP4  4
+#define BPP6  6                /* (defined only to help avoid cut-and-paste errors) */
+#define BPP8  8
+
+/* Combines the row recently read in with the previous row.
+   This routine takes care of alpha and transparency if requested.
+   This routine also handles the two methods of progressive display
+   of interlaced images, depending on the mask value.
+   The mask value describes which pixels are to be combined with
+   the row.  The pattern always repeats every 8 pixels, so just 8
+   bits are needed.  A one indicates the pixel is to be combined; a
+   zero indicates the pixel is to be skipped.  This is in addition
+   to any alpha or transparency value associated with the pixel.
+   If you want all pixels to be combined, pass 0xff (255) in mask. */
+
+/* Use this routine for the x86 platform - it uses a faster MMX routine
+   if the machine supports MMX. */
+
+void /* PRIVATE */
+png_combine_row(png_structp png_ptr, png_bytep row, int mask)
+{
+   png_debug(1, "in png_combine_row (pnggccrd.c)\n");
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+   if (_mmx_supported == 2) {
+       /* this should have happened in png_init_mmx_flags() already */
+       png_warning(png_ptr, "asm_flags may not have been initialized");
+       png_mmx_support();
+   }
+#endif
+
+   if (mask == 0xff)
+   {
+      png_debug(2,"mask == 0xff:  doing single png_memcpy()\n");
+      png_memcpy(row, png_ptr->row_buf + 1,
+       (png_size_t)((png_ptr->width * png_ptr->row_info.pixel_depth + 7) >> 3));
+   }
+   else   /* (png_combine_row() is never called with mask == 0) */
+   {
+      switch (png_ptr->row_info.pixel_depth)
+      {
+         case 1:        /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int s_inc, s_start, s_end;
+            int m;
+            int shift;
+            png_uint_32 i;
+
+            sp = png_ptr->row_buf + 1;
+            dp = row;
+            m = 0x80;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+                s_start = 0;
+                s_end = 7;
+                s_inc = 1;
+            }
+            else
+#endif
+            {
+                s_start = 7;
+                s_end = 0;
+                s_inc = -1;
+            }
+
+            shift = s_start;
+
+            for (i = 0; i < png_ptr->width; i++)
+            {
+               if (m & mask)
+               {
+                  int value;
+
+                  value = (*sp >> shift) & 0x1;
+                  *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+
+         case 2:        /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int s_start, s_end, s_inc;
+            int m;
+            int shift;
+            png_uint_32 i;
+            int value;
+
+            sp = png_ptr->row_buf + 1;
+            dp = row;
+            m = 0x80;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+               s_start = 0;
+               s_end = 6;
+               s_inc = 2;
+            }
+            else
+#endif
+            {
+               s_start = 6;
+               s_end = 0;
+               s_inc = -2;
+            }
+
+            shift = s_start;
+
+            for (i = 0; i < png_ptr->width; i++)
+            {
+               if (m & mask)
+               {
+                  value = (*sp >> shift) & 0x3;
+                  *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+
+         case 4:        /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int s_start, s_end, s_inc;
+            int m;
+            int shift;
+            png_uint_32 i;
+            int value;
+
+            sp = png_ptr->row_buf + 1;
+            dp = row;
+            m = 0x80;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+               s_start = 0;
+               s_end = 4;
+               s_inc = 4;
+            }
+            else
+#endif
+            {
+               s_start = 4;
+               s_end = 0;
+               s_inc = -4;
+            }
+            shift = s_start;
+
+            for (i = 0; i < png_ptr->width; i++)
+            {
+               if (m & mask)
+               {
+                  value = (*sp >> shift) & 0xf;
+                  *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+
+         case 8:        /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
+                /* && _mmx_supported */ )
+            {
+               png_uint_32 len;
+               int diff;
+               int dummy_value_a;   // fix 'forbidden register spilled' error
+               int dummy_value_d;
+               int dummy_value_c;
+               int dummy_value_S;
+               int dummy_value_D;
+               _unmask = ~mask;            // global variable for -fPIC version
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = (int) (png_ptr->width & 7);  // amount lost
+
+               __asm__ __volatile__ (
+                  "movd      _unmask, %%mm7  \n\t" // load bit pattern
+                  "psubb     %%mm6, %%mm6    \n\t" // zero mm6
+                  "punpcklbw %%mm7, %%mm7    \n\t"
+                  "punpcklwd %%mm7, %%mm7    \n\t"
+                  "punpckldq %%mm7, %%mm7    \n\t" // fill reg with 8 masks
+
+                  "movq      _mask8_0, %%mm0 \n\t"
+                  "pand      %%mm7, %%mm0    \n\t" // nonzero if keep byte
+                  "pcmpeqb   %%mm6, %%mm0    \n\t" // zeros->1s, v versa
+
+// preload        "movl      len, %%ecx      \n\t" // load length of line
+// preload        "movl      srcptr, %%esi   \n\t" // load source
+// preload        "movl      dstptr, %%edi   \n\t" // load dest
+
+                  "cmpl      $0, %%ecx       \n\t" // len == 0 ?
+                  "je        mainloop8end    \n\t"
+
+                "mainloop8:                  \n\t"
+                  "movq      (%%esi), %%mm4  \n\t" // *srcptr
+                  "pand      %%mm0, %%mm4    \n\t"
+                  "movq      %%mm0, %%mm6    \n\t"
+                  "pandn     (%%edi), %%mm6  \n\t" // *dstptr
+                  "por       %%mm6, %%mm4    \n\t"
+                  "movq      %%mm4, (%%edi)  \n\t"
+                  "addl      $8, %%esi       \n\t" // inc by 8 bytes processed
+                  "addl      $8, %%edi       \n\t"
+                  "subl      $8, %%ecx       \n\t" // dec by 8 pixels processed
+                  "ja        mainloop8       \n\t"
+
+                "mainloop8end:               \n\t"
+// preload        "movl      diff, %%ecx     \n\t" // (diff is in eax)
+                  "movl      %%eax, %%ecx    \n\t"
+                  "cmpl      $0, %%ecx       \n\t"
+                  "jz        end8            \n\t"
+// preload        "movl      mask, %%edx     \n\t"
+                  "sall      $24, %%edx      \n\t" // make low byte, high byte
+
+                "secondloop8:                \n\t"
+                  "sall      %%edx           \n\t" // move high bit to CF
+                  "jnc       skip8           \n\t" // if CF = 0
+                  "movb      (%%esi), %%al   \n\t"
+                  "movb      %%al, (%%edi)   \n\t"
+
+                "skip8:                      \n\t"
+                  "incl      %%esi           \n\t"
+                  "incl      %%edi           \n\t"
+                  "decl      %%ecx           \n\t"
+                  "jnz       secondloop8     \n\t"
+
+                "end8:                       \n\t"
+                  "EMMS                      \n\t"  // DONE
+
+                  : "=a" (dummy_value_a),           // output regs (dummy)
+                    "=d" (dummy_value_d),
+                    "=c" (dummy_value_c),
+                    "=S" (dummy_value_S),
+                    "=D" (dummy_value_D)
+
+                  : "3" (srcptr),      // esi       // input regs
+                    "4" (dstptr),      // edi
+                    "0" (diff),        // eax
+// was (unmask)     "b"    RESERVED    // ebx       // Global Offset Table idx
+                    "2" (len),         // ecx
+                    "1" (mask)         // edx
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  : "%mm0", "%mm4", "%mm6", "%mm7"  // clobber list
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = png_pass_start[png_ptr->pass];
+                 /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+               register int stride = png_pass_inc[png_ptr->pass];
+                 /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+               register int rep_bytes = png_pass_width[png_ptr->pass];
+                 /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+               png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+               int diff = (int) (png_ptr->width & 7); /* amount lost */
+               register png_uint_32 final_val = len;  /* GRR bugfix */
+
+               srcptr = png_ptr->row_buf + 1 + initial_val;
+               dstptr = row + initial_val;
+
+               for (i = initial_val; i < final_val; i += stride)
+               {
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               }
+               if (diff)  /* number of leftover pixels:  3 for pngtest */
+               {
+                  final_val+=diff /* *BPP1 */ ;
+                  for (; i < final_val; i += stride)
+                  {
+                     if (rep_bytes > (int)(final_val-i))
+                        rep_bytes = (int)(final_val-i);
+                     png_memcpy(dstptr, srcptr, rep_bytes);
+                     srcptr += stride;
+                     dstptr += stride;
+                  }
+               }
+
+            } /* end of else (_mmx_supported) */
+
+            break;
+         }       /* end 8 bpp */
+
+         case 16:       /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
+                /* && _mmx_supported */ )
+            {
+               png_uint_32 len;
+               int diff;
+               int dummy_value_a;   // fix 'forbidden register spilled' error
+               int dummy_value_d;
+               int dummy_value_c;
+               int dummy_value_S;
+               int dummy_value_D;
+               _unmask = ~mask;            // global variable for -fPIC version
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = (int) (png_ptr->width & 7); // amount lost //
+
+               __asm__ __volatile__ (
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+                  "psubb     %%mm6, %%mm6     \n\t" // zero mm6
+                  "punpcklbw %%mm7, %%mm7     \n\t"
+                  "punpcklwd %%mm7, %%mm7     \n\t"
+                  "punpckldq %%mm7, %%mm7     \n\t" // fill reg with 8 masks
+
+                  "movq      _mask16_0, %%mm0 \n\t"
+                  "movq      _mask16_1, %%mm1 \n\t"
+
+                  "pand      %%mm7, %%mm0     \n\t"
+                  "pand      %%mm7, %%mm1     \n\t"
+
+                  "pcmpeqb   %%mm6, %%mm0     \n\t"
+                  "pcmpeqb   %%mm6, %%mm1     \n\t"
+
+// preload        "movl      len, %%ecx       \n\t" // load length of line
+// preload        "movl      srcptr, %%esi    \n\t" // load source
+// preload        "movl      dstptr, %%edi    \n\t" // load dest
+
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        mainloop16end    \n\t"
+
+                "mainloop16:                  \n\t"
+                  "movq      (%%esi), %%mm4   \n\t"
+                  "pand      %%mm0, %%mm4     \n\t"
+                  "movq      %%mm0, %%mm6     \n\t"
+                  "movq      (%%edi), %%mm7   \n\t"
+                  "pandn     %%mm7, %%mm6     \n\t"
+                  "por       %%mm6, %%mm4     \n\t"
+                  "movq      %%mm4, (%%edi)   \n\t"
+
+                  "movq      8(%%esi), %%mm5  \n\t"
+                  "pand      %%mm1, %%mm5     \n\t"
+                  "movq      %%mm1, %%mm7     \n\t"
+                  "movq      8(%%edi), %%mm6  \n\t"
+                  "pandn     %%mm6, %%mm7     \n\t"
+                  "por       %%mm7, %%mm5     \n\t"
+                  "movq      %%mm5, 8(%%edi)  \n\t"
+
+                  "addl      $16, %%esi       \n\t" // inc by 16 bytes processed
+                  "addl      $16, %%edi       \n\t"
+                  "subl      $8, %%ecx        \n\t" // dec by 8 pixels processed
+                  "ja        mainloop16       \n\t"
+
+                "mainloop16end:               \n\t"
+// preload        "movl      diff, %%ecx      \n\t" // (diff is in eax)
+                  "movl      %%eax, %%ecx     \n\t"
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        end16            \n\t"
+// preload        "movl      mask, %%edx      \n\t"
+                  "sall      $24, %%edx       \n\t" // make low byte, high byte
+
+                "secondloop16:                \n\t"
+                  "sall      %%edx            \n\t" // move high bit to CF
+                  "jnc       skip16           \n\t" // if CF = 0
+                  "movw      (%%esi), %%ax    \n\t"
+                  "movw      %%ax, (%%edi)    \n\t"
+
+                "skip16:                      \n\t"
+                  "addl      $2, %%esi        \n\t"
+                  "addl      $2, %%edi        \n\t"
+                  "decl      %%ecx            \n\t"
+                  "jnz       secondloop16     \n\t"
+
+                "end16:                       \n\t"
+                  "EMMS                       \n\t" // DONE
+
+                  : "=a" (dummy_value_a),           // output regs (dummy)
+                    "=c" (dummy_value_c),
+                    "=d" (dummy_value_d),
+                    "=S" (dummy_value_S),
+                    "=D" (dummy_value_D)
+
+                  : "0" (diff),        // eax       // input regs
+// was (unmask)     " "    RESERVED    // ebx       // Global Offset Table idx
+                    "1" (len),         // ecx
+                    "2" (mask),        // edx
+                    "3" (srcptr),      // esi
+                    "4" (dstptr)       // edi
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  : "%mm0", "%mm1", "%mm4"          // clobber list
+                  , "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = BPP2 * png_pass_start[png_ptr->pass];
+                 /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+               register int stride = BPP2 * png_pass_inc[png_ptr->pass];
+                 /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+               register int rep_bytes = BPP2 * png_pass_width[png_ptr->pass];
+                 /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+               png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+               int diff = (int) (png_ptr->width & 7); /* amount lost */
+               register png_uint_32 final_val = BPP2 * len;   /* GRR bugfix */
+
+               srcptr = png_ptr->row_buf + 1 + initial_val;
+               dstptr = row + initial_val;
+
+               for (i = initial_val; i < final_val; i += stride)
+               {
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               }
+               if (diff)  /* number of leftover pixels:  3 for pngtest */
+               {
+                  final_val+=diff*BPP2;
+                  for (; i < final_val; i += stride)
+                  {
+                     if (rep_bytes > (int)(final_val-i))
+                        rep_bytes = (int)(final_val-i);
+                     png_memcpy(dstptr, srcptr, rep_bytes);
+                     srcptr += stride;
+                     dstptr += stride;
+                  }
+               }
+            } /* end of else (_mmx_supported) */
+
+            break;
+         }       /* end 16 bpp */
+
+         case 24:       /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
+                /* && _mmx_supported */ )
+            {
+               png_uint_32 len;
+               int diff;
+               int dummy_value_a;   // fix 'forbidden register spilled' error
+               int dummy_value_d;
+               int dummy_value_c;
+               int dummy_value_S;
+               int dummy_value_D;
+               _unmask = ~mask;            // global variable for -fPIC version
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = (int) (png_ptr->width & 7); // amount lost //
+
+               __asm__ __volatile__ (
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+                  "psubb     %%mm6, %%mm6     \n\t" // zero mm6
+                  "punpcklbw %%mm7, %%mm7     \n\t"
+                  "punpcklwd %%mm7, %%mm7     \n\t"
+                  "punpckldq %%mm7, %%mm7     \n\t" // fill reg with 8 masks
+
+                  "movq      _mask24_0, %%mm0 \n\t"
+                  "movq      _mask24_1, %%mm1 \n\t"
+                  "movq      _mask24_2, %%mm2 \n\t"
+
+                  "pand      %%mm7, %%mm0     \n\t"
+                  "pand      %%mm7, %%mm1     \n\t"
+                  "pand      %%mm7, %%mm2     \n\t"
+
+                  "pcmpeqb   %%mm6, %%mm0     \n\t"
+                  "pcmpeqb   %%mm6, %%mm1     \n\t"
+                  "pcmpeqb   %%mm6, %%mm2     \n\t"
+
+// preload        "movl      len, %%ecx       \n\t" // load length of line
+// preload        "movl      srcptr, %%esi    \n\t" // load source
+// preload        "movl      dstptr, %%edi    \n\t" // load dest
+
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        mainloop24end    \n\t"
+
+                "mainloop24:                  \n\t"
+                  "movq      (%%esi), %%mm4   \n\t"
+                  "pand      %%mm0, %%mm4     \n\t"
+                  "movq      %%mm0, %%mm6     \n\t"
+                  "movq      (%%edi), %%mm7   \n\t"
+                  "pandn     %%mm7, %%mm6     \n\t"
+                  "por       %%mm6, %%mm4     \n\t"
+                  "movq      %%mm4, (%%edi)   \n\t"
+
+                  "movq      8(%%esi), %%mm5  \n\t"
+                  "pand      %%mm1, %%mm5     \n\t"
+                  "movq      %%mm1, %%mm7     \n\t"
+                  "movq      8(%%edi), %%mm6  \n\t"
+                  "pandn     %%mm6, %%mm7     \n\t"
+                  "por       %%mm7, %%mm5     \n\t"
+                  "movq      %%mm5, 8(%%edi)  \n\t"
+
+                  "movq      16(%%esi), %%mm6 \n\t"
+                  "pand      %%mm2, %%mm6     \n\t"
+                  "movq      %%mm2, %%mm4     \n\t"
+                  "movq      16(%%edi), %%mm7 \n\t"
+                  "pandn     %%mm7, %%mm4     \n\t"
+                  "por       %%mm4, %%mm6     \n\t"
+                  "movq      %%mm6, 16(%%edi) \n\t"
+
+                  "addl      $24, %%esi       \n\t" // inc by 24 bytes processed
+                  "addl      $24, %%edi       \n\t"
+                  "subl      $8, %%ecx        \n\t" // dec by 8 pixels processed
+
+                  "ja        mainloop24       \n\t"
+
+                "mainloop24end:               \n\t"
+// preload        "movl      diff, %%ecx      \n\t" // (diff is in eax)
+                  "movl      %%eax, %%ecx     \n\t"
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        end24            \n\t"
+// preload        "movl      mask, %%edx      \n\t"
+                  "sall      $24, %%edx       \n\t" // make low byte, high byte
+
+                "secondloop24:                \n\t"
+                  "sall      %%edx            \n\t" // move high bit to CF
+                  "jnc       skip24           \n\t" // if CF = 0
+                  "movw      (%%esi), %%ax    \n\t"
+                  "movw      %%ax, (%%edi)    \n\t"
+                  "xorl      %%eax, %%eax     \n\t"
+                  "movb      2(%%esi), %%al   \n\t"
+                  "movb      %%al, 2(%%edi)   \n\t"
+
+                "skip24:                      \n\t"
+                  "addl      $3, %%esi        \n\t"
+                  "addl      $3, %%edi        \n\t"
+                  "decl      %%ecx            \n\t"
+                  "jnz       secondloop24     \n\t"
+
+                "end24:                       \n\t"
+                  "EMMS                       \n\t" // DONE
+
+                  : "=a" (dummy_value_a),           // output regs (dummy)
+                    "=d" (dummy_value_d),
+                    "=c" (dummy_value_c),
+                    "=S" (dummy_value_S),
+                    "=D" (dummy_value_D)
+
+                  : "3" (srcptr),      // esi       // input regs
+                    "4" (dstptr),      // edi
+                    "0" (diff),        // eax
+// was (unmask)     "b"    RESERVED    // ebx       // Global Offset Table idx
+                    "2" (len),         // ecx
+                    "1" (mask)         // edx
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  : "%mm0", "%mm1", "%mm2"          // clobber list
+                  , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = BPP3 * png_pass_start[png_ptr->pass];
+                 /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+               register int stride = BPP3 * png_pass_inc[png_ptr->pass];
+                 /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+               register int rep_bytes = BPP3 * png_pass_width[png_ptr->pass];
+                 /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+               png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+               int diff = (int) (png_ptr->width & 7); /* amount lost */
+               register png_uint_32 final_val = BPP3 * len;   /* GRR bugfix */
+
+               srcptr = png_ptr->row_buf + 1 + initial_val;
+               dstptr = row + initial_val;
+
+               for (i = initial_val; i < final_val; i += stride)
+               {
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               }
+               if (diff)  /* number of leftover pixels:  3 for pngtest */
+               {
+                  final_val+=diff*BPP3;
+                  for (; i < final_val; i += stride)
+                  {
+                     if (rep_bytes > (int)(final_val-i))
+                        rep_bytes = (int)(final_val-i);
+                     png_memcpy(dstptr, srcptr, rep_bytes);
+                     srcptr += stride;
+                     dstptr += stride;
+                  }
+               }
+            } /* end of else (_mmx_supported) */
+
+            break;
+         }       /* end 24 bpp */
+
+         case 32:       /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
+                /* && _mmx_supported */ )
+            {
+               png_uint_32 len;
+               int diff;
+               int dummy_value_a;   // fix 'forbidden register spilled' error
+               int dummy_value_d;
+               int dummy_value_c;
+               int dummy_value_S;
+               int dummy_value_D;
+               _unmask = ~mask;            // global variable for -fPIC version
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = (int) (png_ptr->width & 7); // amount lost //
+
+               __asm__ __volatile__ (
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+                  "psubb     %%mm6, %%mm6     \n\t" // zero mm6
+                  "punpcklbw %%mm7, %%mm7     \n\t"
+                  "punpcklwd %%mm7, %%mm7     \n\t"
+                  "punpckldq %%mm7, %%mm7     \n\t" // fill reg with 8 masks
+
+                  "movq      _mask32_0, %%mm0 \n\t"
+                  "movq      _mask32_1, %%mm1 \n\t"
+                  "movq      _mask32_2, %%mm2 \n\t"
+                  "movq      _mask32_3, %%mm3 \n\t"
+
+                  "pand      %%mm7, %%mm0     \n\t"
+                  "pand      %%mm7, %%mm1     \n\t"
+                  "pand      %%mm7, %%mm2     \n\t"
+                  "pand      %%mm7, %%mm3     \n\t"
+
+                  "pcmpeqb   %%mm6, %%mm0     \n\t"
+                  "pcmpeqb   %%mm6, %%mm1     \n\t"
+                  "pcmpeqb   %%mm6, %%mm2     \n\t"
+                  "pcmpeqb   %%mm6, %%mm3     \n\t"
+
+// preload        "movl      len, %%ecx       \n\t" // load length of line
+// preload        "movl      srcptr, %%esi    \n\t" // load source
+// preload        "movl      dstptr, %%edi    \n\t" // load dest
+
+                  "cmpl      $0, %%ecx        \n\t" // lcr
+                  "jz        mainloop32end    \n\t"
+
+                "mainloop32:                  \n\t"
+                  "movq      (%%esi), %%mm4   \n\t"
+                  "pand      %%mm0, %%mm4     \n\t"
+                  "movq      %%mm0, %%mm6     \n\t"
+                  "movq      (%%edi), %%mm7   \n\t"
+                  "pandn     %%mm7, %%mm6     \n\t"
+                  "por       %%mm6, %%mm4     \n\t"
+                  "movq      %%mm4, (%%edi)   \n\t"
+
+                  "movq      8(%%esi), %%mm5  \n\t"
+                  "pand      %%mm1, %%mm5     \n\t"
+                  "movq      %%mm1, %%mm7     \n\t"
+                  "movq      8(%%edi), %%mm6  \n\t"
+                  "pandn     %%mm6, %%mm7     \n\t"
+                  "por       %%mm7, %%mm5     \n\t"
+                  "movq      %%mm5, 8(%%edi)  \n\t"
+
+                  "movq      16(%%esi), %%mm6 \n\t"
+                  "pand      %%mm2, %%mm6     \n\t"
+                  "movq      %%mm2, %%mm4     \n\t"
+                  "movq      16(%%edi), %%mm7 \n\t"
+                  "pandn     %%mm7, %%mm4     \n\t"
+                  "por       %%mm4, %%mm6     \n\t"
+                  "movq      %%mm6, 16(%%edi) \n\t"
+
+                  "movq      24(%%esi), %%mm7 \n\t"
+                  "pand      %%mm3, %%mm7     \n\t"
+                  "movq      %%mm3, %%mm5     \n\t"
+                  "movq      24(%%edi), %%mm4 \n\t"
+                  "pandn     %%mm4, %%mm5     \n\t"
+                  "por       %%mm5, %%mm7     \n\t"
+                  "movq      %%mm7, 24(%%edi) \n\t"
+
+                  "addl      $32, %%esi       \n\t" // inc by 32 bytes processed
+                  "addl      $32, %%edi       \n\t"
+                  "subl      $8, %%ecx        \n\t" // dec by 8 pixels processed
+                  "ja        mainloop32       \n\t"
+
+                "mainloop32end:               \n\t"
+// preload        "movl      diff, %%ecx      \n\t" // (diff is in eax)
+                  "movl      %%eax, %%ecx     \n\t"
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        end32            \n\t"
+// preload        "movl      mask, %%edx      \n\t"
+                  "sall      $24, %%edx       \n\t" // low byte => high byte
+
+                "secondloop32:                \n\t"
+                  "sall      %%edx            \n\t" // move high bit to CF
+                  "jnc       skip32           \n\t" // if CF = 0
+                  "movl      (%%esi), %%eax   \n\t"
+                  "movl      %%eax, (%%edi)   \n\t"
+
+                "skip32:                      \n\t"
+                  "addl      $4, %%esi        \n\t"
+                  "addl      $4, %%edi        \n\t"
+                  "decl      %%ecx            \n\t"
+                  "jnz       secondloop32     \n\t"
+
+                "end32:                       \n\t"
+                  "EMMS                       \n\t" // DONE
+
+                  : "=a" (dummy_value_a),           // output regs (dummy)
+                    "=d" (dummy_value_d),
+                    "=c" (dummy_value_c),
+                    "=S" (dummy_value_S),
+                    "=D" (dummy_value_D)
+
+                  : "3" (srcptr),      // esi       // input regs
+                    "4" (dstptr),      // edi
+                    "0" (diff),        // eax
+// was (unmask)     "b"    RESERVED    // ebx       // Global Offset Table idx
+                    "2" (len),         // ecx
+                    "1" (mask)         // edx
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  : "%mm0", "%mm1", "%mm2", "%mm3"  // clobber list
+                  , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = BPP4 * png_pass_start[png_ptr->pass];
+                 /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+               register int stride = BPP4 * png_pass_inc[png_ptr->pass];
+                 /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+               register int rep_bytes = BPP4 * png_pass_width[png_ptr->pass];
+                 /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+               png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+               int diff = (int) (png_ptr->width & 7); /* amount lost */
+               register png_uint_32 final_val = BPP4 * len;   /* GRR bugfix */
+
+               srcptr = png_ptr->row_buf + 1 + initial_val;
+               dstptr = row + initial_val;
+
+               for (i = initial_val; i < final_val; i += stride)
+               {
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               }
+               if (diff)  /* number of leftover pixels:  3 for pngtest */
+               {
+                  final_val+=diff*BPP4;
+                  for (; i < final_val; i += stride)
+                  {
+                     if (rep_bytes > (int)(final_val-i))
+                        rep_bytes = (int)(final_val-i);
+                     png_memcpy(dstptr, srcptr, rep_bytes);
+                     srcptr += stride;
+                     dstptr += stride;
+                  }
+               }
+            } /* end of else (_mmx_supported) */
+
+            break;
+         }       /* end 32 bpp */
+
+         case 48:       /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
+                /* && _mmx_supported */ )
+            {
+               png_uint_32 len;
+               int diff;
+               int dummy_value_a;   // fix 'forbidden register spilled' error
+               int dummy_value_d;
+               int dummy_value_c;
+               int dummy_value_S;
+               int dummy_value_D;
+               _unmask = ~mask;            // global variable for -fPIC version
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               len  = png_ptr->width &~7;  // reduce to multiple of 8
+               diff = (int) (png_ptr->width & 7); // amount lost //
+
+               __asm__ __volatile__ (
+                  "movd      _unmask, %%mm7   \n\t" // load bit pattern
+                  "psubb     %%mm6, %%mm6     \n\t" // zero mm6
+                  "punpcklbw %%mm7, %%mm7     \n\t"
+                  "punpcklwd %%mm7, %%mm7     \n\t"
+                  "punpckldq %%mm7, %%mm7     \n\t" // fill reg with 8 masks
+
+                  "movq      _mask48_0, %%mm0 \n\t"
+                  "movq      _mask48_1, %%mm1 \n\t"
+                  "movq      _mask48_2, %%mm2 \n\t"
+                  "movq      _mask48_3, %%mm3 \n\t"
+                  "movq      _mask48_4, %%mm4 \n\t"
+                  "movq      _mask48_5, %%mm5 \n\t"
+
+                  "pand      %%mm7, %%mm0     \n\t"
+                  "pand      %%mm7, %%mm1     \n\t"
+                  "pand      %%mm7, %%mm2     \n\t"
+                  "pand      %%mm7, %%mm3     \n\t"
+                  "pand      %%mm7, %%mm4     \n\t"
+                  "pand      %%mm7, %%mm5     \n\t"
+
+                  "pcmpeqb   %%mm6, %%mm0     \n\t"
+                  "pcmpeqb   %%mm6, %%mm1     \n\t"
+                  "pcmpeqb   %%mm6, %%mm2     \n\t"
+                  "pcmpeqb   %%mm6, %%mm3     \n\t"
+                  "pcmpeqb   %%mm6, %%mm4     \n\t"
+                  "pcmpeqb   %%mm6, %%mm5     \n\t"
+
+// preload        "movl      len, %%ecx       \n\t" // load length of line
+// preload        "movl      srcptr, %%esi    \n\t" // load source
+// preload        "movl      dstptr, %%edi    \n\t" // load dest
+
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        mainloop48end    \n\t"
+
+                "mainloop48:                  \n\t"
+                  "movq      (%%esi), %%mm7   \n\t"
+                  "pand      %%mm0, %%mm7     \n\t"
+                  "movq      %%mm0, %%mm6     \n\t"
+                  "pandn     (%%edi), %%mm6   \n\t"
+                  "por       %%mm6, %%mm7     \n\t"
+                  "movq      %%mm7, (%%edi)   \n\t"
+
+                  "movq      8(%%esi), %%mm6  \n\t"
+                  "pand      %%mm1, %%mm6     \n\t"
+                  "movq      %%mm1, %%mm7     \n\t"
+                  "pandn     8(%%edi), %%mm7  \n\t"
+                  "por       %%mm7, %%mm6     \n\t"
+                  "movq      %%mm6, 8(%%edi)  \n\t"
+
+                  "movq      16(%%esi), %%mm6 \n\t"
+                  "pand      %%mm2, %%mm6     \n\t"
+                  "movq      %%mm2, %%mm7     \n\t"
+                  "pandn     16(%%edi), %%mm7 \n\t"
+                  "por       %%mm7, %%mm6     \n\t"
+                  "movq      %%mm6, 16(%%edi) \n\t"
+
+                  "movq      24(%%esi), %%mm7 \n\t"
+                  "pand      %%mm3, %%mm7     \n\t"
+                  "movq      %%mm3, %%mm6     \n\t"
+                  "pandn     24(%%edi), %%mm6 \n\t"
+                  "por       %%mm6, %%mm7     \n\t"
+                  "movq      %%mm7, 24(%%edi) \n\t"
+
+                  "movq      32(%%esi), %%mm6 \n\t"
+                  "pand      %%mm4, %%mm6     \n\t"
+                  "movq      %%mm4, %%mm7     \n\t"
+                  "pandn     32(%%edi), %%mm7 \n\t"
+                  "por       %%mm7, %%mm6     \n\t"
+                  "movq      %%mm6, 32(%%edi) \n\t"
+
+                  "movq      40(%%esi), %%mm7 \n\t"
+                  "pand      %%mm5, %%mm7     \n\t"
+                  "movq      %%mm5, %%mm6     \n\t"
+                  "pandn     40(%%edi), %%mm6 \n\t"
+                  "por       %%mm6, %%mm7     \n\t"
+                  "movq      %%mm7, 40(%%edi) \n\t"
+
+                  "addl      $48, %%esi       \n\t" // inc by 48 bytes processed
+                  "addl      $48, %%edi       \n\t"
+                  "subl      $8, %%ecx        \n\t" // dec by 8 pixels processed
+
+                  "ja        mainloop48       \n\t"
+
+                "mainloop48end:               \n\t"
+// preload        "movl      diff, %%ecx      \n\t" // (diff is in eax)
+                  "movl      %%eax, %%ecx     \n\t"
+                  "cmpl      $0, %%ecx        \n\t"
+                  "jz        end48            \n\t"
+// preload        "movl      mask, %%edx      \n\t"
+                  "sall      $24, %%edx       \n\t" // make low byte, high byte
+
+                "secondloop48:                \n\t"
+                  "sall      %%edx            \n\t" // move high bit to CF
+                  "jnc       skip48           \n\t" // if CF = 0
+                  "movl      (%%esi), %%eax   \n\t"
+                  "movl      %%eax, (%%edi)   \n\t"
+
+                "skip48:                      \n\t"
+                  "addl      $4, %%esi        \n\t"
+                  "addl      $4, %%edi        \n\t"
+                  "decl      %%ecx            \n\t"
+                  "jnz       secondloop48     \n\t"
+
+                "end48:                       \n\t"
+                  "EMMS                       \n\t" // DONE
+
+                  : "=a" (dummy_value_a),           // output regs (dummy)
+                    "=d" (dummy_value_d),
+                    "=c" (dummy_value_c),
+                    "=S" (dummy_value_S),
+                    "=D" (dummy_value_D)
+
+                  : "3" (srcptr),      // esi       // input regs
+                    "4" (dstptr),      // edi
+                    "0" (diff),        // eax
+// was (unmask)     "b"    RESERVED    // ebx       // Global Offset Table idx
+                    "2" (len),         // ecx
+                    "1" (mask)         // edx
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+                  : "%mm0", "%mm1", "%mm2", "%mm3"  // clobber list
+                  , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+               );
+            }
+            else /* mmx _not supported - Use modified C routine */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               register png_uint_32 i;
+               png_uint_32 initial_val = BPP6 * png_pass_start[png_ptr->pass];
+                 /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+               register int stride = BPP6 * png_pass_inc[png_ptr->pass];
+                 /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+               register int rep_bytes = BPP6 * png_pass_width[png_ptr->pass];
+                 /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+               png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+               int diff = (int) (png_ptr->width & 7); /* amount lost */
+               register png_uint_32 final_val = BPP6 * len;   /* GRR bugfix */
+
+               srcptr = png_ptr->row_buf + 1 + initial_val;
+               dstptr = row + initial_val;
+
+               for (i = initial_val; i < final_val; i += stride)
+               {
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               }
+               if (diff)  /* number of leftover pixels:  3 for pngtest */
+               {
+                  final_val+=diff*BPP6;
+                  for (; i < final_val; i += stride)
+                  {
+                     if (rep_bytes > (int)(final_val-i))
+                        rep_bytes = (int)(final_val-i);
+                     png_memcpy(dstptr, srcptr, rep_bytes);
+                     srcptr += stride;
+                     dstptr += stride;
+                  }
+               }
+            } /* end of else (_mmx_supported) */
+
+            break;
+         }       /* end 48 bpp */
+
+         case 64:       /* png_ptr->row_info.pixel_depth */
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            register png_uint_32 i;
+            png_uint_32 initial_val = BPP8 * png_pass_start[png_ptr->pass];
+              /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
+            register int stride = BPP8 * png_pass_inc[png_ptr->pass];
+              /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
+            register int rep_bytes = BPP8 * png_pass_width[png_ptr->pass];
+              /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
+            png_uint_32 len = png_ptr->width &~7;  /* reduce to mult. of 8 */
+            int diff = (int) (png_ptr->width & 7); /* amount lost */
+            register png_uint_32 final_val = BPP8 * len;   /* GRR bugfix */
+
+            srcptr = png_ptr->row_buf + 1 + initial_val;
+            dstptr = row + initial_val;
+
+            for (i = initial_val; i < final_val; i += stride)
+            {
+               png_memcpy(dstptr, srcptr, rep_bytes);
+               srcptr += stride;
+               dstptr += stride;
+            }
+            if (diff)  /* number of leftover pixels:  3 for pngtest */
+            {
+               final_val+=diff*BPP8;
+               for (; i < final_val; i += stride)
+               {
+                  if (rep_bytes > (int)(final_val-i))
+                     rep_bytes = (int)(final_val-i);
+                  png_memcpy(dstptr, srcptr, rep_bytes);
+                  srcptr += stride;
+                  dstptr += stride;
+               }
+            }
+
+            break;
+         }       /* end 64 bpp */
+
+         default: /* png_ptr->row_info.pixel_depth != 1,2,4,8,16,24,32,48,64 */
+         {
+            /* this should never happen */
+            png_warning(png_ptr, "Invalid row_info.pixel_depth in pnggccrd");
+            break;
+         }
+      } /* end switch (png_ptr->row_info.pixel_depth) */
+
+   } /* end if (non-trivial mask) */
+
+} /* end png_combine_row() */
+
+#endif /* PNG_HAVE_ASSEMBLER_COMBINE_ROW */
+
+
+
+
+/*===========================================================================*/
+/*                                                                           */
+/*                 P N G _ D O _ R E A D _ I N T E R L A C E                 */
+/*                                                                           */
+/*===========================================================================*/
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+#if defined(PNG_HAVE_ASSEMBLER_READ_INTERLACE)
+
+/* png_do_read_interlace() is called after any 16-bit to 8-bit conversion
+ * has taken place.  [GRR: what other steps come before and/or after?]
+ */
+
+void /* PRIVATE */
+png_do_read_interlace(png_structp png_ptr)
+{
+   png_row_infop row_info = &(png_ptr->row_info);
+   png_bytep row = png_ptr->row_buf + 1;
+   int pass = png_ptr->pass;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+   png_uint_32 transformations = png_ptr->transformations;
+#endif
+
+   png_debug(1, "in png_do_read_interlace (pnggccrd.c)\n");
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+   if (_mmx_supported == 2) {
+       /* this should have happened in png_init_mmx_flags() already */
+       png_warning(png_ptr, "asm_flags may not have been initialized");
+       png_mmx_support();
+   }
+#endif
+
+   if (row != NULL && row_info != NULL)
+   {
+      png_uint_32 final_width;
+
+      final_width = row_info->width * png_pass_inc[pass];
+
+      switch (row_info->pixel_depth)
+      {
+         case 1:
+         {
+            png_bytep sp, dp;
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_byte v;
+            png_uint_32 i;
+            int j;
+
+            sp = row + (png_size_t)((row_info->width - 1) >> 3);
+            dp = row + (png_size_t)((final_width - 1) >> 3);
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (int)((row_info->width + 7) & 7);
+               dshift = (int)((final_width + 7) & 7);
+               s_start = 7;
+               s_end = 0;
+               s_inc = -1;
+            }
+            else
+#endif
+            {
+               sshift = 7 - (int)((row_info->width + 7) & 7);
+               dshift = 7 - (int)((final_width + 7) & 7);
+               s_start = 0;
+               s_end = 7;
+               s_inc = 1;
+            }
+
+            for (i = row_info->width; i; i--)
+            {
+               v = (png_byte)((*sp >> sshift) & 0x1);
+               for (j = 0; j < png_pass_inc[pass]; j++)
+               {
+                  *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+
+         case 2:
+         {
+            png_bytep sp, dp;
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_uint_32 i;
+
+            sp = row + (png_size_t)((row_info->width - 1) >> 2);
+            dp = row + (png_size_t)((final_width - 1) >> 2);
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (png_size_t)(((row_info->width + 3) & 3) << 1);
+               dshift = (png_size_t)(((final_width + 3) & 3) << 1);
+               s_start = 6;
+               s_end = 0;
+               s_inc = -2;
+            }
+            else
+#endif
+            {
+               sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1);
+               dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1);
+               s_start = 0;
+               s_end = 6;
+               s_inc = 2;
+            }
+
+            for (i = row_info->width; i; i--)
+            {
+               png_byte v;
+               int j;
+
+               v = (png_byte)((*sp >> sshift) & 0x3);
+               for (j = 0; j < png_pass_inc[pass]; j++)
+               {
+                  *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+
+         case 4:
+         {
+            png_bytep sp, dp;
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_uint_32 i;
+
+            sp = row + (png_size_t)((row_info->width - 1) >> 1);
+            dp = row + (png_size_t)((final_width - 1) >> 1);
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (png_size_t)(((row_info->width + 1) & 1) << 2);
+               dshift = (png_size_t)(((final_width + 1) & 1) << 2);
+               s_start = 4;
+               s_end = 0;
+               s_inc = -4;
+            }
+            else
+#endif
+            {
+               sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2);
+               dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2);
+               s_start = 0;
+               s_end = 4;
+               s_inc = 4;
+            }
+
+            for (i = row_info->width; i; i--)
+            {
+               png_byte v;
+               int j;
+
+               v = (png_byte)((*sp >> sshift) & 0xf);
+               for (j = 0; j < png_pass_inc[pass]; j++)
+               {
+                  *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+
+       /*====================================================================*/
+
+         default: /* 8-bit or larger (this is where the routine is modified) */
+         {
+#if 0
+//          static unsigned long long _const4 = 0x0000000000FFFFFFLL;  no good
+//          static unsigned long long const4 = 0x0000000000FFFFFFLL;   no good
+//          unsigned long long _const4 = 0x0000000000FFFFFFLL;         no good
+//          unsigned long long const4 = 0x0000000000FFFFFFLL;          no good
+#endif
+            png_bytep sptr, dp;
+            png_uint_32 i;
+            png_size_t pixel_bytes;
+            int width = (int)row_info->width;
+
+            pixel_bytes = (row_info->pixel_depth >> 3);
+
+            /* point sptr at the last pixel in the pre-expanded row: */
+            sptr = row + (width - 1) * pixel_bytes;
+
+            /* point dp at the last pixel position in the expanded row: */
+            dp = row + (final_width - 1) * pixel_bytes;
+
+            /* New code by Nirav Chhatrapati - Intel Corporation */
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_INTERLACE)
+                /* && _mmx_supported */ )
+            {
+               //--------------------------------------------------------------
+               if (pixel_bytes == 3)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int dummy_value_c;   // fix 'forbidden register spilled'
+                     int dummy_value_S;
+                     int dummy_value_D;
+
+                     __asm__ __volatile__ (
+                        "subl $21, %%edi         \n\t"
+                                     // (png_pass_inc[pass] - 1)*pixel_bytes
+
+                     ".loop3_pass0:              \n\t"
+                        "movd (%%esi), %%mm0     \n\t" // x x x x x 2 1 0
+                        "pand _const4, %%mm0     \n\t" // z z z z z 2 1 0
+                        "movq %%mm0, %%mm1       \n\t" // z z z z z 2 1 0
+                        "psllq $16, %%mm0        \n\t" // z z z 2 1 0 z z
+                        "movq %%mm0, %%mm2       \n\t" // z z z 2 1 0 z z
+                        "psllq $24, %%mm0        \n\t" // 2 1 0 z z z z z
+                        "psrlq $8, %%mm1         \n\t" // z z z z z z 2 1
+                        "por %%mm2, %%mm0        \n\t" // 2 1 0 2 1 0 z z
+                        "por %%mm1, %%mm0        \n\t" // 2 1 0 2 1 0 2 1
+                        "movq %%mm0, %%mm3       \n\t" // 2 1 0 2 1 0 2 1
+                        "psllq $16, %%mm0        \n\t" // 0 2 1 0 2 1 z z
+                        "movq %%mm3, %%mm4       \n\t" // 2 1 0 2 1 0 2 1
+                        "punpckhdq %%mm0, %%mm3  \n\t" // 0 2 1 0 2 1 0 2
+                        "movq %%mm4, 16(%%edi)   \n\t"
+                        "psrlq $32, %%mm0        \n\t" // z z z z 0 2 1 0
+                        "movq %%mm3, 8(%%edi)    \n\t"
+                        "punpckldq %%mm4, %%mm0  \n\t" // 1 0 2 1 0 2 1 0
+                        "subl $3, %%esi          \n\t"
+                        "movq %%mm0, (%%edi)     \n\t"
+                        "subl $24, %%edi         \n\t"
+                        "decl %%ecx              \n\t"
+                        "jnz .loop3_pass0        \n\t"
+                        "EMMS                    \n\t" // DONE
+
+                        : "=c" (dummy_value_c),        // output regs (dummy)
+                          "=S" (dummy_value_S),
+                          "=D" (dummy_value_D)
+
+                        : "1" (sptr),      // esi      // input regs
+                          "2" (dp),        // edi
+                          "0" (width)      // ecx
+// doesn't work           "i" (0x0000000000FFFFFFLL)   // %1 (a.k.a. _const4)
+
+#if 0  /* %mm0, ..., %mm4 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                        : "%mm0", "%mm1", "%mm2"       // clobber list
+                        , "%mm3", "%mm4"
+#endif
+                     );
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int dummy_value_c;   // fix 'forbidden register spilled'
+                     int dummy_value_S;
+                     int dummy_value_D;
+
+                     __asm__ __volatile__ (
+                        "subl $9, %%edi          \n\t"
+                                     // (png_pass_inc[pass] - 1)*pixel_bytes
+
+                     ".loop3_pass2:              \n\t"
+                        "movd (%%esi), %%mm0     \n\t" // x x x x x 2 1 0
+                        "pand _const4, %%mm0     \n\t" // z z z z z 2 1 0
+                        "movq %%mm0, %%mm1       \n\t" // z z z z z 2 1 0
+                        "psllq $16, %%mm0        \n\t" // z z z 2 1 0 z z
+                        "movq %%mm0, %%mm2       \n\t" // z z z 2 1 0 z z
+                        "psllq $24, %%mm0        \n\t" // 2 1 0 z z z z z
+                        "psrlq $8, %%mm1         \n\t" // z z z z z z 2 1
+                        "por %%mm2, %%mm0        \n\t" // 2 1 0 2 1 0 z z
+                        "por %%mm1, %%mm0        \n\t" // 2 1 0 2 1 0 2 1
+                        "movq %%mm0, 4(%%edi)    \n\t"
+                        "psrlq $16, %%mm0        \n\t" // z z 2 1 0 2 1 0
+                        "subl $3, %%esi          \n\t"
+                        "movd %%mm0, (%%edi)     \n\t"
+                        "subl $12, %%edi         \n\t"
+                        "decl %%ecx              \n\t"
+                        "jnz .loop3_pass2        \n\t"
+                        "EMMS                    \n\t" // DONE
+
+                        : "=c" (dummy_value_c),        // output regs (dummy)
+                          "=S" (dummy_value_S),
+                          "=D" (dummy_value_D)
+
+                        : "1" (sptr),      // esi      // input regs
+                          "2" (dp),        // edi
+                          "0" (width)      // ecx
+
+#if 0  /* %mm0, ..., %mm2 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                        : "%mm0", "%mm1", "%mm2"       // clobber list
+#endif
+                     );
+                  }
+                  else if (width) /* && ((pass == 4) || (pass == 5)) */
+                  {
+                     int width_mmx = ((width >> 1) << 1) - 8;   // GRR:  huh?
+                     if (width_mmx < 0)
+                         width_mmx = 0;
+                     width -= width_mmx;        // 8 or 9 pix, 24 or 27 bytes
+                     if (width_mmx)
+                     {
+                        // png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+                        // sptr points at last pixel in pre-expanded row
+                        // dp points at last pixel position in expanded row
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $3, %%esi          \n\t"
+                           "subl $9, %%edi          \n\t"
+                                        // (png_pass_inc[pass] + 1)*pixel_bytes
+
+                        ".loop3_pass4:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // x x 5 4 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // x x 5 4 3 2 1 0
+                           "movq %%mm0, %%mm2       \n\t" // x x 5 4 3 2 1 0
+                           "psllq $24, %%mm0        \n\t" // 4 3 2 1 0 z z z
+                           "pand _const4, %%mm1     \n\t" // z z z z z 2 1 0
+                           "psrlq $24, %%mm2        \n\t" // z z z x x 5 4 3
+                           "por %%mm1, %%mm0        \n\t" // 4 3 2 1 0 2 1 0
+                           "movq %%mm2, %%mm3       \n\t" // z z z x x 5 4 3
+                           "psllq $8, %%mm2         \n\t" // z z x x 5 4 3 z
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "psrlq $16, %%mm3        \n\t" // z z z z z x x 5
+                           "pand _const6, %%mm3     \n\t" // z z z z z z z 5
+                           "por %%mm3, %%mm2        \n\t" // z z x x 5 4 3 5
+                           "subl $6, %%esi          \n\t"
+                           "movd %%mm2, 8(%%edi)    \n\t"
+                           "subl $12, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop3_pass4        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, ..., %mm3 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+                           , "%mm2", "%mm3"
+#endif
+                        );
+                     }
+
+                     sptr -= width_mmx*3;
+                     dp -= width_mmx*6;
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+
+                        png_memcpy(v, sptr, 3);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           png_memcpy(dp, v, 3);
+                           dp -= 3;
+                        }
+                        sptr -= 3;
+                     }
+                  }
+               } /* end of pixel_bytes == 3 */
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 1)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int width_mmx = ((width >> 2) << 2);
+                     width -= width_mmx;        // 0-3 pixels => 0-3 bytes
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $3, %%esi          \n\t"
+                           "subl $31, %%edi         \n\t"
+
+                        ".loop1_pass0:              \n\t"
+                           "movd (%%esi), %%mm0     \n\t" // x x x x 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // x x x x 3 2 1 0
+                           "punpcklbw %%mm0, %%mm0  \n\t" // 3 3 2 2 1 1 0 0
+                           "movq %%mm0, %%mm2       \n\t" // 3 3 2 2 1 1 0 0
+                           "punpcklwd %%mm0, %%mm0  \n\t" // 1 1 1 1 0 0 0 0
+                           "movq %%mm0, %%mm3       \n\t" // 1 1 1 1 0 0 0 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 0 0 0 0 0 0 0 0
+                           "punpckhdq %%mm3, %%mm3  \n\t" // 1 1 1 1 1 1 1 1
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "punpckhwd %%mm2, %%mm2  \n\t" // 3 3 3 3 2 2 2 2
+                           "movq %%mm3, 8(%%edi)    \n\t"
+                           "movq %%mm2, %%mm4       \n\t" // 3 3 3 3 2 2 2 2
+                           "punpckldq %%mm2, %%mm2  \n\t" // 2 2 2 2 2 2 2 2
+                           "punpckhdq %%mm4, %%mm4  \n\t" // 3 3 3 3 3 3 3 3
+                           "movq %%mm2, 16(%%edi)   \n\t"
+                           "subl $4, %%esi          \n\t"
+                           "movq %%mm4, 24(%%edi)   \n\t"
+                           "subl $32, %%edi         \n\t"
+                           "subl $4, %%ecx          \n\t"
+                           "jnz .loop1_pass0        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, ..., %mm4 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1", "%mm2"       // clobber list
+                           , "%mm3", "%mm4"
+#endif
+                        );
+                     }
+
+                     sptr -= width_mmx;
+                     dp -= width_mmx*8;
+                     for (i = width; i; i--)
+                     {
+                        int j;
+
+                       /* I simplified this part in version 1.0.4e
+                        * here and in several other instances where
+                        * pixel_bytes == 1  -- GR-P
+                        *
+                        * Original code:
+                        *
+                        * png_byte v[8];
+                        * png_memcpy(v, sptr, pixel_bytes);
+                        * for (j = 0; j < png_pass_inc[pass]; j++)
+                        * {
+                        *    png_memcpy(dp, v, pixel_bytes);
+                        *    dp -= pixel_bytes;
+                        * }
+                        * sptr -= pixel_bytes;
+                        *
+                        * Replacement code is in the next three lines:
+                        */
+
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           *dp-- = *sptr;
+                        }
+                        --sptr;
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int width_mmx = ((width >> 2) << 2);
+                     width -= width_mmx;        // 0-3 pixels => 0-3 bytes
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $3, %%esi          \n\t"
+                           "subl $15, %%edi         \n\t"
+
+                        ".loop1_pass2:              \n\t"
+                           "movd (%%esi), %%mm0     \n\t" // x x x x 3 2 1 0
+                           "punpcklbw %%mm0, %%mm0  \n\t" // 3 3 2 2 1 1 0 0
+                           "movq %%mm0, %%mm1       \n\t" // 3 3 2 2 1 1 0 0
+                           "punpcklwd %%mm0, %%mm0  \n\t" // 1 1 1 1 0 0 0 0
+                           "punpckhwd %%mm1, %%mm1  \n\t" // 3 3 3 3 2 2 2 2
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $4, %%esi          \n\t"
+                           "movq %%mm1, 8(%%edi)    \n\t"
+                           "subl $16, %%edi         \n\t"
+                           "subl $4, %%ecx          \n\t"
+                           "jnz .loop1_pass2        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#endif
+                        );
+                     }
+
+                     sptr -= width_mmx;
+                     dp -= width_mmx*4;
+                     for (i = width; i; i--)
+                     {
+                        int j;
+
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           *dp-- = *sptr;
+                        }
+                        --sptr;
+                     }
+                  }
+                  else if (width)  /* && ((pass == 4) || (pass == 5)) */
+                  {
+                     int width_mmx = ((width >> 3) << 3);
+                     width -= width_mmx;        // 0-3 pixels => 0-3 bytes
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $7, %%esi          \n\t"
+                           "subl $15, %%edi         \n\t"
+
+                        ".loop1_pass4:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 7 6 5 4 3 2 1 0
+                           "punpcklbw %%mm0, %%mm0  \n\t" // 3 3 2 2 1 1 0 0
+                           "punpckhbw %%mm1, %%mm1  \n\t" // 7 7 6 6 5 5 4 4
+                           "movq %%mm1, 8(%%edi)    \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $16, %%edi         \n\t"
+                           "subl $8, %%ecx          \n\t"
+                           "jnz .loop1_pass4        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (none)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#endif
+                        );
+                     }
+
+                     sptr -= width_mmx;
+                     dp -= width_mmx*2;
+                     for (i = width; i; i--)
+                     {
+                        int j;
+
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           *dp-- = *sptr;
+                        }
+                        --sptr;
+                     }
+                  }
+               } /* end of pixel_bytes == 1 */
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 2)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1);
+                     width -= width_mmx;        // 0,1 pixels => 0,2 bytes
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $2, %%esi          \n\t"
+                           "subl $30, %%edi         \n\t"
+
+                        ".loop2_pass0:              \n\t"
+                           "movd (%%esi), %%mm0     \n\t" // x x x x 3 2 1 0
+                           "punpcklwd %%mm0, %%mm0  \n\t" // 3 2 3 2 1 0 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 3 2 3 2 1 0 1 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 1 0 1 0 1 0 1 0
+                           "punpckhdq %%mm1, %%mm1  \n\t" // 3 2 3 2 3 2 3 2
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "movq %%mm1, 16(%%edi)   \n\t"
+                           "subl $4, %%esi          \n\t"
+                           "movq %%mm1, 24(%%edi)   \n\t"
+                           "subl $32, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop2_pass0        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*2 - 2); // sign fixed
+                     dp -= (width_mmx*16 - 2);  // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 2;
+                        png_memcpy(v, sptr, 2);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 2;
+                           png_memcpy(dp, v, 2);
+                        }
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;        // 0,1 pixels => 0,2 bytes
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $2, %%esi          \n\t"
+                           "subl $14, %%edi         \n\t"
+
+                        ".loop2_pass2:              \n\t"
+                           "movd (%%esi), %%mm0     \n\t" // x x x x 3 2 1 0
+                           "punpcklwd %%mm0, %%mm0  \n\t" // 3 2 3 2 1 0 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 3 2 3 2 1 0 1 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 1 0 1 0 1 0 1 0
+                           "punpckhdq %%mm1, %%mm1  \n\t" // 3 2 3 2 3 2 3 2
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $4, %%esi          \n\t"
+                           "movq %%mm1, 8(%%edi)    \n\t"
+                           "subl $16, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop2_pass2        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*2 - 2); // sign fixed
+                     dp -= (width_mmx*8 - 2);   // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 2;
+                        png_memcpy(v, sptr, 2);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 2;
+                           png_memcpy(dp, v, 2);
+                        }
+                     }
+                  }
+                  else if (width)  // pass == 4 or 5
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;        // 0,1 pixels => 0,2 bytes
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $2, %%esi          \n\t"
+                           "subl $6, %%edi          \n\t"
+
+                        ".loop2_pass4:              \n\t"
+                           "movd (%%esi), %%mm0     \n\t" // x x x x 3 2 1 0
+                           "punpcklwd %%mm0, %%mm0  \n\t" // 3 2 3 2 1 0 1 0
+                           "subl $4, %%esi          \n\t"
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $8, %%edi          \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop2_pass4        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0"                       // clobber list
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*2 - 2); // sign fixed
+                     dp -= (width_mmx*4 - 2);   // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 2;
+                        png_memcpy(v, sptr, 2);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 2;
+                           png_memcpy(dp, v, 2);
+                        }
+                     }
+                  }
+               } /* end of pixel_bytes == 2 */
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 4)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1);
+                     width -= width_mmx;        // 0,1 pixels => 0,4 bytes
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $4, %%esi          \n\t"
+                           "subl $60, %%edi         \n\t"
+
+                        ".loop4_pass0:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 7 6 5 4 3 2 1 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 3 2 1 0 3 2 1 0
+                           "punpckhdq %%mm1, %%mm1  \n\t" // 7 6 5 4 7 6 5 4
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "movq %%mm0, 16(%%edi)   \n\t"
+                           "movq %%mm0, 24(%%edi)   \n\t"
+                           "movq %%mm1, 32(%%edi)   \n\t"
+                           "movq %%mm1, 40(%%edi)   \n\t"
+                           "movq %%mm1, 48(%%edi)   \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm1, 56(%%edi)   \n\t"
+                           "subl $64, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop4_pass0        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*4 - 4); // sign fixed
+                     dp -= (width_mmx*32 - 4);  // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 4;
+                        png_memcpy(v, sptr, 4);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 4;
+                           png_memcpy(dp, v, 4);
+                        }
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1);
+                     width -= width_mmx;        // 0,1 pixels => 0,4 bytes
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $4, %%esi          \n\t"
+                           "subl $28, %%edi         \n\t"
+
+                        ".loop4_pass2:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 7 6 5 4 3 2 1 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 3 2 1 0 3 2 1 0
+                           "punpckhdq %%mm1, %%mm1  \n\t" // 7 6 5 4 7 6 5 4
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "movq %%mm1, 16(%%edi)   \n\t"
+                           "movq %%mm1, 24(%%edi)   \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "subl $32, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop4_pass2        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*4 - 4); // sign fixed
+                     dp -= (width_mmx*16 - 4);  // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 4;
+                        png_memcpy(v, sptr, 4);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 4;
+                           png_memcpy(dp, v, 4);
+                        }
+                     }
+                  }
+                  else if (width)  // pass == 4 or 5
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;        // 0,1 pixels => 0,4 bytes
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $4, %%esi          \n\t"
+                           "subl $12, %%edi         \n\t"
+
+                        ".loop4_pass4:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, %%mm1       \n\t" // 7 6 5 4 3 2 1 0
+                           "punpckldq %%mm0, %%mm0  \n\t" // 3 2 1 0 3 2 1 0
+                           "punpckhdq %%mm1, %%mm1  \n\t" // 7 6 5 4 7 6 5 4
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm1, 8(%%edi)    \n\t"
+                           "subl $16, %%edi         \n\t"
+                           "subl $2, %%ecx          \n\t"
+                           "jnz .loop4_pass4        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width_mmx)  // ecx
+
+#if 0  /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0", "%mm1"               // clobber list
+#endif
+                        );
+                     }
+
+                     sptr -= (width_mmx*4 - 4); // sign fixed
+                     dp -= (width_mmx*8 - 4);   // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 4;
+                        png_memcpy(v, sptr, 4);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 4;
+                           png_memcpy(dp, v, 4);
+                        }
+                     }
+                  }
+               } /* end of pixel_bytes == 4 */
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 8)
+               {
+// GRR TEST:  should work, but needs testing (special 64-bit version of rpng2?)
+                  // GRR NOTE:  no need to combine passes here!
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int dummy_value_c;  // fix 'forbidden register spilled'
+                     int dummy_value_S;
+                     int dummy_value_D;
+
+                     // source is 8-byte RRGGBBAA
+                     // dest is 64-byte RRGGBBAA RRGGBBAA RRGGBBAA RRGGBBAA ...
+                     __asm__ __volatile__ (
+                        "subl $56, %%edi         \n\t" // start of last block
+
+                     ".loop8_pass0:              \n\t"
+                        "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                        "movq %%mm0, (%%edi)     \n\t"
+                        "movq %%mm0, 8(%%edi)    \n\t"
+                        "movq %%mm0, 16(%%edi)   \n\t"
+                        "movq %%mm0, 24(%%edi)   \n\t"
+                        "movq %%mm0, 32(%%edi)   \n\t"
+                        "movq %%mm0, 40(%%edi)   \n\t"
+                        "movq %%mm0, 48(%%edi)   \n\t"
+                        "subl $8, %%esi          \n\t"
+                        "movq %%mm0, 56(%%edi)   \n\t"
+                        "subl $64, %%edi         \n\t"
+                        "decl %%ecx              \n\t"
+                        "jnz .loop8_pass0        \n\t"
+                        "EMMS                    \n\t" // DONE
+
+                        : "=c" (dummy_value_c),        // output regs (dummy)
+                          "=S" (dummy_value_S),
+                          "=D" (dummy_value_D)
+
+                        : "1" (sptr),      // esi      // input regs
+                          "2" (dp),        // edi
+                          "0" (width)      // ecx
+
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                        : "%mm0"                       // clobber list
+#endif
+                     );
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     // source is 8-byte RRGGBBAA
+                     // dest is 32-byte RRGGBBAA RRGGBBAA RRGGBBAA RRGGBBAA
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $24, %%edi         \n\t" // start of last block
+
+                        ".loop8_pass2:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "movq %%mm0, 16(%%edi)   \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm0, 24(%%edi)   \n\t"
+                           "subl $32, %%edi         \n\t"
+                           "decl %%ecx              \n\t"
+                           "jnz .loop8_pass2        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width)      // ecx
+
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0"                       // clobber list
+#endif
+                        );
+                     }
+                  }
+                  else if (width)  // pass == 4 or 5
+                  {
+                     // source is 8-byte RRGGBBAA
+                     // dest is 16-byte RRGGBBAA RRGGBBAA
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        int dummy_value_c;  // fix 'forbidden register spilled'
+                        int dummy_value_S;
+                        int dummy_value_D;
+
+                        __asm__ __volatile__ (
+                           "subl $8, %%edi          \n\t" // start of last block
+
+                        ".loop8_pass4:              \n\t"
+                           "movq (%%esi), %%mm0     \n\t" // 7 6 5 4 3 2 1 0
+                           "movq %%mm0, (%%edi)     \n\t"
+                           "subl $8, %%esi          \n\t"
+                           "movq %%mm0, 8(%%edi)    \n\t"
+                           "subl $16, %%edi         \n\t"
+                           "decl %%ecx              \n\t"
+                           "jnz .loop8_pass4        \n\t"
+                           "EMMS                    \n\t" // DONE
+
+                           : "=c" (dummy_value_c),        // output regs (dummy)
+                             "=S" (dummy_value_S),
+                             "=D" (dummy_value_D)
+
+                           : "1" (sptr),      // esi      // input regs
+                             "2" (dp),        // edi
+                             "0" (width)      // ecx
+
+#if 0  /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */
+                           : "%mm0"                       // clobber list
+#endif
+                        );
+                     }
+                  }
+
+               } /* end of pixel_bytes == 8 */
+
+               //--------------------------------------------------------------
+               else if (pixel_bytes == 6)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 6);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 6);
+                        dp -= 6;
+                     }
+                     sptr -= 6;
+                  }
+               } /* end of pixel_bytes == 6 */
+
+               //--------------------------------------------------------------
+               else
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr-= pixel_bytes;
+                  }
+               }
+            } // end of _mmx_supported ========================================
+
+            else /* MMX not supported:  use modified C code - takes advantage
+                  *   of inlining of png_memcpy for a constant */
+                 /* GRR 19991007:  does it?  or should pixel_bytes in each
+                  *   block be replaced with immediate value (e.g., 1)? */
+                 /* GRR 19991017:  replaced with constants in each case */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+            {
+               if (pixel_bytes == 1)
+               {
+                  for (i = width; i; i--)
+                  {
+                     int j;
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        *dp-- = *sptr;
+                     }
+                     --sptr;
+                  }
+               }
+               else if (pixel_bytes == 3)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 3);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 3);
+                        dp -= 3;
+                     }
+                     sptr -= 3;
+                  }
+               }
+               else if (pixel_bytes == 2)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 2);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 2);
+                        dp -= 2;
+                     }
+                     sptr -= 2;
+                  }
+               }
+               else if (pixel_bytes == 4)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 4);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+#ifdef PNG_DEBUG
+                        if (dp < row || dp+3 > row+png_ptr->row_buf_size)
+                        {
+                           printf("dp out of bounds: row=%d, dp=%d, rp=%d\n",
+                             row, dp, row+png_ptr->row_buf_size);
+                           printf("row_buf=%d\n",png_ptr->row_buf_size);
+                        }
+#endif
+                        png_memcpy(dp, v, 4);
+                        dp -= 4;
+                     }
+                     sptr -= 4;
+                  }
+               }
+               else if (pixel_bytes == 6)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 6);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 6);
+                        dp -= 6;
+                     }
+                     sptr -= 6;
+                  }
+               }
+               else if (pixel_bytes == 8)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 8);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 8);
+                        dp -= 8;
+                     }
+                     sptr -= 8;
+                  }
+               }
+               else     /* GRR:  should never be reached */
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr -= pixel_bytes;
+                  }
+               }
+
+            } /* end if (MMX not supported) */
+            break;
+         }
+      } /* end switch (row_info->pixel_depth) */
+
+      row_info->width = final_width;
+      row_info->rowbytes = ((final_width *
+         (png_uint_32)row_info->pixel_depth + 7) >> 3);
+   }
+
+} /* end png_do_read_interlace() */
+
+#endif /* PNG_HAVE_ASSEMBLER_READ_INTERLACE */
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+
+
+
+#if defined(PNG_HAVE_ASSEMBLER_READ_FILTER_ROW)
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+
+// These variables are utilized in the functions below.  They are declared
+// globally here to ensure alignment on 8-byte boundaries.
+
+union uAll {
+   long long use;
+   double  align;
+} _LBCarryMask = {0x0101010101010101LL},
+  _HBClearMask = {0x7f7f7f7f7f7f7f7fLL},
+  _ActiveMask, _ActiveMask2, _ActiveMaskEnd, _ShiftBpp, _ShiftRem;
+
+#ifdef PNG_THREAD_UNSAFE_OK
+//===========================================================================//
+//                                                                           //
+//           P N G _ R E A D _ F I L T E R _ R O W _ M M X _ A V G           //
+//                                                                           //
+//===========================================================================//
+
+// Optimized code for PNG Average filter decoder
+
+static void /* PRIVATE */
+png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row,
+                            png_bytep prev_row)
+{
+   int bpp;
+   int dummy_value_c;   // fix 'forbidden register 2 (cx) was spilled' error
+   int dummy_value_S;
+   int dummy_value_D;
+
+   bpp = (row_info->pixel_depth + 7) >> 3;  // get # bytes per pixel
+   _FullLength  = row_info->rowbytes;       // # of bytes to filter
+
+   __asm__ __volatile__ (
+      // initialize address pointers and offset
+#ifdef __PIC__
+      "pushl %%ebx                 \n\t" // save index to Global Offset Table
+#endif
+//pre "movl row, %%edi             \n\t" // edi:  Avg(x)
+      "xorl %%ebx, %%ebx           \n\t" // ebx:  x
+      "movl %%edi, %%edx           \n\t"
+//pre "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+//pre "subl bpp, %%edx             \n\t" // (bpp is preloaded into ecx)
+      "subl %%ecx, %%edx           \n\t" // edx:  Raw(x-bpp)
+
+      "xorl %%eax,%%eax            \n\t"
+
+      // Compute the Raw value for the first bpp bytes
+      //    Raw(x) = Avg(x) + (Prior(x)/2)
+   "avg_rlp:                       \n\t"
+      "movb (%%esi,%%ebx,),%%al    \n\t" // load al with Prior(x)
+      "incl %%ebx                  \n\t"
+      "shrb %%al                   \n\t" // divide by 2
+      "addb -1(%%edi,%%ebx,),%%al  \n\t" // add Avg(x); -1 to offset inc ebx
+//pre "cmpl bpp, %%ebx             \n\t" // (bpp is preloaded into ecx)
+      "cmpl %%ecx, %%ebx           \n\t"
+      "movb %%al,-1(%%edi,%%ebx,)  \n\t" // write Raw(x); -1 to offset inc ebx
+      "jb avg_rlp                  \n\t" // mov does not affect flags
+
+      // get # of bytes to alignment
+      "movl %%edi, _dif            \n\t" // take start of row
+      "addl %%ebx, _dif            \n\t" // add bpp
+      "addl $0xf, _dif             \n\t" // add 7+8 to incr past alignment bdry
+      "andl $0xfffffff8, _dif      \n\t" // mask to alignment boundary
+      "subl %%edi, _dif            \n\t" // subtract from start => value ebx at
+      "jz avg_go                   \n\t" //  alignment
+
+      // fix alignment
+      // Compute the Raw value for the bytes up to the alignment boundary
+      //    Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+      "xorl %%ecx, %%ecx           \n\t"
+
+   "avg_lp1:                       \n\t"
+      "xorl %%eax, %%eax           \n\t"
+      "movb (%%esi,%%ebx,), %%cl   \n\t" // load cl with Prior(x)
+      "movb (%%edx,%%ebx,), %%al   \n\t" // load al with Raw(x-bpp)
+      "addw %%cx, %%ax             \n\t"
+      "incl %%ebx                  \n\t"
+      "shrw %%ax                   \n\t" // divide by 2
+      "addb -1(%%edi,%%ebx,), %%al \n\t" // add Avg(x); -1 to offset inc ebx
+      "cmpl _dif, %%ebx            \n\t" // check if at alignment boundary
+      "movb %%al, -1(%%edi,%%ebx,) \n\t" // write Raw(x); -1 to offset inc ebx
+      "jb avg_lp1                  \n\t" // repeat until at alignment boundary
+
+   "avg_go:                        \n\t"
+      "movl _FullLength, %%eax     \n\t"
+      "movl %%eax, %%ecx           \n\t"
+      "subl %%ebx, %%eax           \n\t" // subtract alignment fix
+      "andl $0x00000007, %%eax     \n\t" // calc bytes over mult of 8
+      "subl %%eax, %%ecx           \n\t" // drop over bytes from original length
+      "movl %%ecx, _MMXLength      \n\t"
+#ifdef __PIC__
+      "popl %%ebx                  \n\t" // restore index to Global Offset Table
+#endif
+
+      : "=c" (dummy_value_c),            // output regs (dummy)
+        "=S" (dummy_value_S),
+        "=D" (dummy_value_D)
+
+      : "0" (bpp),       // ecx          // input regs
+        "1" (prev_row),  // esi
+        "2" (row)        // edi
+
+      : "%eax", "%edx"                   // clobber list
+#ifndef __PIC__
+      , "%ebx"
+#endif
+      // GRR: INCLUDE "memory" as clobbered? (_dif, _MMXLength)
+      // (seems to work fine without...)
+   );
+
+   // now do the math for the rest of the row
+   switch (bpp)
+   {
+      case 3:
+      {
+         _ActiveMask.use  = 0x0000000000ffffffLL;
+         _ShiftBpp.use = 24;    // == 3 * 8
+         _ShiftRem.use = 40;    // == 64 - 24
+
+         __asm__ __volatile__ (
+            // re-init address pointers and offset
+            "movq _ActiveMask, %%mm7      \n\t"
+            "movl _dif, %%ecx             \n\t" // ecx:  x = offset to
+            "movq _LBCarryMask, %%mm5     \n\t" //  alignment boundary
+// preload  "movl row, %%edi              \n\t" // edi:  Avg(x)
+            "movq _HBClearMask, %%mm4     \n\t"
+// preload  "movl prev_row, %%esi         \n\t" // esi:  Prior(x)
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes
+                                                // (correct pos. in loop below)
+         "avg_3lp:                        \n\t"
+            "movq (%%edi,%%ecx,), %%mm0   \n\t" // load mm0 with Avg(x)
+            "movq %%mm5, %%mm3            \n\t"
+            "psrlq _ShiftRem, %%mm2       \n\t" // correct position Raw(x-bpp)
+                                                // data
+            "movq (%%esi,%%ecx,), %%mm1   \n\t" // load mm1 with Prior(x)
+            "movq %%mm7, %%mm6            \n\t"
+            "pand %%mm1, %%mm3            \n\t" // get lsb for each prev_row byte
+            "psrlq $1, %%mm1              \n\t" // divide prev_row bytes by 2
+            "pand  %%mm4, %%mm1           \n\t" // clear invalid bit 7 of each
+                                                // byte
+            "paddb %%mm1, %%mm0           \n\t" // add (Prev_row/2) to Avg for
+                                                // each byte
+            // add 1st active group (Raw(x-bpp)/2) to average with LBCarry
+            "movq %%mm3, %%mm1            \n\t" // now use mm1 for getting
+                                                // LBCarrys
+            "pand %%mm2, %%mm1            \n\t" // get LBCarrys for each byte
+                                                // where both
+                               // lsb's were == 1 (only valid for active group)
+            "psrlq $1, %%mm2              \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2           \n\t" // clear invalid bit 7 of each
+                                                // byte
+            "paddb %%mm1, %%mm2           \n\t" // add LBCarrys to (Raw(x-bpp)/2)
+                                                // for each byte
+            "pand %%mm6, %%mm2            \n\t" // leave only Active Group 1
+                                                // bytes to add to Avg
+            "paddb %%mm2, %%mm0           \n\t" // add (Raw/2) + LBCarrys to
+                                                // Avg for each Active
+                               //  byte
+            // add 2nd active group (Raw(x-bpp)/2) to average with _LBCarry
+            "psllq _ShiftBpp, %%mm6       \n\t" // shift the mm6 mask to cover
+                                                // bytes 3-5
+            "movq %%mm0, %%mm2            \n\t" // mov updated Raws to mm2
+            "psllq _ShiftBpp, %%mm2       \n\t" // shift data to pos. correctly
+            "movq %%mm3, %%mm1            \n\t" // now use mm1 for getting
+                                                // LBCarrys
+            "pand %%mm2, %%mm1            \n\t" // get LBCarrys for each byte
+                                                // where both
+                               // lsb's were == 1 (only valid for active group)
+            "psrlq $1, %%mm2              \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2           \n\t" // clear invalid bit 7 of each
+                                                // byte
+            "paddb %%mm1, %%mm2           \n\t" // add LBCarrys to (Raw(x-bpp)/2)
+                                                // for each byte
+            "pand %%mm6, %%mm2            \n\t" // leave only Active Group 2
+                                                // bytes to add to Avg
+            "paddb %%mm2, %%mm0           \n\t" // add (Raw/2) + LBCarrys to
+                                                // Avg for each Active
+                               //  byte
+
+            // add 3rd active group (Raw(x-bpp)/2) to average with _LBCarry
+            "psllq _ShiftBpp, %%mm6       \n\t" // shift mm6 mask to cover last
+                                                // two
+                                 // bytes
+            "movq %%mm0, %%mm2            \n\t" // mov updated Raws to mm2
+            "psllq _ShiftBpp, %%mm2       \n\t" // shift data to pos. correctly
+                              // Data only needs to be shifted once here to
+                              // get the correct x-bpp offset.
+            "movq %%mm3, %%mm1            \n\t" // now use mm1 for getting
+                                                // LBCarrys
+            "pand %%mm2, %%mm1            \n\t" // get LBCarrys for each byte
+                                                // where both
+                              // lsb's were == 1 (only valid for active group)
+            "psrlq $1, %%mm2              \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2           \n\t" // clear invalid bit 7 of each
+                                                // byte
+            "paddb %%mm1, %%mm2           \n\t" // add LBCarrys to (Raw(x-bpp)/2)
+                                                // for each byte
+            "pand %%mm6, %%mm2            \n\t" // leave only Active Group 2
+                                                // bytes to add to Avg
+            "addl $8, %%ecx               \n\t"
+            "paddb %%mm2, %%mm0           \n\t" // add (Raw/2) + LBCarrys to
+                                                // Avg for each Active
+                                                // byte
+            // now ready to write back to memory
+            "movq %%mm0, -8(%%edi,%%ecx,) \n\t"
+            // move updated Raw(x) to use as Raw(x-bpp) for next loop
+            "cmpl _MMXLength, %%ecx       \n\t"
+            "movq %%mm0, %%mm2            \n\t" // mov updated Raw(x) to mm2
+            "jb avg_3lp                   \n\t"
+
+            : "=S" (dummy_value_S),             // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi           // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                            // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 3 bpp
+
+      case 6:
+      case 4:
+      //case 7:   // who wrote this?  PNG doesn't support 5 or 7 bytes/pixel
+      //case 5:   // GRR BOGUS
+      {
+         _ActiveMask.use  = 0xffffffffffffffffLL; // use shift below to clear
+                                                  // appropriate inactive bytes
+         _ShiftBpp.use = bpp << 3;
+         _ShiftRem.use = 64 - _ShiftBpp.use;
+
+         __asm__ __volatile__ (
+            "movq _HBClearMask, %%mm4    \n\t"
+
+            // re-init address pointers and offset
+            "movl _dif, %%ecx            \n\t" // ecx:  x = offset to
+                                               // alignment boundary
+
+            // load _ActiveMask and clear all bytes except for 1st active group
+            "movq _ActiveMask, %%mm7     \n\t"
+// preload  "movl row, %%edi             \n\t" // edi:  Avg(x)
+            "psrlq _ShiftRem, %%mm7      \n\t"
+// preload  "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+            "movq %%mm7, %%mm6           \n\t"
+            "movq _LBCarryMask, %%mm5    \n\t"
+            "psllq _ShiftBpp, %%mm6      \n\t" // create mask for 2nd active
+                                               // group
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes
+                                          // (we correct pos. in loop below)
+         "avg_4lp:                       \n\t"
+            "movq (%%edi,%%ecx,), %%mm0  \n\t"
+            "psrlq _ShiftRem, %%mm2      \n\t" // shift data to pos. correctly
+            "movq (%%esi,%%ecx,), %%mm1  \n\t"
+            // add (Prev_row/2) to average
+            "movq %%mm5, %%mm3           \n\t"
+            "pand %%mm1, %%mm3           \n\t" // get lsb for each prev_row byte
+            "psrlq $1, %%mm1             \n\t" // divide prev_row bytes by 2
+            "pand  %%mm4, %%mm1          \n\t" // clear invalid bit 7 of each
+                                               // byte
+            "paddb %%mm1, %%mm0          \n\t" // add (Prev_row/2) to Avg for
+                                               // each byte
+            // add 1st active group (Raw(x-bpp)/2) to average with _LBCarry
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting
+                                               // LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte
+                                               // where both
+                              // lsb's were == 1 (only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each
+                                               // byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2)
+                                               // for each byte
+            "pand %%mm7, %%mm2           \n\t" // leave only Active Group 1
+                                               // bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg
+                                               // for each Active
+                              // byte
+            // add 2nd active group (Raw(x-bpp)/2) to average with _LBCarry
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq _ShiftBpp, %%mm2      \n\t" // shift data to pos. correctly
+            "addl $8, %%ecx              \n\t"
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting
+                                               // LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte
+                                               // where both
+                              // lsb's were == 1 (only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each
+                                               // byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2)
+                                               // for each byte
+            "pand %%mm6, %%mm2           \n\t" // leave only Active Group 2
+                                               // bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to
+                                               // Avg for each Active
+                              // byte
+            "cmpl _MMXLength, %%ecx      \n\t"
+            // now ready to write back to memory
+            "movq %%mm0, -8(%%edi,%%ecx,) \n\t"
+            // prep Raw(x-bpp) for next loop
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "jb avg_4lp                  \n\t"
+
+            : "=S" (dummy_value_S),            // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi          // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                           // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 4,6 bpp
+
+      case 2:
+      {
+         _ActiveMask.use  = 0x000000000000ffffLL;
+         _ShiftBpp.use = 16;   // == 2 * 8
+         _ShiftRem.use = 48;   // == 64 - 16
+
+         __asm__ __volatile__ (
+            // load _ActiveMask
+            "movq _ActiveMask, %%mm7     \n\t"
+            // re-init address pointers and offset
+            "movl _dif, %%ecx            \n\t" // ecx:  x = offset to alignment
+                                               // boundary
+            "movq _LBCarryMask, %%mm5    \n\t"
+// preload  "movl row, %%edi             \n\t" // edi:  Avg(x)
+            "movq _HBClearMask, %%mm4    \n\t"
+// preload  "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes
+                              // (we correct pos. in loop below)
+         "avg_2lp:                       \n\t"
+            "movq (%%edi,%%ecx,), %%mm0  \n\t"
+            "psrlq _ShiftRem, %%mm2      \n\t" // shift data to pos. correctly
+            "movq (%%esi,%%ecx,), %%mm1  \n\t" //  (GRR BUGFIX:  was psllq)
+            // add (Prev_row/2) to average
+            "movq %%mm5, %%mm3           \n\t"
+            "pand %%mm1, %%mm3           \n\t" // get lsb for each prev_row byte
+            "psrlq $1, %%mm1             \n\t" // divide prev_row bytes by 2
+            "pand  %%mm4, %%mm1          \n\t" // clear invalid bit 7 of each
+                                               // byte
+            "movq %%mm7, %%mm6           \n\t"
+            "paddb %%mm1, %%mm0          \n\t" // add (Prev_row/2) to Avg for
+                                               // each byte
+
+            // add 1st active group (Raw(x-bpp)/2) to average with _LBCarry
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting
+                                               // LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte
+                                               // where both
+                                               // lsb's were == 1 (only valid
+                                               // for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each
+                                               // byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2)
+                                               // for each byte
+            "pand %%mm6, %%mm2           \n\t" // leave only Active Group 1
+                                               // bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to Avg
+                                               // for each Active byte
+
+            // add 2nd active group (Raw(x-bpp)/2) to average with _LBCarry
+            "psllq _ShiftBpp, %%mm6      \n\t" // shift the mm6 mask to cover
+                                               // bytes 2 & 3
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq _ShiftBpp, %%mm2      \n\t" // shift data to pos. correctly
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting
+                                               // LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte
+                                               // where both
+                                               // lsb's were == 1 (only valid
+                                               // for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each
+                                               // byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2)
+                                               // for each byte
+            "pand %%mm6, %%mm2           \n\t" // leave only Active Group 2
+                                               // bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to
+                                               // Avg for each Active byte
+
+            // add 3rd active group (Raw(x-bpp)/2) to average with _LBCarry
+            "psllq _ShiftBpp, %%mm6      \n\t" // shift the mm6 mask to cover
+                                               // bytes 4 & 5
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq _ShiftBpp, %%mm2      \n\t" // shift data to pos. correctly
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting
+                                               // LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte
+                                               // where both lsb's were == 1
+                                               // (only valid for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each
+                                               // byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2)
+                                               // for each byte
+            "pand %%mm6, %%mm2           \n\t" // leave only Active Group 2
+                                               // bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to
+                                               // Avg for each Active byte
+
+            // add 4th active group (Raw(x-bpp)/2) to average with _LBCarry
+            "psllq _ShiftBpp, %%mm6      \n\t" // shift the mm6 mask to cover
+                                               // bytes 6 & 7
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "psllq _ShiftBpp, %%mm2      \n\t" // shift data to pos. correctly
+            "addl $8, %%ecx              \n\t"
+            "movq %%mm3, %%mm1           \n\t" // now use mm1 for getting
+                                               // LBCarrys
+            "pand %%mm2, %%mm1           \n\t" // get LBCarrys for each byte
+                                               // where both
+                                               // lsb's were == 1 (only valid
+                                               // for active group)
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each
+                                               // byte
+            "paddb %%mm1, %%mm2          \n\t" // add LBCarrys to (Raw(x-bpp)/2)
+                                               // for each byte
+            "pand %%mm6, %%mm2           \n\t" // leave only Active Group 2
+                                               // bytes to add to Avg
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) + LBCarrys to
+                                               // Avg for each Active byte
+
+            "cmpl _MMXLength, %%ecx      \n\t"
+            // now ready to write back to memory
+            "movq %%mm0, -8(%%edi,%%ecx,) \n\t"
+            // prep Raw(x-bpp) for next loop
+            "movq %%mm0, %%mm2           \n\t" // mov updated Raws to mm2
+            "jb avg_2lp                  \n\t"
+
+            : "=S" (dummy_value_S),            // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi          // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                           // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 2 bpp
+
+      case 1:
+      {
+         __asm__ __volatile__ (
+            // re-init address pointers and offset
+#ifdef __PIC__
+            "pushl %%ebx                 \n\t" // save Global Offset Table index
+#endif
+            "movl _dif, %%ebx            \n\t" // ebx:  x = offset to alignment
+                                               // boundary
+// preload  "movl row, %%edi             \n\t" // edi:  Avg(x)
+            "cmpl _FullLength, %%ebx     \n\t" // test if offset at end of array
+            "jnb avg_1end                \n\t"
+            // do Paeth decode for remaining bytes
+// preload  "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+            "movl %%edi, %%edx           \n\t"
+// preload  "subl bpp, %%edx             \n\t" // (bpp is preloaded into ecx)
+            "subl %%ecx, %%edx           \n\t" // edx:  Raw(x-bpp)
+            "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx
+                                               //  in loop below
+         "avg_1lp:                       \n\t"
+            // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+            "xorl %%eax, %%eax           \n\t"
+            "movb (%%esi,%%ebx,), %%cl   \n\t" // load cl with Prior(x)
+            "movb (%%edx,%%ebx,), %%al   \n\t" // load al with Raw(x-bpp)
+            "addw %%cx, %%ax             \n\t"
+            "incl %%ebx                  \n\t"
+            "shrw %%ax                   \n\t" // divide by 2
+            "addb -1(%%edi,%%ebx,), %%al \n\t" // add Avg(x); -1 to offset
+                                               // inc ebx
+            "cmpl _FullLength, %%ebx     \n\t" // check if at end of array
+            "movb %%al, -1(%%edi,%%ebx,) \n\t" // write back Raw(x);
+                         // mov does not affect flags; -1 to offset inc ebx
+            "jb avg_1lp                  \n\t"
+
+         "avg_1end:                      \n\t"
+#ifdef __PIC__
+            "popl %%ebx                  \n\t" // Global Offset Table index
+#endif
+
+            : "=c" (dummy_value_c),            // output regs (dummy)
+              "=S" (dummy_value_S),
+              "=D" (dummy_value_D)
+
+            : "0" (bpp),       // ecx          // input regs
+              "1" (prev_row),  // esi
+              "2" (row)        // edi
+
+            : "%eax", "%edx"                   // clobber list
+#ifndef __PIC__
+            , "%ebx"
+#endif
+         );
+      }
+      return;  // end 1 bpp
+
+      case 8:
+      {
+         __asm__ __volatile__ (
+            // re-init address pointers and offset
+            "movl _dif, %%ecx            \n\t" // ecx:  x == offset to alignment
+            "movq _LBCarryMask, %%mm5    \n\t" //            boundary
+// preload  "movl row, %%edi             \n\t" // edi:  Avg(x)
+            "movq _HBClearMask, %%mm4    \n\t"
+// preload  "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes
+                                      // (NO NEED to correct pos. in loop below)
+
+         "avg_8lp:                       \n\t"
+            "movq (%%edi,%%ecx,), %%mm0  \n\t"
+            "movq %%mm5, %%mm3           \n\t"
+            "movq (%%esi,%%ecx,), %%mm1  \n\t"
+            "addl $8, %%ecx              \n\t"
+            "pand %%mm1, %%mm3           \n\t" // get lsb for each prev_row byte
+            "psrlq $1, %%mm1             \n\t" // divide prev_row bytes by 2
+            "pand %%mm2, %%mm3           \n\t" // get LBCarrys for each byte
+                                               //  where both lsb's were == 1
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm1          \n\t" // clear invalid bit 7, each byte
+            "paddb %%mm3, %%mm0          \n\t" // add LBCarrys to Avg, each byte
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7, each byte
+            "paddb %%mm1, %%mm0          \n\t" // add (Prev_row/2) to Avg, each
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) to Avg for each
+            "cmpl _MMXLength, %%ecx      \n\t"
+            "movq %%mm0, -8(%%edi,%%ecx,) \n\t"
+            "movq %%mm0, %%mm2           \n\t" // reuse as Raw(x-bpp)
+            "jb avg_8lp                  \n\t"
+
+            : "=S" (dummy_value_S),            // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi          // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                           // clobber list
+#if 0  /* %mm0, ..., %mm5 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2"
+            , "%mm3", "%mm4", "%mm5"
+#endif
+         );
+      }
+      break;  // end 8 bpp
+
+      default:                  // bpp greater than 8 (!= 1,2,3,4,[5],6,[7],8)
+      {
+
+#ifdef PNG_DEBUG
+         // GRR:  PRINT ERROR HERE:  SHOULD NEVER BE REACHED
+        png_debug(1,
+        "Internal logic error in pnggccrd (png_read_filter_row_mmx_avg())\n");
+#endif
+
+#if 0
+        __asm__ __volatile__ (
+            "movq _LBCarryMask, %%mm5    \n\t"
+            // re-init address pointers and offset
+            "movl _dif, %%ebx            \n\t" // ebx:  x = offset to
+                                               // alignment boundary
+            "movl row, %%edi             \n\t" // edi:  Avg(x)
+            "movq _HBClearMask, %%mm4    \n\t"
+            "movl %%edi, %%edx           \n\t"
+            "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+            "subl bpp, %%edx             \n\t" // edx:  Raw(x-bpp)
+         "avg_Alp:                       \n\t"
+            "movq (%%edi,%%ebx,), %%mm0  \n\t"
+            "movq %%mm5, %%mm3           \n\t"
+            "movq (%%esi,%%ebx,), %%mm1  \n\t"
+            "pand %%mm1, %%mm3           \n\t" // get lsb for each prev_row byte
+            "movq (%%edx,%%ebx,), %%mm2  \n\t"
+            "psrlq $1, %%mm1             \n\t" // divide prev_row bytes by 2
+            "pand %%mm2, %%mm3           \n\t" // get LBCarrys for each byte
+                                               // where both lsb's were == 1
+            "psrlq $1, %%mm2             \n\t" // divide raw bytes by 2
+            "pand  %%mm4, %%mm1          \n\t" // clear invalid bit 7 of each
+                                               // byte
+            "paddb %%mm3, %%mm0          \n\t" // add LBCarrys to Avg for each
+                                               // byte
+            "pand  %%mm4, %%mm2          \n\t" // clear invalid bit 7 of each
+                                               // byte
+            "paddb %%mm1, %%mm0          \n\t" // add (Prev_row/2) to Avg for
+                                               // each byte
+            "addl $8, %%ebx              \n\t"
+            "paddb %%mm2, %%mm0          \n\t" // add (Raw/2) to Avg for each
+                                               // byte
+            "cmpl _MMXLength, %%ebx      \n\t"
+            "movq %%mm0, -8(%%edi,%%ebx,) \n\t"
+            "jb avg_Alp                  \n\t"
+
+            : // FIXASM: output regs/vars go here, e.g.:  "=m" (memory_var)
+
+            : // FIXASM: input regs, e.g.:  "c" (count), "S" (src), "D" (dest)
+
+            : "%ebx", "%edx", "%edi", "%esi" // CHECKASM: clobber list
+         );
+#endif /* 0 - NEVER REACHED */
+      }
+      break;
+
+   } // end switch (bpp)
+
+   __asm__ __volatile__ (
+      // MMX acceleration complete; now do clean-up
+      // check if any remaining bytes left to decode
+#ifdef __PIC__
+      "pushl %%ebx                 \n\t" // save index to Global Offset Table
+#endif
+      "movl _MMXLength, %%ebx      \n\t" // ebx:  x == offset bytes after MMX
+//pre "movl row, %%edi             \n\t" // edi:  Avg(x)
+      "cmpl _FullLength, %%ebx     \n\t" // test if offset at end of array
+      "jnb avg_end                 \n\t"
+
+      // do Avg decode for remaining bytes
+//pre "movl prev_row, %%esi        \n\t" // esi:  Prior(x)
+      "movl %%edi, %%edx           \n\t"
+//pre "subl bpp, %%edx             \n\t" // (bpp is preloaded into ecx)
+      "subl %%ecx, %%edx           \n\t" // edx:  Raw(x-bpp)
+      "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx below
+
+   "avg_lp2:                       \n\t"
+      // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+      "xorl %%eax, %%eax           \n\t"
+      "movb (%%esi,%%ebx,), %%cl   \n\t" // load cl with Prior(x)
+      "movb (%%edx,%%ebx,), %%al   \n\t" // load al with Raw(x-bpp)
+      "addw %%cx, %%ax             \n\t"
+      "incl %%ebx                  \n\t"
+      "shrw %%ax                   \n\t" // divide by 2
+      "addb -1(%%edi,%%ebx,), %%al \n\t" // add Avg(x); -1 to offset inc ebx
+      "cmpl _FullLength, %%ebx     \n\t" // check if at end of array
+      "movb %%al, -1(%%edi,%%ebx,) \n\t" // write back Raw(x) [mov does not
+      "jb avg_lp2                  \n\t" //  affect flags; -1 to offset inc ebx]
+
+   "avg_end:                       \n\t"
+      "EMMS                        \n\t" // end MMX; prep for poss. FP instrs.
+#ifdef __PIC__
+      "popl %%ebx                  \n\t" // restore index to Global Offset Table
+#endif
+
+      : "=c" (dummy_value_c),            // output regs (dummy)
+        "=S" (dummy_value_S),
+        "=D" (dummy_value_D)
+
+      : "0" (bpp),       // ecx          // input regs
+        "1" (prev_row),  // esi
+        "2" (row)        // edi
+
+      : "%eax", "%edx"                   // clobber list
+#ifndef __PIC__
+      , "%ebx"
+#endif
+   );
+
+} /* end png_read_filter_row_mmx_avg() */
+#endif
+
+
+
+#ifdef PNG_THREAD_UNSAFE_OK
+//===========================================================================//
+//                                                                           //
+//         P N G _ R E A D _ F I L T E R _ R O W _ M M X _ P A E T H         //
+//                                                                           //
+//===========================================================================//
+
+// Optimized code for PNG Paeth filter decoder
+
+static void /* PRIVATE */
+png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
+                              png_bytep prev_row)
+{
+   int bpp;
+   int dummy_value_c;   // fix 'forbidden register 2 (cx) was spilled' error
+   int dummy_value_S;
+   int dummy_value_D;
+
+   bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
+   _FullLength  = row_info->rowbytes; // # of bytes to filter
+
+   __asm__ __volatile__ (
+#ifdef __PIC__
+      "pushl %%ebx                 \n\t" // save index to Global Offset Table
+#endif
+      "xorl %%ebx, %%ebx           \n\t" // ebx:  x offset
+//pre "movl row, %%edi             \n\t"
+      "xorl %%edx, %%edx           \n\t" // edx:  x-bpp offset
+//pre "movl prev_row, %%esi        \n\t"
+      "xorl %%eax, %%eax           \n\t"
+
+      // Compute the Raw value for the first bpp bytes
+      // Note: the formula works out to be always
+      //   Paeth(x) = Raw(x) + Prior(x)      where x < bpp
+   "paeth_rlp:                     \n\t"
+      "movb (%%edi,%%ebx,), %%al   \n\t"
+      "addb (%%esi,%%ebx,), %%al   \n\t"
+      "incl %%ebx                  \n\t"
+//pre "cmpl bpp, %%ebx             \n\t" (bpp is preloaded into ecx)
+      "cmpl %%ecx, %%ebx           \n\t"
+      "movb %%al, -1(%%edi,%%ebx,) \n\t"
+      "jb paeth_rlp                \n\t"
+      // get # of bytes to alignment
+      "movl %%edi, _dif            \n\t" // take start of row
+      "addl %%ebx, _dif            \n\t" // add bpp
+      "xorl %%ecx, %%ecx           \n\t"
+      "addl $0xf, _dif             \n\t" // add 7 + 8 to incr past alignment
+                                         // boundary
+      "andl $0xfffffff8, _dif      \n\t" // mask to alignment boundary
+      "subl %%edi, _dif            \n\t" // subtract from start ==> value ebx
+                                         // at alignment
+      "jz paeth_go                 \n\t"
+      // fix alignment
+
+   "paeth_lp1:                     \n\t"
+      "xorl %%eax, %%eax           \n\t"
+      // pav = p - a = (a + b - c) - a = b - c
+      "movb (%%esi,%%ebx,), %%al   \n\t" // load Prior(x) into al
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+      "movl %%eax, _patemp         \n\t" // Save pav for later use
+      "xorl %%eax, %%eax           \n\t"
+      // pbv = p - b = (a + b - c) - b = a - c
+      "movb (%%edi,%%edx,), %%al   \n\t" // load Raw(x-bpp) into al
+      "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+      "movl %%eax, %%ecx           \n\t"
+      // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+      "addl _patemp, %%eax         \n\t" // pcv = pav + pbv
+      // pc = abs(pcv)
+      "testl $0x80000000, %%eax    \n\t"
+      "jz paeth_pca                \n\t"
+      "negl %%eax                  \n\t" // reverse sign of neg values
+
+   "paeth_pca:                     \n\t"
+      "movl %%eax, _pctemp         \n\t" // save pc for later use
+      // pb = abs(pbv)
+      "testl $0x80000000, %%ecx    \n\t"
+      "jz paeth_pba                \n\t"
+      "negl %%ecx                  \n\t" // reverse sign of neg values
+
+   "paeth_pba:                     \n\t"
+      "movl %%ecx, _pbtemp         \n\t" // save pb for later use
+      // pa = abs(pav)
+      "movl _patemp, %%eax         \n\t"
+      "testl $0x80000000, %%eax    \n\t"
+      "jz paeth_paa                \n\t"
+      "negl %%eax                  \n\t" // reverse sign of neg values
+
+   "paeth_paa:                     \n\t"
+      "movl %%eax, _patemp         \n\t" // save pa for later use
+      // test if pa <= pb
+      "cmpl %%ecx, %%eax           \n\t"
+      "jna paeth_abb               \n\t"
+      // pa > pb; now test if pb <= pc
+      "cmpl _pctemp, %%ecx         \n\t"
+      "jna paeth_bbc               \n\t"
+      // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "jmp paeth_paeth             \n\t"
+
+   "paeth_bbc:                     \n\t"
+      // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+      "movb (%%esi,%%ebx,), %%cl   \n\t" // load Prior(x) into cl
+      "jmp paeth_paeth             \n\t"
+
+   "paeth_abb:                     \n\t"
+      // pa <= pb; now test if pa <= pc
+      "cmpl _pctemp, %%eax         \n\t"
+      "jna paeth_abc               \n\t"
+      // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "jmp paeth_paeth             \n\t"
+
+   "paeth_abc:                     \n\t"
+      // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+      "movb (%%edi,%%edx,), %%cl   \n\t" // load Raw(x-bpp) into cl
+
+   "paeth_paeth:                   \n\t"
+      "incl %%ebx                  \n\t"
+      "incl %%edx                  \n\t"
+      // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+      "addb %%cl, -1(%%edi,%%ebx,) \n\t"
+      "cmpl _dif, %%ebx            \n\t"
+      "jb paeth_lp1                \n\t"
+
+   "paeth_go:                      \n\t"
+      "movl _FullLength, %%ecx     \n\t"
+      "movl %%ecx, %%eax           \n\t"
+      "subl %%ebx, %%eax           \n\t" // subtract alignment fix
+      "andl $0x00000007, %%eax     \n\t" // calc bytes over mult of 8
+      "subl %%eax, %%ecx           \n\t" // drop over bytes from original length
+      "movl %%ecx, _MMXLength      \n\t"
+#ifdef __PIC__
+      "popl %%ebx                  \n\t" // restore index to Global Offset Table
+#endif
+
+      : "=c" (dummy_value_c),            // output regs (dummy)
+        "=S" (dummy_value_S),
+        "=D" (dummy_value_D)
+
+      : "0" (bpp),       // ecx          // input regs
+        "1" (prev_row),  // esi
+        "2" (row)        // edi
+
+      : "%eax", "%edx"                   // clobber list
+#ifndef __PIC__
+      , "%ebx"
+#endif
+   );
+
+   // now do the math for the rest of the row
+   switch (bpp)
+   {
+      case 3:
+      {
+         _ActiveMask.use = 0x0000000000ffffffLL;
+         _ActiveMaskEnd.use = 0xffff000000000000LL;
+         _ShiftBpp.use = 24;    // == bpp(3) * 8
+         _ShiftRem.use = 40;    // == 64 - 24
+
+         __asm__ __volatile__ (
+            "movl _dif, %%ecx            \n\t"
+// preload  "movl row, %%edi             \n\t"
+// preload  "movl prev_row, %%esi        \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm1 \n\t"
+         "paeth_3lp:                     \n\t"
+            "psrlq _ShiftRem, %%mm1      \n\t" // shift last 3 bytes to 1st
+                                               // 3 bytes
+            "movq (%%esi,%%ecx,), %%mm2  \n\t" // load b=Prior(x)
+            "punpcklbw %%mm0, %%mm1      \n\t" // unpack High bytes of a
+            "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // prep c=Prior(x-bpp) bytes
+            "punpcklbw %%mm0, %%mm2      \n\t" // unpack High bytes of b
+            "psrlq _ShiftRem, %%mm3      \n\t" // shift last 3 bytes to 1st
+                                               // 3 bytes
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "punpcklbw %%mm0, %%mm3      \n\t" // unpack High bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "packuswb %%mm1, %%mm7       \n\t"
+            "movq (%%esi,%%ecx,), %%mm3  \n\t" // load c=Prior(x-bpp)
+            "pand _ActiveMask, %%mm7     \n\t"
+            "movq %%mm3, %%mm2           \n\t" // load b=Prior(x) step 1
+            "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "punpcklbw %%mm0, %%mm3      \n\t" // unpack High bytes of c
+            "movq %%mm7, (%%edi,%%ecx,)  \n\t" // write back updated value
+            "movq %%mm7, %%mm1           \n\t" // now mm1 will be used as
+                                               // Raw(x-bpp)
+            // now do Paeth for 2nd set of bytes (3-5)
+            "psrlq _ShiftBpp, %%mm2      \n\t" // load b=Prior(x) step 2
+            "punpcklbw %%mm0, %%mm1      \n\t" // unpack High bytes of a
+            "pxor %%mm7, %%mm7           \n\t"
+            "punpcklbw %%mm0, %%mm2      \n\t" // unpack High bytes of b
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) =
+            //       pav + pbv = pbv + pav
+            "movq %%mm5, %%mm6           \n\t"
+            "paddw %%mm4, %%mm6          \n\t"
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm5, %%mm0        \n\t" // create mask pbv bytes < 0
+            "pcmpgtw %%mm4, %%mm7        \n\t" // create mask pav bytes < 0
+            "pand %%mm5, %%mm0           \n\t" // only pbv bytes < 0 in mm0
+            "pand %%mm4, %%mm7           \n\t" // only pav bytes < 0 in mm7
+            "psubw %%mm0, %%mm5          \n\t"
+            "psubw %%mm7, %%mm4          \n\t"
+            "psubw %%mm0, %%mm5          \n\t"
+            "psubw %%mm7, %%mm4          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "movq (%%esi,%%ecx,), %%mm2  \n\t" // load b=Prior(x)
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "pxor %%mm1, %%mm1           \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "packuswb %%mm1, %%mm7       \n\t"
+            "movq %%mm2, %%mm3           \n\t" // load c=Prior(x-bpp) step 1
+            "pand _ActiveMask, %%mm7     \n\t"
+            "punpckhbw %%mm0, %%mm2      \n\t" // unpack High bytes of b
+            "psllq _ShiftBpp, %%mm7      \n\t" // shift bytes to 2nd group of
+                                               // 3 bytes
+             // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "psllq _ShiftBpp, %%mm3      \n\t" // load c=Prior(x-bpp) step 2
+            "movq %%mm7, (%%edi,%%ecx,)  \n\t" // write back updated value
+            "movq %%mm7, %%mm1           \n\t"
+            "punpckhbw %%mm0, %%mm3      \n\t" // unpack High bytes of c
+            "psllq _ShiftBpp, %%mm1      \n\t" // shift bytes
+                                    // now mm1 will be used as Raw(x-bpp)
+            // now do Paeth for 3rd, and final, set of bytes (6-7)
+            "pxor %%mm7, %%mm7           \n\t"
+            "punpckhbw %%mm0, %%mm1      \n\t" // unpack High bytes of a
+            "psubw %%mm3, %%mm4          \n\t"
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "paddw %%mm5, %%mm6          \n\t"
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // create mask pav bytes < 0
+            "pcmpgtw %%mm5, %%mm7        \n\t" // create mask pbv bytes < 0
+            "pand %%mm4, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "pand %%mm5, %%mm7           \n\t" // only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm1, %%mm1           \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            // step ecx to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ecx              \n\t"
+            "pand _ActiveMaskEnd, %%mm1  \n\t"
+            "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add Paeth predictor with
+                                                 // Raw(x)
+
+            "cmpl _MMXLength, %%ecx      \n\t"
+            "pxor %%mm0, %%mm0           \n\t" // pxor does not affect flags
+            "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value
+                                 // mm1 will be used as Raw(x-bpp) next loop
+                           // mm3 ready to be used as Prior(x-bpp) next loop
+            "jb paeth_3lp                \n\t"
+
+            : "=S" (dummy_value_S),             // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi           // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                            // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 3 bpp
+
+      case 6:
+      //case 7:   // GRR BOGUS
+      //case 5:   // GRR BOGUS
+      {
+         _ActiveMask.use  = 0x00000000ffffffffLL;
+         _ActiveMask2.use = 0xffffffff00000000LL;
+         _ShiftBpp.use = bpp << 3;    // == bpp * 8
+         _ShiftRem.use = 64 - _ShiftBpp.use;
+
+         __asm__ __volatile__ (
+            "movl _dif, %%ecx            \n\t"
+// preload  "movl row, %%edi             \n\t"
+// preload  "movl prev_row, %%esi        \n\t"
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm1 \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+
+         "paeth_6lp:                     \n\t"
+            // must shift to position Raw(x-bpp) data
+            "psrlq _ShiftRem, %%mm1      \n\t"
+            // do first set of 4 bytes
+            "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "punpcklbw %%mm0, %%mm1      \n\t" // unpack Low bytes of a
+            "movq (%%esi,%%ecx,), %%mm2  \n\t" // load b=Prior(x)
+            "punpcklbw %%mm0, %%mm2      \n\t" // unpack Low bytes of b
+            // must shift to position Prior(x-bpp) data
+            "psrlq _ShiftRem, %%mm3      \n\t"
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "punpcklbw %%mm0, %%mm3      \n\t" // unpack Low bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "packuswb %%mm1, %%mm7       \n\t"
+            "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // load c=Prior(x-bpp)
+            "pand _ActiveMask, %%mm7     \n\t"
+            "psrlq _ShiftRem, %%mm3      \n\t"
+            "movq (%%esi,%%ecx,), %%mm2  \n\t" // load b=Prior(x) step 1
+            "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor and Raw(x)
+            "movq %%mm2, %%mm6           \n\t"
+            "movq %%mm7, (%%edi,%%ecx,)  \n\t" // write back updated value
+            "movq -8(%%edi,%%ecx,), %%mm1 \n\t"
+            "psllq _ShiftBpp, %%mm6      \n\t"
+            "movq %%mm7, %%mm5           \n\t"
+            "psrlq _ShiftRem, %%mm1      \n\t"
+            "por %%mm6, %%mm3            \n\t"
+            "psllq _ShiftBpp, %%mm5      \n\t"
+            "punpckhbw %%mm0, %%mm3      \n\t" // unpack High bytes of c
+            "por %%mm5, %%mm1            \n\t"
+            // do second set of 4 bytes
+            "punpckhbw %%mm0, %%mm2      \n\t" // unpack High bytes of b
+            "punpckhbw %%mm0, %%mm1      \n\t" // unpack High bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "pxor %%mm1, %%mm1           \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // step ecx to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ecx              \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add Paeth predictor with Raw(x)
+            "cmpl _MMXLength, %%ecx      \n\t"
+            "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value
+                                // mm1 will be used as Raw(x-bpp) next loop
+            "jb paeth_6lp                \n\t"
+
+            : "=S" (dummy_value_S),             // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi           // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                            // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 6 bpp
+
+      case 4:
+      {
+         _ActiveMask.use  = 0x00000000ffffffffLL;
+
+         __asm__ __volatile__ (
+            "movl _dif, %%ecx            \n\t"
+// preload  "movl row, %%edi             \n\t"
+// preload  "movl prev_row, %%esi        \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm1 \n\t" // only time should need to read
+                                     //  a=Raw(x-bpp) bytes
+         "paeth_4lp:                     \n\t"
+            // do first set of 4 bytes
+            "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "punpckhbw %%mm0, %%mm1      \n\t" // unpack Low bytes of a
+            "movq (%%esi,%%ecx,), %%mm2  \n\t" // load b=Prior(x)
+            "punpcklbw %%mm0, %%mm2      \n\t" // unpack High bytes of b
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "punpckhbw %%mm0, %%mm3      \n\t" // unpack High bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "packuswb %%mm1, %%mm7       \n\t"
+            "movq (%%esi,%%ecx,), %%mm3  \n\t" // load c=Prior(x-bpp)
+            "pand _ActiveMask, %%mm7     \n\t"
+            "movq %%mm3, %%mm2           \n\t" // load b=Prior(x) step 1
+            "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "punpcklbw %%mm0, %%mm3      \n\t" // unpack High bytes of c
+            "movq %%mm7, (%%edi,%%ecx,)  \n\t" // write back updated value
+            "movq %%mm7, %%mm1           \n\t" // now mm1 will be used as Raw(x-bpp)
+            // do second set of 4 bytes
+            "punpckhbw %%mm0, %%mm2      \n\t" // unpack Low bytes of b
+            "punpcklbw %%mm0, %%mm1      \n\t" // unpack Low bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "pxor %%mm1, %%mm1           \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // step ecx to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ecx              \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add predictor with Raw(x)
+            "cmpl _MMXLength, %%ecx      \n\t"
+            "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value
+                                // mm1 will be used as Raw(x-bpp) next loop
+            "jb paeth_4lp                \n\t"
+
+            : "=S" (dummy_value_S),             // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi           // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                            // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 4 bpp
+
+      case 8:                          // bpp == 8
+      {
+         _ActiveMask.use  = 0x00000000ffffffffLL;
+
+         __asm__ __volatile__ (
+            "movl _dif, %%ecx            \n\t"
+// preload  "movl row, %%edi             \n\t"
+// preload  "movl prev_row, %%esi        \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%ecx,), %%mm1 \n\t" // only time should need to read
+                                       //  a=Raw(x-bpp) bytes
+         "paeth_8lp:                     \n\t"
+            // do first set of 4 bytes
+            "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "punpcklbw %%mm0, %%mm1      \n\t" // unpack Low bytes of a
+            "movq (%%esi,%%ecx,), %%mm2  \n\t" // load b=Prior(x)
+            "punpcklbw %%mm0, %%mm2      \n\t" // unpack Low bytes of b
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            "punpcklbw %%mm0, %%mm3      \n\t" // unpack Low bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "packuswb %%mm1, %%mm7       \n\t"
+            "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes
+            "pand _ActiveMask, %%mm7     \n\t"
+            "movq (%%esi,%%ecx,), %%mm2  \n\t" // load b=Prior(x)
+            "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x)
+            "punpckhbw %%mm0, %%mm3      \n\t" // unpack High bytes of c
+            "movq %%mm7, (%%edi,%%ecx,)  \n\t" // write back updated value
+            "movq -8(%%edi,%%ecx,), %%mm1 \n\t" // read a=Raw(x-bpp) bytes
+
+            // do second set of 4 bytes
+            "punpckhbw %%mm0, %%mm2      \n\t" // unpack High bytes of b
+            "punpckhbw %%mm0, %%mm1      \n\t" // unpack High bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            "movq %%mm2, %%mm4           \n\t"
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movq %%mm1, %%mm5           \n\t"
+            "psubw %%mm3, %%mm4          \n\t"
+            "pxor %%mm7, %%mm7           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "movq %%mm4, %%mm6           \n\t"
+            "psubw %%mm3, %%mm5          \n\t"
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            "pcmpgtw %%mm4, %%mm0        \n\t" // create mask pav bytes < 0
+            "paddw %%mm5, %%mm6          \n\t"
+            "pand %%mm4, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "pcmpgtw %%mm5, %%mm7        \n\t" // create mask pbv bytes < 0
+            "psubw %%mm0, %%mm4          \n\t"
+            "pand %%mm5, %%mm7           \n\t" // only pbv bytes < 0 in mm0
+            "psubw %%mm0, %%mm4          \n\t"
+            "psubw %%mm7, %%mm5          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            "pcmpgtw %%mm6, %%mm0        \n\t" // create mask pcv bytes < 0
+            "pand %%mm6, %%mm0           \n\t" // only pav bytes < 0 in mm7
+            "psubw %%mm7, %%mm5          \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            //  test pa <= pb
+            "movq %%mm4, %%mm7           \n\t"
+            "psubw %%mm0, %%mm6          \n\t"
+            "pcmpgtw %%mm5, %%mm7        \n\t" // pa > pb?
+            "movq %%mm7, %%mm0           \n\t"
+            // use mm7 mask to merge pa & pb
+            "pand %%mm7, %%mm5           \n\t"
+            // use mm0 mask copy to merge a & b
+            "pand %%mm0, %%mm2           \n\t"
+            "pandn %%mm4, %%mm7          \n\t"
+            "pandn %%mm1, %%mm0          \n\t"
+            "paddw %%mm5, %%mm7          \n\t"
+            "paddw %%mm2, %%mm0          \n\t"
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            "pcmpgtw %%mm6, %%mm7        \n\t" // pab > pc?
+            "pxor %%mm1, %%mm1           \n\t"
+            "pand %%mm7, %%mm3           \n\t"
+            "pandn %%mm0, %%mm7          \n\t"
+            "pxor %%mm1, %%mm1           \n\t"
+            "paddw %%mm3, %%mm7          \n\t"
+            "pxor %%mm0, %%mm0           \n\t"
+            // step ecx to next set of 8 bytes and repeat loop til done
+            "addl $8, %%ecx              \n\t"
+            "packuswb %%mm7, %%mm1       \n\t"
+            "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add Paeth predictor with Raw(x)
+            "cmpl _MMXLength, %%ecx      \n\t"
+            "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value
+                            // mm1 will be used as Raw(x-bpp) next loop
+            "jb paeth_8lp                \n\t"
+
+            : "=S" (dummy_value_S),             // output regs (dummy)
+              "=D" (dummy_value_D)
+
+            : "0" (prev_row),  // esi           // input regs
+              "1" (row)        // edi
+
+            : "%ecx"                            // clobber list
+#if 0  /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3"
+            , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;  // end 8 bpp
+
+      case 1:                // bpp = 1
+      case 2:                // bpp = 2
+      default:               // bpp > 8
+      {
+         __asm__ __volatile__ (
+#ifdef __PIC__
+            "pushl %%ebx                 \n\t" // save Global Offset Table index
+#endif
+            "movl _dif, %%ebx            \n\t"
+            "cmpl _FullLength, %%ebx     \n\t"
+            "jnb paeth_dend              \n\t"
+
+// preload  "movl row, %%edi             \n\t"
+// preload  "movl prev_row, %%esi        \n\t"
+            // do Paeth decode for remaining bytes
+            "movl %%ebx, %%edx           \n\t"
+// preload  "subl bpp, %%edx             \n\t" // (bpp is preloaded into ecx)
+            "subl %%ecx, %%edx           \n\t" // edx = ebx - bpp
+            "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx
+
+         "paeth_dlp:                     \n\t"
+            "xorl %%eax, %%eax           \n\t"
+            // pav = p - a = (a + b - c) - a = b - c
+            "movb (%%esi,%%ebx,), %%al   \n\t" // load Prior(x) into al
+            "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+            "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+            "movl %%eax, _patemp         \n\t" // Save pav for later use
+            "xorl %%eax, %%eax           \n\t"
+            // pbv = p - b = (a + b - c) - b = a - c
+            "movb (%%edi,%%edx,), %%al   \n\t" // load Raw(x-bpp) into al
+            "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+            "movl %%eax, %%ecx           \n\t"
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            "addl _patemp, %%eax         \n\t" // pcv = pav + pbv
+            // pc = abs(pcv)
+            "testl $0x80000000, %%eax    \n\t"
+            "jz paeth_dpca               \n\t"
+            "negl %%eax                  \n\t" // reverse sign of neg values
+
+         "paeth_dpca:                    \n\t"
+            "movl %%eax, _pctemp         \n\t" // save pc for later use
+            // pb = abs(pbv)
+            "testl $0x80000000, %%ecx    \n\t"
+            "jz paeth_dpba               \n\t"
+            "negl %%ecx                  \n\t" // reverse sign of neg values
+
+         "paeth_dpba:                    \n\t"
+            "movl %%ecx, _pbtemp         \n\t" // save pb for later use
+            // pa = abs(pav)
+            "movl _patemp, %%eax         \n\t"
+            "testl $0x80000000, %%eax    \n\t"
+            "jz paeth_dpaa               \n\t"
+            "negl %%eax                  \n\t" // reverse sign of neg values
+
+         "paeth_dpaa:                    \n\t"
+            "movl %%eax, _patemp         \n\t" // save pa for later use
+            // test if pa <= pb
+            "cmpl %%ecx, %%eax           \n\t"
+            "jna paeth_dabb              \n\t"
+            // pa > pb; now test if pb <= pc
+            "cmpl _pctemp, %%ecx         \n\t"
+            "jna paeth_dbbc              \n\t"
+            // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+            "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+            "jmp paeth_dpaeth            \n\t"
+
+         "paeth_dbbc:                    \n\t"
+            // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+            "movb (%%esi,%%ebx,), %%cl   \n\t" // load Prior(x) into cl
+            "jmp paeth_dpaeth            \n\t"
+
+         "paeth_dabb:                    \n\t"
+            // pa <= pb; now test if pa <= pc
+            "cmpl _pctemp, %%eax         \n\t"
+            "jna paeth_dabc              \n\t"
+            // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+            "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+            "jmp paeth_dpaeth            \n\t"
+
+         "paeth_dabc:                    \n\t"
+            // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+            "movb (%%edi,%%edx,), %%cl   \n\t" // load Raw(x-bpp) into cl
+
+         "paeth_dpaeth:                  \n\t"
+            "incl %%ebx                  \n\t"
+            "incl %%edx                  \n\t"
+            // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+            "addb %%cl, -1(%%edi,%%ebx,) \n\t"
+            "cmpl _FullLength, %%ebx     \n\t"
+            "jb paeth_dlp                \n\t"
+
+         "paeth_dend:                    \n\t"
+#ifdef __PIC__
+            "popl %%ebx                  \n\t" // index to Global Offset Table
+#endif
+
+            : "=c" (dummy_value_c),            // output regs (dummy)
+              "=S" (dummy_value_S),
+              "=D" (dummy_value_D)
+
+            : "0" (bpp),       // ecx          // input regs
+              "1" (prev_row),  // esi
+              "2" (row)        // edi
+
+            : "%eax", "%edx"                   // clobber list
+#ifndef __PIC__
+            , "%ebx"
+#endif
+         );
+      }
+      return;                   // No need to go further with this one
+
+   } // end switch (bpp)
+
+   __asm__ __volatile__ (
+      // MMX acceleration complete; now do clean-up
+      // check if any remaining bytes left to decode
+#ifdef __PIC__
+      "pushl %%ebx                 \n\t" // save index to Global Offset Table
+#endif
+      "movl _MMXLength, %%ebx      \n\t"
+      "cmpl _FullLength, %%ebx     \n\t"
+      "jnb paeth_end               \n\t"
+//pre "movl row, %%edi             \n\t"
+//pre "movl prev_row, %%esi        \n\t"
+      // do Paeth decode for remaining bytes
+      "movl %%ebx, %%edx           \n\t"
+//pre "subl bpp, %%edx             \n\t" // (bpp is preloaded into ecx)
+      "subl %%ecx, %%edx           \n\t" // edx = ebx - bpp
+      "xorl %%ecx, %%ecx           \n\t" // zero ecx before using cl & cx below
+
+   "paeth_lp2:                     \n\t"
+      "xorl %%eax, %%eax           \n\t"
+      // pav = p - a = (a + b - c) - a = b - c
+      "movb (%%esi,%%ebx,), %%al   \n\t" // load Prior(x) into al
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+      "movl %%eax, _patemp         \n\t" // Save pav for later use
+      "xorl %%eax, %%eax           \n\t"
+      // pbv = p - b = (a + b - c) - b = a - c
+      "movb (%%edi,%%edx,), %%al   \n\t" // load Raw(x-bpp) into al
+      "subl %%ecx, %%eax           \n\t" // subtract Prior(x-bpp)
+      "movl %%eax, %%ecx           \n\t"
+      // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+      "addl _patemp, %%eax         \n\t" // pcv = pav + pbv
+      // pc = abs(pcv)
+      "testl $0x80000000, %%eax    \n\t"
+      "jz paeth_pca2               \n\t"
+      "negl %%eax                  \n\t" // reverse sign of neg values
+
+   "paeth_pca2:                    \n\t"
+      "movl %%eax, _pctemp         \n\t" // save pc for later use
+      // pb = abs(pbv)
+      "testl $0x80000000, %%ecx    \n\t"
+      "jz paeth_pba2               \n\t"
+      "negl %%ecx                  \n\t" // reverse sign of neg values
+
+   "paeth_pba2:                    \n\t"
+      "movl %%ecx, _pbtemp         \n\t" // save pb for later use
+      // pa = abs(pav)
+      "movl _patemp, %%eax         \n\t"
+      "testl $0x80000000, %%eax    \n\t"
+      "jz paeth_paa2               \n\t"
+      "negl %%eax                  \n\t" // reverse sign of neg values
+
+   "paeth_paa2:                    \n\t"
+      "movl %%eax, _patemp         \n\t" // save pa for later use
+      // test if pa <= pb
+      "cmpl %%ecx, %%eax           \n\t"
+      "jna paeth_abb2              \n\t"
+      // pa > pb; now test if pb <= pc
+      "cmpl _pctemp, %%ecx         \n\t"
+      "jna paeth_bbc2              \n\t"
+      // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "jmp paeth_paeth2            \n\t"
+
+   "paeth_bbc2:                    \n\t"
+      // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+      "movb (%%esi,%%ebx,), %%cl   \n\t" // load Prior(x) into cl
+      "jmp paeth_paeth2            \n\t"
+
+   "paeth_abb2:                    \n\t"
+      // pa <= pb; now test if pa <= pc
+      "cmpl _pctemp, %%eax         \n\t"
+      "jna paeth_abc2              \n\t"
+      // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+      "movb (%%esi,%%edx,), %%cl   \n\t" // load Prior(x-bpp) into cl
+      "jmp paeth_paeth2            \n\t"
+
+   "paeth_abc2:                    \n\t"
+      // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+      "movb (%%edi,%%edx,), %%cl   \n\t" // load Raw(x-bpp) into cl
+
+   "paeth_paeth2:                  \n\t"
+      "incl %%ebx                  \n\t"
+      "incl %%edx                  \n\t"
+      // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+      "addb %%cl, -1(%%edi,%%ebx,) \n\t"
+      "cmpl _FullLength, %%ebx     \n\t"
+      "jb paeth_lp2                \n\t"
+
+   "paeth_end:                     \n\t"
+      "EMMS                        \n\t" // end MMX; prep for poss. FP instrs.
+#ifdef __PIC__
+      "popl %%ebx                  \n\t" // restore index to Global Offset Table
+#endif
+
+      : "=c" (dummy_value_c),            // output regs (dummy)
+        "=S" (dummy_value_S),
+        "=D" (dummy_value_D)
+
+      : "0" (bpp),       // ecx          // input regs
+        "1" (prev_row),  // esi
+        "2" (row)        // edi
+
+      : "%eax", "%edx"                   // clobber list (no input regs!)
+#ifndef __PIC__
+      , "%ebx"
+#endif
+   );
+
+} /* end png_read_filter_row_mmx_paeth() */
+#endif
+
+
+
+
+#ifdef PNG_THREAD_UNSAFE_OK
+//===========================================================================//
+//                                                                           //
+//           P N G _ R E A D _ F I L T E R _ R O W _ M M X _ S U B           //
+//                                                                           //
+//===========================================================================//
+
+// Optimized code for PNG Sub filter decoder
+
+static void /* PRIVATE */
+png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
+{
+   int bpp;
+   int dummy_value_a;
+   int dummy_value_D;
+
+   bpp = (row_info->pixel_depth + 7) >> 3;   // calc number of bytes per pixel
+   _FullLength = row_info->rowbytes - bpp;   // number of bytes to filter
+
+   __asm__ __volatile__ (
+//pre "movl row, %%edi             \n\t"
+      "movl %%edi, %%esi           \n\t" // lp = row
+//pre "movl bpp, %%eax             \n\t"
+      "addl %%eax, %%edi           \n\t" // rp = row + bpp
+//irr "xorl %%eax, %%eax           \n\t"
+      // get # of bytes to alignment
+      "movl %%edi, _dif            \n\t" // take start of row
+      "addl $0xf, _dif             \n\t" // add 7 + 8 to incr past
+                                         //  alignment boundary
+      "xorl %%ecx, %%ecx           \n\t"
+      "andl $0xfffffff8, _dif      \n\t" // mask to alignment boundary
+      "subl %%edi, _dif            \n\t" // subtract from start ==> value
+      "jz sub_go                   \n\t" //  ecx at alignment
+
+   "sub_lp1:                       \n\t" // fix alignment
+      "movb (%%esi,%%ecx,), %%al   \n\t"
+      "addb %%al, (%%edi,%%ecx,)   \n\t"
+      "incl %%ecx                  \n\t"
+      "cmpl _dif, %%ecx            \n\t"
+      "jb sub_lp1                  \n\t"
+
+   "sub_go:                        \n\t"
+      "movl _FullLength, %%eax     \n\t"
+      "movl %%eax, %%edx           \n\t"
+      "subl %%ecx, %%edx           \n\t" // subtract alignment fix
+      "andl $0x00000007, %%edx     \n\t" // calc bytes over mult of 8
+      "subl %%edx, %%eax           \n\t" // drop over bytes from length
+      "movl %%eax, _MMXLength      \n\t"
+
+      : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+        "=D" (dummy_value_D)    // 1
+
+      : "0" (bpp),              // eax    // input regs
+        "1" (row)               // edi
+
+      : "%ebx", "%ecx", "%edx"            // clobber list
+      , "%esi"
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+      , "%mm0", "%mm1", "%mm2", "%mm3"
+      , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+   );
+
+   // now do the math for the rest of the row
+   switch (bpp)
+   {
+      case 3:
+      {
+         _ActiveMask.use  = 0x0000ffffff000000LL;
+         _ShiftBpp.use = 24;       // == 3 * 8
+         _ShiftRem.use  = 40;      // == 64 - 24
+
+         __asm__ __volatile__ (
+// preload  "movl row, %%edi              \n\t"
+            "movq _ActiveMask, %%mm7       \n\t" // load _ActiveMask for 2nd
+                                                //  active byte group
+            "movl %%edi, %%esi            \n\t" // lp = row
+// preload  "movl bpp, %%eax              \n\t"
+            "addl %%eax, %%edi            \n\t" // rp = row + bpp
+            "movq %%mm7, %%mm6            \n\t"
+            "movl _dif, %%edx             \n\t"
+            "psllq _ShiftBpp, %%mm6       \n\t" // move mask in mm6 to cover
+                                                //  3rd active byte group
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%edx,), %%mm1 \n\t"
+
+         "sub_3lp:                        \n\t" // shift data for adding first
+            "psrlq _ShiftRem, %%mm1       \n\t" //  bpp bytes (no need for mask;
+                                                //  shift clears inactive bytes)
+            // add 1st active group
+            "movq (%%edi,%%edx,), %%mm0   \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+
+            // add 2nd active group
+            "movq %%mm0, %%mm1            \n\t" // mov updated Raws to mm1
+            "psllq _ShiftBpp, %%mm1       \n\t" // shift data to pos. correctly
+            "pand %%mm7, %%mm1            \n\t" // mask to use 2nd active group
+            "paddb %%mm1, %%mm0           \n\t"
+
+            // add 3rd active group
+            "movq %%mm0, %%mm1            \n\t" // mov updated Raws to mm1
+            "psllq _ShiftBpp, %%mm1       \n\t" // shift data to pos. correctly
+            "pand %%mm6, %%mm1            \n\t" // mask to use 3rd active group
+            "addl $8, %%edx               \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+
+            "cmpl _MMXLength, %%edx       \n\t"
+            "movq %%mm0, -8(%%edi,%%edx,) \n\t" // write updated Raws to array
+            "movq %%mm0, %%mm1            \n\t" // prep 1st add at top of loop
+            "jb sub_3lp                   \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%edx", "%esi"                    // clobber list
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;
+
+      case 1:
+      {
+         __asm__ __volatile__ (
+            "movl _dif, %%edx            \n\t"
+// preload  "movl row, %%edi             \n\t"
+            "cmpl _FullLength, %%edx     \n\t"
+            "jnb sub_1end                \n\t"
+            "movl %%edi, %%esi           \n\t" // lp = row
+            "xorl %%eax, %%eax           \n\t"
+// preload  "movl bpp, %%eax             \n\t"
+            "addl %%eax, %%edi           \n\t" // rp = row + bpp
+
+         "sub_1lp:                       \n\t"
+            "movb (%%esi,%%edx,), %%al   \n\t"
+            "addb %%al, (%%edi,%%edx,)   \n\t"
+            "incl %%edx                  \n\t"
+            "cmpl _FullLength, %%edx     \n\t"
+            "jb sub_1lp                  \n\t"
+
+         "sub_1end:                      \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%edx", "%esi"                    // clobber list
+         );
+      }
+      return;
+
+      case 6:
+      case 4:
+      //case 7:   // GRR BOGUS
+      //case 5:   // GRR BOGUS
+      {
+         _ShiftBpp.use = bpp << 3;
+         _ShiftRem.use = 64 - _ShiftBpp.use;
+
+         __asm__ __volatile__ (
+// preload  "movl row, %%edi              \n\t"
+            "movl _dif, %%edx             \n\t"
+            "movl %%edi, %%esi            \n\t" // lp = row
+// preload  "movl bpp, %%eax              \n\t"
+            "addl %%eax, %%edi            \n\t" // rp = row + bpp
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%edx,), %%mm1 \n\t"
+
+         "sub_4lp:                        \n\t" // shift data for adding first
+            "psrlq _ShiftRem, %%mm1       \n\t" //  bpp bytes (no need for mask;
+                                                //  shift clears inactive bytes)
+            "movq (%%edi,%%edx,), %%mm0   \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+
+            // add 2nd active group
+            "movq %%mm0, %%mm1            \n\t" // mov updated Raws to mm1
+            "psllq _ShiftBpp, %%mm1       \n\t" // shift data to pos. correctly
+            "addl $8, %%edx               \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+
+            "cmpl _MMXLength, %%edx       \n\t"
+            "movq %%mm0, -8(%%edi,%%edx,) \n\t"
+            "movq %%mm0, %%mm1            \n\t" // prep 1st add at top of loop
+            "jb sub_4lp                   \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%edx", "%esi"                    // clobber list
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1"
+#endif
+         );
+      }
+      break;
+
+      case 2:
+      {
+         _ActiveMask.use = 0x00000000ffff0000LL;
+         _ShiftBpp.use = 16;       // == 2 * 8
+         _ShiftRem.use = 48;       // == 64 - 16
+
+         __asm__ __volatile__ (
+            "movq _ActiveMask, %%mm7      \n\t" // load _ActiveMask for 2nd
+                                                //  active byte group
+            "movl _dif, %%edx             \n\t"
+            "movq %%mm7, %%mm6            \n\t"
+// preload  "movl row, %%edi              \n\t"
+            "psllq _ShiftBpp, %%mm6       \n\t" // move mask in mm6 to cover
+                                                //  3rd active byte group
+            "movl %%edi, %%esi            \n\t" // lp = row
+            "movq %%mm6, %%mm5            \n\t"
+// preload  "movl bpp, %%eax              \n\t"
+            "addl %%eax, %%edi            \n\t" // rp = row + bpp
+            "psllq _ShiftBpp, %%mm5       \n\t" // move mask in mm5 to cover
+                                                //  4th active byte group
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%edx,), %%mm1 \n\t"
+
+         "sub_2lp:                        \n\t" // shift data for adding first
+            "psrlq _ShiftRem, %%mm1       \n\t" //  bpp bytes (no need for mask;
+                                                //  shift clears inactive bytes)
+            // add 1st active group
+            "movq (%%edi,%%edx,), %%mm0   \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+
+            // add 2nd active group
+            "movq %%mm0, %%mm1            \n\t" // mov updated Raws to mm1
+            "psllq _ShiftBpp, %%mm1       \n\t" // shift data to pos. correctly
+            "pand %%mm7, %%mm1            \n\t" // mask to use 2nd active group
+            "paddb %%mm1, %%mm0           \n\t"
+
+            // add 3rd active group
+            "movq %%mm0, %%mm1            \n\t" // mov updated Raws to mm1
+            "psllq _ShiftBpp, %%mm1       \n\t" // shift data to pos. correctly
+            "pand %%mm6, %%mm1            \n\t" // mask to use 3rd active group
+            "paddb %%mm1, %%mm0           \n\t"
+
+            // add 4th active group
+            "movq %%mm0, %%mm1            \n\t" // mov updated Raws to mm1
+            "psllq _ShiftBpp, %%mm1       \n\t" // shift data to pos. correctly
+            "pand %%mm5, %%mm1            \n\t" // mask to use 4th active group
+            "addl $8, %%edx               \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+            "cmpl _MMXLength, %%edx       \n\t"
+            "movq %%mm0, -8(%%edi,%%edx,) \n\t" // write updated Raws to array
+            "movq %%mm0, %%mm1            \n\t" // prep 1st add at top of loop
+            "jb sub_2lp                   \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%edx", "%esi"                    // clobber list
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;
+
+      case 8:
+      {
+         __asm__ __volatile__ (
+// preload  "movl row, %%edi              \n\t"
+            "movl _dif, %%edx             \n\t"
+            "movl %%edi, %%esi            \n\t" // lp = row
+// preload  "movl bpp, %%eax              \n\t"
+            "addl %%eax, %%edi            \n\t" // rp = row + bpp
+            "movl _MMXLength, %%ecx       \n\t"
+
+            // prime the pump:  load the first Raw(x-bpp) data set
+            "movq -8(%%edi,%%edx,), %%mm7 \n\t"
+            "andl $0x0000003f, %%ecx      \n\t" // calc bytes over mult of 64
+
+         "sub_8lp:                        \n\t"
+            "movq (%%edi,%%edx,), %%mm0   \n\t" // load Sub(x) for 1st 8 bytes
+            "paddb %%mm7, %%mm0           \n\t"
+            "movq 8(%%edi,%%edx,), %%mm1  \n\t" // load Sub(x) for 2nd 8 bytes
+            "movq %%mm0, (%%edi,%%edx,)   \n\t" // write Raw(x) for 1st 8 bytes
+
+            // Now mm0 will be used as Raw(x-bpp) for the 2nd group of 8 bytes.
+            // This will be repeated for each group of 8 bytes with the 8th
+            // group being used as the Raw(x-bpp) for the 1st group of the
+            // next loop.
+
+            "paddb %%mm0, %%mm1           \n\t"
+            "movq 16(%%edi,%%edx,), %%mm2 \n\t" // load Sub(x) for 3rd 8 bytes
+            "movq %%mm1, 8(%%edi,%%edx,)  \n\t" // write Raw(x) for 2nd 8 bytes
+            "paddb %%mm1, %%mm2           \n\t"
+            "movq 24(%%edi,%%edx,), %%mm3 \n\t" // load Sub(x) for 4th 8 bytes
+            "movq %%mm2, 16(%%edi,%%edx,) \n\t" // write Raw(x) for 3rd 8 bytes
+            "paddb %%mm2, %%mm3           \n\t"
+            "movq 32(%%edi,%%edx,), %%mm4 \n\t" // load Sub(x) for 5th 8 bytes
+            "movq %%mm3, 24(%%edi,%%edx,) \n\t" // write Raw(x) for 4th 8 bytes
+            "paddb %%mm3, %%mm4           \n\t"
+            "movq 40(%%edi,%%edx,), %%mm5 \n\t" // load Sub(x) for 6th 8 bytes
+            "movq %%mm4, 32(%%edi,%%edx,) \n\t" // write Raw(x) for 5th 8 bytes
+            "paddb %%mm4, %%mm5           \n\t"
+            "movq 48(%%edi,%%edx,), %%mm6 \n\t" // load Sub(x) for 7th 8 bytes
+            "movq %%mm5, 40(%%edi,%%edx,) \n\t" // write Raw(x) for 6th 8 bytes
+            "paddb %%mm5, %%mm6           \n\t"
+            "movq 56(%%edi,%%edx,), %%mm7 \n\t" // load Sub(x) for 8th 8 bytes
+            "movq %%mm6, 48(%%edi,%%edx,) \n\t" // write Raw(x) for 7th 8 bytes
+            "addl $64, %%edx              \n\t"
+            "paddb %%mm6, %%mm7           \n\t"
+            "cmpl %%ecx, %%edx            \n\t"
+            "movq %%mm7, -8(%%edi,%%edx,) \n\t" // write Raw(x) for 8th 8 bytes
+            "jb sub_8lp                   \n\t"
+
+            "cmpl _MMXLength, %%edx       \n\t"
+            "jnb sub_8lt8                 \n\t"
+
+         "sub_8lpA:                       \n\t"
+            "movq (%%edi,%%edx,), %%mm0   \n\t"
+            "addl $8, %%edx               \n\t"
+            "paddb %%mm7, %%mm0           \n\t"
+            "cmpl _MMXLength, %%edx       \n\t"
+            "movq %%mm0, -8(%%edi,%%edx,) \n\t" // -8 to offset early addl edx
+            "movq %%mm0, %%mm7            \n\t" // move calculated Raw(x) data
+                                                //  to mm1 to be new Raw(x-bpp)
+                                                //  for next loop
+            "jb sub_8lpA                  \n\t"
+
+         "sub_8lt8:                       \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%ecx", "%edx", "%esi"            // clobber list
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+         );
+      }
+      break;
+
+      default:                // bpp greater than 8 bytes      GRR BOGUS
+      {
+         __asm__ __volatile__ (
+            "movl _dif, %%edx             \n\t"
+// preload  "movl row, %%edi              \n\t"
+            "movl %%edi, %%esi            \n\t" // lp = row
+// preload  "movl bpp, %%eax              \n\t"
+            "addl %%eax, %%edi            \n\t" // rp = row + bpp
+
+         "sub_Alp:                        \n\t"
+            "movq (%%edi,%%edx,), %%mm0   \n\t"
+            "movq (%%esi,%%edx,), %%mm1   \n\t"
+            "addl $8, %%edx               \n\t"
+            "paddb %%mm1, %%mm0           \n\t"
+            "cmpl _MMXLength, %%edx       \n\t"
+            "movq %%mm0, -8(%%edi,%%edx,) \n\t" // mov does not affect flags;
+                                                //  -8 to offset addl edx
+            "jb sub_Alp                   \n\t"
+
+            : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+              "=D" (dummy_value_D)    // 1
+
+            : "0" (bpp),              // eax    // input regs
+              "1" (row)               // edi
+
+            : "%edx", "%esi"                    // clobber list
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+            , "%mm0", "%mm1"
+#endif
+         );
+      }
+      break;
+
+   } // end switch (bpp)
+
+   __asm__ __volatile__ (
+      "movl _MMXLength, %%edx       \n\t"
+//pre "movl row, %%edi              \n\t"
+      "cmpl _FullLength, %%edx      \n\t"
+      "jnb sub_end                  \n\t"
+
+      "movl %%edi, %%esi            \n\t" // lp = row
+//pre "movl bpp, %%eax              \n\t"
+      "addl %%eax, %%edi            \n\t" // rp = row + bpp
+      "xorl %%eax, %%eax            \n\t"
+
+   "sub_lp2:                        \n\t"
+      "movb (%%esi,%%edx,), %%al    \n\t"
+      "addb %%al, (%%edi,%%edx,)    \n\t"
+      "incl %%edx                   \n\t"
+      "cmpl _FullLength, %%edx      \n\t"
+      "jb sub_lp2                   \n\t"
+
+   "sub_end:                        \n\t"
+      "EMMS                         \n\t" // end MMX instructions
+
+      : "=a" (dummy_value_a),   // 0      // output regs (dummy)
+        "=D" (dummy_value_D)    // 1
+
+      : "0" (bpp),              // eax    // input regs
+        "1" (row)               // edi
+
+      : "%edx", "%esi"                    // clobber list
+   );
+
+} // end of png_read_filter_row_mmx_sub()
+#endif
+
+
+
+
+//===========================================================================//
+//                                                                           //
+//            P N G _ R E A D _ F I L T E R _ R O W _ M M X _ U P            //
+//                                                                           //
+//===========================================================================//
+
+// Optimized code for PNG Up filter decoder
+
+static void /* PRIVATE */
+png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row,
+                           png_bytep prev_row)
+{
+   png_uint_32 len;
+   int dummy_value_d;   // fix 'forbidden register 3 (dx) was spilled' error
+   int dummy_value_S;
+   int dummy_value_D;
+
+   len = row_info->rowbytes;              // number of bytes to filter
+
+   __asm__ __volatile__ (
+//pre "movl row, %%edi              \n\t"
+      // get # of bytes to alignment
+      "movl %%edi, %%ecx            \n\t"
+      "xorl %%ebx, %%ebx            \n\t"
+      "addl $0x7, %%ecx             \n\t"
+      "xorl %%eax, %%eax            \n\t"
+      "andl $0xfffffff8, %%ecx      \n\t"
+//pre "movl prev_row, %%esi         \n\t"
+      "subl %%edi, %%ecx            \n\t"
+      "jz up_go                     \n\t"
+
+   "up_lp1:                         \n\t" // fix alignment
+      "movb (%%edi,%%ebx,), %%al    \n\t"
+      "addb (%%esi,%%ebx,), %%al    \n\t"
+      "incl %%ebx                   \n\t"
+      "cmpl %%ecx, %%ebx            \n\t"
+      "movb %%al, -1(%%edi,%%ebx,)  \n\t" // mov does not affect flags; -1 to
+      "jb up_lp1                    \n\t" //  offset incl ebx
+
+   "up_go:                          \n\t"
+//pre "movl len, %%edx              \n\t"
+      "movl %%edx, %%ecx            \n\t"
+      "subl %%ebx, %%edx            \n\t" // subtract alignment fix
+      "andl $0x0000003f, %%edx      \n\t" // calc bytes over mult of 64
+      "subl %%edx, %%ecx            \n\t" // drop over bytes from length
+
+      // unrolled loop - use all MMX registers and interleave to reduce
+      // number of branch instructions (loops) and reduce partial stalls
+   "up_loop:                        \n\t"
+      "movq (%%esi,%%ebx,), %%mm1   \n\t"
+      "movq (%%edi,%%ebx,), %%mm0   \n\t"
+      "movq 8(%%esi,%%ebx,), %%mm3  \n\t"
+      "paddb %%mm1, %%mm0           \n\t"
+      "movq 8(%%edi,%%ebx,), %%mm2  \n\t"
+      "movq %%mm0, (%%edi,%%ebx,)   \n\t"
+      "paddb %%mm3, %%mm2           \n\t"
+      "movq 16(%%esi,%%ebx,), %%mm5 \n\t"
+      "movq %%mm2, 8(%%edi,%%ebx,)  \n\t"
+      "movq 16(%%edi,%%ebx,), %%mm4 \n\t"
+      "movq 24(%%esi,%%ebx,), %%mm7 \n\t"
+      "paddb %%mm5, %%mm4           \n\t"
+      "movq 24(%%edi,%%ebx,), %%mm6 \n\t"
+      "movq %%mm4, 16(%%edi,%%ebx,) \n\t"
+      "paddb %%mm7, %%mm6           \n\t"
+      "movq 32(%%esi,%%ebx,), %%mm1 \n\t"
+      "movq %%mm6, 24(%%edi,%%ebx,) \n\t"
+      "movq 32(%%edi,%%ebx,), %%mm0 \n\t"
+      "movq 40(%%esi,%%ebx,), %%mm3 \n\t"
+      "paddb %%mm1, %%mm0           \n\t"
+      "movq 40(%%edi,%%ebx,), %%mm2 \n\t"
+      "movq %%mm0, 32(%%edi,%%ebx,) \n\t"
+      "paddb %%mm3, %%mm2           \n\t"
+      "movq 48(%%esi,%%ebx,), %%mm5 \n\t"
+      "movq %%mm2, 40(%%edi,%%ebx,) \n\t"
+      "movq 48(%%edi,%%ebx,), %%mm4 \n\t"
+      "movq 56(%%esi,%%ebx,), %%mm7 \n\t"
+      "paddb %%mm5, %%mm4           \n\t"
+      "movq 56(%%edi,%%ebx,), %%mm6 \n\t"
+      "movq %%mm4, 48(%%edi,%%ebx,) \n\t"
+      "addl $64, %%ebx              \n\t"
+      "paddb %%mm7, %%mm6           \n\t"
+      "cmpl %%ecx, %%ebx            \n\t"
+      "movq %%mm6, -8(%%edi,%%ebx,) \n\t" // (+56)movq does not affect flags;
+      "jb up_loop                   \n\t" //  -8 to offset addl ebx
+
+      "cmpl $0, %%edx               \n\t" // test for bytes over mult of 64
+      "jz up_end                    \n\t"
+
+      "cmpl $8, %%edx               \n\t" // test for less than 8 bytes
+      "jb up_lt8                    \n\t" //  [added by lcreeve@netins.net]
+
+      "addl %%edx, %%ecx            \n\t"
+      "andl $0x00000007, %%edx      \n\t" // calc bytes over mult of 8
+      "subl %%edx, %%ecx            \n\t" // drop over bytes from length
+      "jz up_lt8                    \n\t"
+
+   "up_lpA:                         \n\t" // use MMX regs to update 8 bytes sim.
+      "movq (%%esi,%%ebx,), %%mm1   \n\t"
+      "movq (%%edi,%%ebx,), %%mm0   \n\t"
+      "addl $8, %%ebx               \n\t"
+      "paddb %%mm1, %%mm0           \n\t"
+      "cmpl %%ecx, %%ebx            \n\t"
+      "movq %%mm0, -8(%%edi,%%ebx,) \n\t" // movq does not affect flags; -8 to
+      "jb up_lpA                    \n\t" //  offset add ebx
+      "cmpl $0, %%edx               \n\t" // test for bytes over mult of 8
+      "jz up_end                    \n\t"
+
+   "up_lt8:                         \n\t"
+      "xorl %%eax, %%eax            \n\t"
+      "addl %%edx, %%ecx            \n\t" // move over byte count into counter
+
+   "up_lp2:                         \n\t" // use x86 regs for remaining bytes
+      "movb (%%edi,%%ebx,), %%al    \n\t"
+      "addb (%%esi,%%ebx,), %%al    \n\t"
+      "incl %%ebx                   \n\t"
+      "cmpl %%ecx, %%ebx            \n\t"
+      "movb %%al, -1(%%edi,%%ebx,)  \n\t" // mov does not affect flags; -1 to
+      "jb up_lp2                    \n\t" //  offset inc ebx
+
+   "up_end:                         \n\t"
+      "EMMS                         \n\t" // conversion of filtered row complete
+
+      : "=d" (dummy_value_d),   // 0      // output regs (dummy)
+        "=S" (dummy_value_S),   // 1
+        "=D" (dummy_value_D)    // 2
+
+      : "0" (len),              // edx    // input regs
+        "1" (prev_row),         // esi
+        "2" (row)               // edi
+
+      : "%eax", "%ebx", "%ecx"            // clobber list (no input regs!)
+
+#if 0  /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */
+      , "%mm0", "%mm1", "%mm2", "%mm3"
+      , "%mm4", "%mm5", "%mm6", "%mm7"
+#endif
+   );
+
+} // end of png_read_filter_row_mmx_up()
+
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+
+
+
+
+/*===========================================================================*/
+/*                                                                           */
+/*                   P N G _ R E A D _ F I L T E R _ R O W                   */
+/*                                                                           */
+/*===========================================================================*/
+
+
+/* Optimized png_read_filter_row routines */
+
+void /* PRIVATE */
+png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep
+   row, png_bytep prev_row, int filter)
+{
+#ifdef PNG_DEBUG
+   char filnm[10];
+#endif
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+/* GRR:  these are superseded by png_ptr->asm_flags: */
+#define UseMMX_sub    1   // GRR:  converted 20000730
+#define UseMMX_up     1   // GRR:  converted 20000729
+#define UseMMX_avg    1   // GRR:  converted 20000828 (+ 16-bit bugfix 20000916)
+#define UseMMX_paeth  1   // GRR:  converted 20000828
+
+   if (_mmx_supported == 2) {
+       /* this should have happened in png_init_mmx_flags() already */
+       png_warning(png_ptr, "asm_flags may not have been initialized");
+       png_mmx_support();
+   }
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+
+#ifdef PNG_DEBUG
+   png_debug(1, "in png_read_filter_row (pnggccrd.c)\n");
+   switch (filter)
+   {
+      case 0: sprintf(filnm, "none");
+         break;
+      case 1: sprintf(filnm, "sub-%s",
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+        (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "MMX" : 
+#endif
+"x86");
+         break;
+      case 2: sprintf(filnm, "up-%s",
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+        (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "MMX" :
+#endif
+ "x86");
+         break;
+      case 3: sprintf(filnm, "avg-%s",
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+        (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "MMX" :
+#endif
+ "x86");
+         break;
+      case 4: sprintf(filnm, "Paeth-%s",
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+        (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "MMX":
+#endif
+"x86");
+         break;
+      default: sprintf(filnm, "unknw");
+         break;
+   }
+   png_debug2(0, "row_number=%5ld, %5s, ", png_ptr->row_number, filnm);
+   png_debug1(0, "row=0x%08lx, ", (unsigned long)row);
+   png_debug2(0, "pixdepth=%2d, bytes=%d, ", (int)row_info->pixel_depth,
+      (int)((row_info->pixel_depth + 7) >> 3));
+   png_debug1(0,"rowbytes=%8ld\n", row_info->rowbytes);
+#endif /* PNG_DEBUG */
+
+   switch (filter)
+   {
+      case PNG_FILTER_VALUE_NONE:
+         break;
+
+      case PNG_FILTER_VALUE_SUB:
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+         if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB) &&
+             (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
+             (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
+         {
+            png_read_filter_row_mmx_sub(row_info, row);
+         }
+         else
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+         {
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+            png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+            png_bytep rp = row + bpp;
+            png_bytep lp = row;
+
+            for (i = bpp; i < istop; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
+               rp++;
+            }
+         }  /* end !UseMMX_sub */
+         break;
+
+      case PNG_FILTER_VALUE_UP:
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+         if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP) &&
+             (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
+             (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
+         {
+            png_read_filter_row_mmx_up(row_info, row, prev_row);
+         }
+          else
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+         {
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+            png_bytep rp = row;
+            png_bytep pp = prev_row;
+
+            for (i = 0; i < istop; ++i)
+            {
+               *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+               rp++;
+            }
+         }  /* end !UseMMX_up */
+         break;
+
+      case PNG_FILTER_VALUE_AVG:
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+         if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG) &&
+             (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
+             (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
+         {
+            png_read_filter_row_mmx_avg(row_info, row, prev_row);
+         }
+         else
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+         {
+            png_uint_32 i;
+            png_bytep rp = row;
+            png_bytep pp = prev_row;
+            png_bytep lp = row;
+            png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+            png_uint_32 istop = row_info->rowbytes - bpp;
+
+            for (i = 0; i < bpp; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) +
+                  ((int)(*pp++) >> 1)) & 0xff);
+               rp++;
+            }
+
+            for (i = 0; i < istop; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) +
+                  ((int)(*pp++ + *lp++) >> 1)) & 0xff);
+               rp++;
+            }
+         }  /* end !UseMMX_avg */
+         break;
+
+      case PNG_FILTER_VALUE_PAETH:
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_THREAD_UNSAFE_OK)
+         if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH) &&
+             (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
+             (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
+         {
+            png_read_filter_row_mmx_paeth(row_info, row, prev_row);
+         }
+         else
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+         {
+            png_uint_32 i;
+            png_bytep rp = row;
+            png_bytep pp = prev_row;
+            png_bytep lp = row;
+            png_bytep cp = prev_row;
+            png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+            png_uint_32 istop = row_info->rowbytes - bpp;
+
+            for (i = 0; i < bpp; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+               rp++;
+            }
+
+            for (i = 0; i < istop; i++)   /* use leftover rp,pp */
+            {
+               int a, b, c, pa, pb, pc, p;
+
+               a = *lp++;
+               b = *pp++;
+               c = *cp++;
+
+               p = b - c;
+               pc = a - c;
+
+#ifdef PNG_USE_ABS
+               pa = abs(p);
+               pb = abs(pc);
+               pc = abs(p + pc);
+#else
+               pa = p < 0 ? -p : p;
+               pb = pc < 0 ? -pc : pc;
+               pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+               /*
+                  if (pa <= pb && pa <= pc)
+                     p = a;
+                  else if (pb <= pc)
+                     p = b;
+                  else
+                     p = c;
+                */
+
+               p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
+
+               *rp = (png_byte)(((int)(*rp) + p) & 0xff);
+               rp++;
+            }
+         }  /* end !UseMMX_paeth */
+         break;
+
+      default:
+         png_warning(png_ptr, "Ignoring bad row-filter type");
+         *row=0;
+         break;
+   }
+}
+
+#endif /* PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
+
+
+/*===========================================================================*/
+/*                                                                           */
+/*                      P N G _ M M X _ S U P P O R T                        */
+/*                                                                           */
+/*===========================================================================*/
+
+/* GRR NOTES:  (1) the following code assumes 386 or better (pushfl/popfl)
+ *             (2) all instructions compile with gcc 2.7.2.3 and later
+ *             (3) the function is moved down here to prevent gcc from
+ *                  inlining it in multiple places and then barfing be-
+ *                  cause the ".NOT_SUPPORTED" label is multiply defined
+ *             [is there a way to signal that a *single* function should
+ *              not be inlined?  is there a way to modify the label for
+ *              each inlined instance, e.g., by appending _1, _2, etc.?
+ *              maybe if don't use leading "." in label name? (nope...sigh)]
+ */
+
+int PNGAPI
+png_mmx_support(void)
+{
+#if defined(PNG_MMX_CODE_SUPPORTED)
+    __asm__ __volatile__ (
+        "pushl %%ebx          \n\t"  // ebx gets clobbered by CPUID instruction
+        "pushl %%ecx          \n\t"  // so does ecx...
+        "pushl %%edx          \n\t"  // ...and edx (but ecx & edx safe on Linux)
+//      ".byte  0x66          \n\t"  // convert 16-bit pushf to 32-bit pushfd
+//      "pushf                \n\t"  // 16-bit pushf
+        "pushfl               \n\t"  // save Eflag to stack
+        "popl %%eax           \n\t"  // get Eflag from stack into eax
+        "movl %%eax, %%ecx    \n\t"  // make another copy of Eflag in ecx
+        "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21)
+        "pushl %%eax          \n\t"  // save modified Eflag back to stack
+//      ".byte  0x66          \n\t"  // convert 16-bit popf to 32-bit popfd
+//      "popf                 \n\t"  // 16-bit popf
+        "popfl                \n\t"  // restore modified value to Eflag reg
+        "pushfl               \n\t"  // save Eflag to stack
+        "popl %%eax           \n\t"  // get Eflag from stack
+        "xorl %%ecx, %%eax    \n\t"  // compare new Eflag with original Eflag
+        "jz .NOT_SUPPORTED    \n\t"  // if same, CPUID instr. is not supported
+
+        "xorl %%eax, %%eax    \n\t"  // set eax to zero
+//      ".byte  0x0f, 0xa2    \n\t"  // CPUID instruction (two-byte opcode)
+        "cpuid                \n\t"  // get the CPU identification info
+        "cmpl $1, %%eax       \n\t"  // make sure eax return non-zero value
+        "jl .NOT_SUPPORTED    \n\t"  // if eax is zero, MMX is not supported
+
+        "xorl %%eax, %%eax    \n\t"  // set eax to zero and...
+        "incl %%eax           \n\t"  // ...increment eax to 1.  This pair is
+                                     // faster than the instruction "mov eax, 1"
+        "cpuid                \n\t"  // get the CPU identification info again
+        "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23)
+        "cmpl $0, %%edx       \n\t"  // 0 = MMX not supported
+        "jz .NOT_SUPPORTED    \n\t"  // non-zero = yes, MMX IS supported
+
+        "movl $1, %%eax       \n\t"  // set return value to 1
+        "jmp  .RETURN         \n\t"  // DONE:  have MMX support
+
+    ".NOT_SUPPORTED:          \n\t"  // target label for jump instructions
+        "movl $0, %%eax       \n\t"  // set return value to 0
+    ".RETURN:          \n\t"  // target label for jump instructions
+        "movl %%eax, _mmx_supported \n\t" // save in global static variable, too
+        "popl %%edx           \n\t"  // restore edx
+        "popl %%ecx           \n\t"  // restore ecx
+        "popl %%ebx           \n\t"  // restore ebx
+
+//      "ret                  \n\t"  // DONE:  no MMX support
+                                     // (fall through to standard C "ret")
+
+        :                            // output list (none)
+
+        :                            // any variables used on input (none)
+
+        : "%eax"                     // clobber list
+//      , "%ebx", "%ecx", "%edx"     // GRR:  we handle these manually
+//      , "memory"   // if write to a variable gcc thought was in a reg
+//      , "cc"       // "condition codes" (flag bits)
+    );
+#else     
+    _mmx_supported = 0;
+#endif /* PNG_MMX_CODE_SUPPORTED */
+
+    return _mmx_supported;
+}
+
+
+#endif /* PNG_USE_PNGGCCRD */
diff --git a/libraries/libpng-1.2.0/pngget.c b/libraries/libpng-1.2.0/pngget.c
new file mode 100644 (file)
index 0000000..d95d246
--- /dev/null
@@ -0,0 +1,917 @@
+
+/* pngget.c - retrieval of values from info struct
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+png_uint_32 PNGAPI
+png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+      return(info_ptr->valid & flag);
+   else
+      return(0);
+}
+
+png_uint_32 PNGAPI
+png_get_rowbytes(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+      return(info_ptr->rowbytes);
+   else
+      return(0);
+}
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+png_bytepp PNGAPI
+png_get_rows(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+      return(info_ptr->row_pointers);
+   else
+      return(0);
+}
+#endif
+
+#ifdef PNG_EASY_ACCESS_SUPPORTED
+/* easy access to info, added in libpng-0.99 */
+png_uint_32 PNGAPI
+png_get_image_width(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->width;
+   }
+   return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_image_height(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->height;
+   }
+   return (0);
+}
+
+png_byte PNGAPI
+png_get_bit_depth(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->bit_depth;
+   }
+   return (0);
+}
+
+png_byte PNGAPI
+png_get_color_type(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->color_type;
+   }
+   return (0);
+}
+
+png_byte PNGAPI
+png_get_filter_type(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->filter_type;
+   }
+   return (0);
+}
+
+png_byte PNGAPI
+png_get_interlace_type(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->interlace_type;
+   }
+   return (0);
+}
+
+png_byte PNGAPI
+png_get_compression_type(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+   {
+      return info_ptr->compression_type;
+   }
+   return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_pHYs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pHYs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter");
+      if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
+          return (0);
+      else return (info_ptr->x_pixels_per_unit);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_pHYs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pHYs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter");
+      if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
+          return (0);
+      else return (info_ptr->y_pixels_per_unit);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_pHYs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pHYs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter");
+      if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER ||
+         info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit)
+          return (0);
+      else return (info_ptr->x_pixels_per_unit);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+float PNGAPI
+png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr)
+   {
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_pHYs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pHYs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio");
+      if (info_ptr->x_pixels_per_unit == 0)
+         return ((float)0.0);
+      else
+         return ((float)((float)info_ptr->y_pixels_per_unit
+            /(float)info_ptr->x_pixels_per_unit));
+   }
+#else
+   return (0.0);
+#endif
+   return ((float)0.0);
+}
+#endif
+
+png_int_32 PNGAPI
+png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_oFFs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_oFFs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns");
+      if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
+          return (0);
+      else return (info_ptr->x_offset);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+png_int_32 PNGAPI
+png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_oFFs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_oFFs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns");
+      if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
+          return (0);
+      else return (info_ptr->y_offset);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+png_int_32 PNGAPI
+png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_oFFs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_oFFs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns");
+      if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
+          return (0);
+      else return (info_ptr->x_offset);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+png_int_32 PNGAPI
+png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+#if defined(PNG_oFFs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_oFFs)
+   {
+      png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns");
+      if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
+          return (0);
+      else return (info_ptr->y_offset);
+   }
+#else
+   return (0);
+#endif
+   return (0);
+}
+
+#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
+{
+   return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr)
+     *.0254 +.5));
+}
+
+png_uint_32 PNGAPI
+png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
+{
+   return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr)
+     *.0254 +.5));
+}
+
+png_uint_32 PNGAPI
+png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
+{
+   return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr)
+     *.0254 +.5));
+}
+
+float PNGAPI
+png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr)
+{
+   return ((float)png_get_x_offset_microns(png_ptr, info_ptr)
+     *.00003937);
+}
+
+float PNGAPI
+png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr)
+{
+   return ((float)png_get_y_offset_microns(png_ptr, info_ptr)
+     *.00003937);
+}
+
+#if defined(PNG_pHYs_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
+{
+   png_uint_32 retval = 0;
+
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+   {
+      png_debug1(1, "in %s retrieval function\n", "pHYs");
+      if (res_x != NULL)
+      {
+         *res_x = info_ptr->x_pixels_per_unit;
+         retval |= PNG_INFO_pHYs;
+      }
+      if (res_y != NULL)
+      {
+         *res_y = info_ptr->y_pixels_per_unit;
+         retval |= PNG_INFO_pHYs;
+      }
+      if (unit_type != NULL)
+      {
+         *unit_type = (int)info_ptr->phys_unit_type;
+         retval |= PNG_INFO_pHYs;
+         if(*unit_type == 1)
+         {
+            if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50);
+            if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50);
+         }
+      }
+   }
+   return (retval);
+}
+#endif /* PNG_pHYs_SUPPORTED */
+#endif  /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */
+
+/* png_get_channels really belongs in here, too, but it's been around longer */
+
+#endif  /* PNG_EASY_ACCESS_SUPPORTED */
+
+png_byte PNGAPI
+png_get_channels(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+      return(info_ptr->channels);
+   else
+      return (0);
+}
+
+png_bytep PNGAPI
+png_get_signature(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr != NULL && info_ptr != NULL)
+      return(info_ptr->signature);
+   else
+      return (NULL);
+}
+
+#if defined(PNG_bKGD_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_bKGD(png_structp png_ptr, png_infop info_ptr,
+   png_color_16p *background)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)
+      && background != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "bKGD");
+      *background = &(info_ptr->background);
+      return (PNG_INFO_bKGD);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_cHRM(png_structp png_ptr, png_infop info_ptr,
+   double *white_x, double *white_y, double *red_x, double *red_y,
+   double *green_x, double *green_y, double *blue_x, double *blue_y)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
+   {
+      png_debug1(1, "in %s retrieval function\n", "cHRM");
+      if (white_x != NULL)
+         *white_x = (double)info_ptr->x_white;
+      if (white_y != NULL)
+         *white_y = (double)info_ptr->y_white;
+      if (red_x != NULL)
+         *red_x = (double)info_ptr->x_red;
+      if (red_y != NULL)
+         *red_y = (double)info_ptr->y_red;
+      if (green_x != NULL)
+         *green_x = (double)info_ptr->x_green;
+      if (green_y != NULL)
+         *green_y = (double)info_ptr->y_green;
+      if (blue_x != NULL)
+         *blue_x = (double)info_ptr->x_blue;
+      if (blue_y != NULL)
+         *blue_y = (double)info_ptr->y_blue;
+      return (PNG_INFO_cHRM);
+   }
+   return (0);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
+   png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
+   png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
+   png_fixed_point *blue_x, png_fixed_point *blue_y)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
+   {
+      png_debug1(1, "in %s retrieval function\n", "cHRM");
+      if (white_x != NULL)
+         *white_x = info_ptr->int_x_white;
+      if (white_y != NULL)
+         *white_y = info_ptr->int_y_white;
+      if (red_x != NULL)
+         *red_x = info_ptr->int_x_red;
+      if (red_y != NULL)
+         *red_y = info_ptr->int_y_red;
+      if (green_x != NULL)
+         *green_x = info_ptr->int_x_green;
+      if (green_y != NULL)
+         *green_y = info_ptr->int_y_green;
+      if (blue_x != NULL)
+         *blue_x = info_ptr->int_x_blue;
+      if (blue_y != NULL)
+         *blue_y = info_ptr->int_y_blue;
+      return (PNG_INFO_cHRM);
+   }
+   return (0);
+}
+#endif
+#endif
+
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
+      && file_gamma != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "gAMA");
+      *file_gamma = (double)info_ptr->gamma;
+      return (PNG_INFO_gAMA);
+   }
+   return (0);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr,
+    png_fixed_point *int_file_gamma)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
+      && int_file_gamma != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "gAMA");
+      *int_file_gamma = info_ptr->int_gamma;
+      return (PNG_INFO_gAMA);
+   }
+   return (0);
+}
+#endif
+#endif
+
+#if defined(PNG_sRGB_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)
+      && file_srgb_intent != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "sRGB");
+      *file_srgb_intent = (int)info_ptr->srgb_intent;
+      return (PNG_INFO_sRGB);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_iCCP_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_iCCP(png_structp png_ptr, png_infop info_ptr,
+             png_charpp name, int *compression_type,
+             png_charpp profile, png_uint_32 *proflen)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)
+      && name != NULL && profile != NULL && proflen != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "iCCP");
+      *name = info_ptr->iccp_name;
+      *profile = info_ptr->iccp_profile;
+      /* compression_type is a dummy so the API won't have to change
+         if we introduce multiple compression types later. */
+      *proflen = (int)info_ptr->iccp_proflen;
+      *compression_type = (int)info_ptr->iccp_compression;
+      return (PNG_INFO_iCCP);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_sPLT(png_structp png_ptr, png_infop info_ptr,
+             png_sPLT_tpp spalettes)
+{
+   if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
+     *spalettes = info_ptr->splt_palettes;
+   return ((png_uint_32)info_ptr->splt_palettes_num);
+}
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)
+      && hist != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "hIST");
+      *hist = info_ptr->hist;
+      return (PNG_INFO_hIST);
+   }
+   return (0);
+}
+#endif
+
+png_uint_32 PNGAPI
+png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 *width, png_uint_32 *height, int *bit_depth,
+   int *color_type, int *interlace_type, int *compression_type,
+   int *filter_type)
+
+{
+   if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL &&
+      bit_depth != NULL && color_type != NULL)
+   {
+      int pixel_depth, channels;
+      png_uint_32 rowbytes_per_pixel;
+
+      png_debug1(1, "in %s retrieval function\n", "IHDR");
+      *width = info_ptr->width;
+      *height = info_ptr->height;
+      *bit_depth = info_ptr->bit_depth;
+      *color_type = info_ptr->color_type;
+      if (compression_type != NULL)
+         *compression_type = info_ptr->compression_type;
+      if (filter_type != NULL)
+         *filter_type = info_ptr->filter_type;
+      if (interlace_type != NULL)
+         *interlace_type = info_ptr->interlace_type;
+
+      /* check for potential overflow of rowbytes */
+      if (*color_type == PNG_COLOR_TYPE_PALETTE)
+         channels = 1;
+      else if (*color_type & PNG_COLOR_MASK_COLOR)
+         channels = 3;
+      else
+         channels = 1;
+      if (*color_type & PNG_COLOR_MASK_ALPHA)
+         channels++;
+      pixel_depth = *bit_depth * channels;
+      rowbytes_per_pixel = (pixel_depth + 7) >> 3;
+      if ((*width > PNG_MAX_UINT/rowbytes_per_pixel))
+      {
+         png_warning(png_ptr,
+            "Width too large for libpng to process image data.");
+      }
+      return (1);
+   }
+   return (0);
+}
+
+#if defined(PNG_oFFs_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_oFFs(png_structp png_ptr, png_infop info_ptr,
+   png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)
+      && offset_x != NULL && offset_y != NULL && unit_type != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "oFFs");
+      *offset_x = info_ptr->x_offset;
+      *offset_y = info_ptr->y_offset;
+      *unit_type = (int)info_ptr->offset_unit_type;
+      return (PNG_INFO_oFFs);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_pCAL(png_structp png_ptr, png_infop info_ptr,
+   png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
+   png_charp *units, png_charpp *params)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)
+      && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
+      nparams != NULL && units != NULL && params != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "pCAL");
+      *purpose = info_ptr->pcal_purpose;
+      *X0 = info_ptr->pcal_X0;
+      *X1 = info_ptr->pcal_X1;
+      *type = (int)info_ptr->pcal_type;
+      *nparams = (int)info_ptr->pcal_nparams;
+      *units = info_ptr->pcal_units;
+      *params = info_ptr->pcal_params;
+      return (PNG_INFO_pCAL);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_sCAL_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_sCAL(png_structp png_ptr, png_infop info_ptr,
+             int *unit, double *width, double *height)
+{
+    if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_sCAL))
+    {
+        *unit = info_ptr->scal_unit;
+        *width = info_ptr->scal_pixel_width;
+        *height = info_ptr->scal_pixel_height;
+        return (PNG_INFO_sCAL);
+    }
+    return(0);
+}
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr,
+             int *unit, png_charpp width, png_charpp height)
+{
+    if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_sCAL))
+    {
+        *unit = info_ptr->scal_unit;
+        *width = info_ptr->scal_s_width;
+        *height = info_ptr->scal_s_height;
+        return (PNG_INFO_sCAL);
+    }
+    return(0);
+}
+#endif
+#endif
+#endif
+
+#if defined(PNG_pHYs_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_pHYs(png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
+{
+   png_uint_32 retval = 0;
+
+   if (png_ptr != NULL && info_ptr != NULL &&
+      (info_ptr->valid & PNG_INFO_pHYs))
+   {
+      png_debug1(1, "in %s retrieval function\n", "pHYs");
+      if (res_x != NULL)
+      {
+         *res_x = info_ptr->x_pixels_per_unit;
+         retval |= PNG_INFO_pHYs;
+      }
+      if (res_y != NULL)
+      {
+         *res_y = info_ptr->y_pixels_per_unit;
+         retval |= PNG_INFO_pHYs;
+      }
+      if (unit_type != NULL)
+      {
+         *unit_type = (int)info_ptr->phys_unit_type;
+         retval |= PNG_INFO_pHYs;
+      }
+   }
+   return (retval);
+}
+#endif
+
+png_uint_32 PNGAPI
+png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette,
+   int *num_palette)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE)
+       && palette != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "PLTE");
+      *palette = info_ptr->palette;
+      *num_palette = info_ptr->num_palette;
+      png_debug1(3, "num_palette = %d\n", *num_palette);
+      return (PNG_INFO_PLTE);
+   }
+   return (0);
+}
+
+#if defined(PNG_sBIT_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)
+      && sig_bit != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "sBIT");
+      *sig_bit = &(info_ptr->sig_bit);
+      return (PNG_INFO_sBIT);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_TEXT_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr,
+   int *num_text)
+{
+   if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
+   {
+      png_debug1(1, "in %s retrieval function\n",
+         (png_ptr->chunk_name[0] == '\0' ? "text"
+             : (png_const_charp)png_ptr->chunk_name));
+      if (text_ptr != NULL)
+         *text_ptr = info_ptr->text;
+      if (num_text != NULL)
+         *num_text = info_ptr->num_text;
+      return ((png_uint_32)info_ptr->num_text);
+   }
+   if (num_text != NULL)
+     *num_text = 0;
+   return(0);
+}
+#endif
+
+#if defined(PNG_tIME_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
+{
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)
+       && mod_time != NULL)
+   {
+      png_debug1(1, "in %s retrieval function\n", "tIME");
+      *mod_time = &(info_ptr->mod_time);
+      return (PNG_INFO_tIME);
+   }
+   return (0);
+}
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
+   png_bytep *trans, int *num_trans, png_color_16p *trans_values)
+{
+   png_uint_32 retval = 0;
+   if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+   {
+      png_debug1(1, "in %s retrieval function\n", "tRNS");
+      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+          if (trans != NULL)
+          {
+             *trans = info_ptr->trans;
+             retval |= PNG_INFO_tRNS;
+          }
+          if (trans_values != NULL)
+             *trans_values = &(info_ptr->trans_values);
+      }
+      else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */
+      {
+          if (trans_values != NULL)
+          {
+             *trans_values = &(info_ptr->trans_values);
+             retval |= PNG_INFO_tRNS;
+          }
+          if(trans != NULL)
+             *trans = NULL;
+      }
+      if(num_trans != NULL)
+      {
+         *num_trans = info_ptr->num_trans;
+         retval |= PNG_INFO_tRNS;
+      }
+   }
+   return (retval);
+}
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr,
+             png_unknown_chunkpp unknowns)
+{
+   if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL)
+     *unknowns = info_ptr->unknown_chunks;
+   return ((png_uint_32)info_ptr->unknown_chunks_num);
+}
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+png_byte PNGAPI
+png_get_rgb_to_gray_status (png_structp png_ptr)
+{
+   return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0);
+}
+#endif
+
+#if defined(PNG_USER_CHUNKS_SUPPORTED)
+png_voidp PNGAPI
+png_get_user_chunk_ptr(png_structp png_ptr)
+{
+   return (png_ptr? png_ptr->user_chunk_ptr : NULL);
+}
+#endif
+
+
+png_uint_32 PNGAPI
+png_get_compression_buffer_size(png_structp png_ptr)
+{
+   return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L);
+}
+
+
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+/* this function was added to libpng 1.2.0 and should exist by default*/
+png_uint_32 PNGAPI
+png_get_asm_flags (png_structp png_ptr)
+{
+    return (png_uint_32)(png_ptr? png_ptr->asm_flags : 0L);
+}
+
+/* this function was added to libpng 1.2.0 and should exist by default */
+png_uint_32 PNGAPI
+png_get_asm_flagmask (int flag_select)
+{
+    png_uint_32 settable_asm_flags = 0;
+
+    if (flag_select & PNG_SELECT_READ)
+        settable_asm_flags |=
+          PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  |
+          PNG_ASM_FLAG_MMX_READ_INTERLACE    |
+          PNG_ASM_FLAG_MMX_READ_FILTER_SUB   |
+          PNG_ASM_FLAG_MMX_READ_FILTER_UP    |
+          PNG_ASM_FLAG_MMX_READ_FILTER_AVG   |
+          PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ;
+          /* no non-MMX flags yet */
+
+#if 0
+    /* GRR:  no write-flags yet, either, but someday... */
+    if (flag_select & PNG_SELECT_WRITE)
+        settable_asm_flags |=
+          PNG_ASM_FLAG_MMX_WRITE_ [whatever] ;
+#endif /* 0 */
+
+    return settable_asm_flags;  /* _theoretically_ settable capabilities only */
+}
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+    /* GRR:  could add this:   && defined(PNG_MMX_CODE_SUPPORTED) */
+/* this function was added to libpng 1.2.0 */
+png_uint_32 PNGAPI
+png_get_mmx_flagmask (int flag_select, int *compilerID)
+{
+    png_uint_32 settable_mmx_flags = 0;
+
+    if (flag_select & PNG_SELECT_READ)
+        settable_mmx_flags |=
+          PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  |
+          PNG_ASM_FLAG_MMX_READ_INTERLACE    |
+          PNG_ASM_FLAG_MMX_READ_FILTER_SUB   |
+          PNG_ASM_FLAG_MMX_READ_FILTER_UP    |
+          PNG_ASM_FLAG_MMX_READ_FILTER_AVG   |
+          PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ;
+#if 0
+    /* GRR:  no MMX write support yet, but someday... */
+    if (flag_select & PNG_SELECT_WRITE)
+        settable_mmx_flags |=
+          PNG_ASM_FLAG_MMX_WRITE_ [whatever] ;
+#endif /* 0 */
+
+    if (compilerID != NULL) {
+#ifdef PNG_USE_PNGVCRD
+        *compilerID = 1;    /* MSVC */
+#else
+#ifdef PNG_USE_PNGGCCRD
+        *compilerID = 2;    /* gcc/gas */
+#else
+        *compilerID = -1;   /* unknown (i.e., no asm/MMX code compiled) */
+#endif
+#endif
+    }
+
+    return settable_mmx_flags;  /* _theoretically_ settable capabilities only */
+}
+
+/* this function was added to libpng 1.2.0 */
+png_byte PNGAPI
+png_get_mmx_bitdepth_threshold (png_structp png_ptr)
+{
+    return (png_byte)(png_ptr? png_ptr->mmx_bitdepth_threshold : 0);
+}
+
+/* this function was added to libpng 1.2.0 */
+png_uint_32 PNGAPI
+png_get_mmx_rowbytes_threshold (png_structp png_ptr)
+{
+    return (png_uint_32)(png_ptr? png_ptr->mmx_rowbytes_threshold : 0L);
+}
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
diff --git a/libraries/libpng-1.2.0/pngmem.c b/libraries/libpng-1.2.0/pngmem.c
new file mode 100644 (file)
index 0000000..4cf4db6
--- /dev/null
@@ -0,0 +1,531 @@
+
+/* pngmem.c - stub functions for memory allocation
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file provides a location for all memory allocation.  Users who
+ * need special memory handling are expected to supply replacement
+ * functions for png_malloc() and png_free(), and to use
+ * png_create_read_struct_2() and png_create_write_struct_2() to
+ * identify the replacement functions.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+/* Borland DOS special memory handler */
+#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
+/* if you change this, be sure to change the one in png.h also */
+
+/* Allocate memory for a png_struct.  The malloc and memset can be replaced
+   by a single call to calloc() if this is thought to improve performance. */
+png_voidp /* PRIVATE */
+png_create_struct(int type)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_struct_2(type, NULL, NULL));
+}
+
+/* Alternate version of png_create_struct, for use with user-defined malloc. */
+png_voidp /* PRIVATE */
+png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+   png_size_t size;
+   png_voidp struct_ptr;
+
+   if (type == PNG_STRUCT_INFO)
+     size = sizeof(png_info);
+   else if (type == PNG_STRUCT_PNG)
+     size = sizeof(png_struct);
+   else
+     return ((png_voidp)NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(malloc_fn != NULL)
+   {
+      if (mem_ptr != NULL)
+      {
+         png_struct dummy_struct;
+         png_structp png_ptr = &dummy_struct;
+         png_ptr->mem_ptr=mem_ptr;
+         struct_ptr = (*(malloc_fn))(png_ptr, size);
+      }
+      else
+         struct_ptr = (*(malloc_fn))(NULL, size);
+      if (struct_ptr != NULL)
+         png_memset(struct_ptr, 0, size);
+      return (struct_ptr);
+   }
+#endif /* PNG_USER_MEM_SUPPORTED */
+   if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
+   {
+      png_memset(struct_ptr, 0, size);
+   }
+   return (struct_ptr);
+}
+
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct(png_voidp struct_ptr)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL, (png_voidp)NULL);
+}
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
+    png_voidp mem_ptr)
+{
+#endif
+   if (struct_ptr != NULL)
+   {
+#ifdef PNG_USER_MEM_SUPPORTED
+      if(free_fn != NULL)
+      {
+         png_struct dummy_struct;
+         png_structp png_ptr = &dummy_struct;
+         png_ptr->mem_ptr=mem_ptr;
+         (*(free_fn))(png_ptr, struct_ptr);
+         return;
+      }
+#endif /* PNG_USER_MEM_SUPPORTED */
+      farfree (struct_ptr);
+   }
+}
+
+/* Allocate memory.  For reasonable files, size should never exceed
+ * 64K.  However, zlib may allocate more then 64K if you don't tell
+ * it not to.  See zconf.h and png.h for more information. zlib does
+ * need to allocate exactly 64K, so whatever you call here must
+ * have the ability to do that.
+ *
+ * Borland seems to have a problem in DOS mode for exactly 64K.
+ * It gives you a segment with an offset of 8 (perhaps to store its
+ * memory stuff).  zlib doesn't like this at all, so we have to
+ * detect and deal with it.  This code should not be needed in
+ * Windows or OS/2 modes, and only in 16 bit mode.  This code has
+ * been updated by Alexander Lehmann for version 0.89 to waste less
+ * memory.
+ *
+ * Note that we can't use png_size_t for the "size" declaration,
+ * since on some systems a png_size_t is a 16-bit quantity, and as a
+ * result, we would be truncating potentially larger memory requests
+ * (which should cause a fatal error) and introducing major problems.
+ */
+png_voidp PNGAPI
+png_malloc(png_structp png_ptr, png_uint_32 size)
+{
+#ifndef PNG_USER_MEM_SUPPORTED
+   png_voidp ret;
+#endif
+   if (png_ptr == NULL || size == 0)
+      return ((png_voidp)NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(png_ptr->malloc_fn != NULL)
+   {
+       ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
+       if (ret == NULL)
+          png_error(png_ptr, "Out of memory!");
+       return (ret);
+   }
+   else
+       return png_malloc_default(png_ptr, size);
+}
+
+png_voidp PNGAPI
+png_malloc_default(png_structp png_ptr, png_uint_32 size)
+{
+   png_voidp ret;
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#ifdef PNG_MAX_MALLOC_64K
+   if (size > (png_uint_32)65536L)
+      png_error(png_ptr, "Cannot Allocate > 64K");
+#endif
+
+   if (size == (png_uint_32)65536L)
+   {
+      if (png_ptr->offset_table == NULL)
+      {
+         /* try to see if we need to do any of this fancy stuff */
+         ret = farmalloc(size);
+         if (ret == NULL || ((png_size_t)ret & 0xffff))
+         {
+            int num_blocks;
+            png_uint_32 total_size;
+            png_bytep table;
+            int i;
+            png_byte huge * hptr;
+
+            if (ret != NULL)
+            {
+               farfree(ret);
+               ret = NULL;
+            }
+
+            if(png_ptr->zlib_window_bits > 14)
+               num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
+            else
+               num_blocks = 1;
+            if (png_ptr->zlib_mem_level >= 7)
+               num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
+            else
+               num_blocks++;
+
+            total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
+
+            table = farmalloc(total_size);
+
+            if (table == NULL)
+            {
+               png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
+            }
+
+            if ((png_size_t)table & 0xfff0)
+            {
+               png_error(png_ptr, "Farmalloc didn't return normalized pointer");
+            }
+
+            png_ptr->offset_table = table;
+            png_ptr->offset_table_ptr = farmalloc(num_blocks *
+               sizeof (png_bytep));
+
+            if (png_ptr->offset_table_ptr == NULL)
+            {
+               png_error(png_ptr, "Out Of memory.");
+            }
+
+            hptr = (png_byte huge *)table;
+            if ((png_size_t)hptr & 0xf)
+            {
+               hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
+               hptr = hptr + 16L;  /* "hptr += 16L" fails on Turbo C++ 3.0 */
+            }
+            for (i = 0; i < num_blocks; i++)
+            {
+               png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
+               hptr = hptr + (png_uint_32)65536L;  /* "+=" fails on TC++3.0 */
+            }
+
+            png_ptr->offset_table_number = num_blocks;
+            png_ptr->offset_table_count = 0;
+            png_ptr->offset_table_count_free = 0;
+         }
+      }
+
+      if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
+         png_error(png_ptr, "Out of Memory.");
+
+      ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
+   }
+   else
+      ret = farmalloc(size);
+
+   if (ret == NULL)
+   {
+      png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
+   }
+
+   return (ret);
+}
+
+/* free a pointer allocated by png_malloc().  In the default
+   configuration, png_ptr is not used, but is passed in case it
+   is needed.  If ptr is NULL, return without taking any action. */
+void PNGAPI
+png_free(png_structp png_ptr, png_voidp ptr)
+{
+   if (png_ptr == NULL || ptr == NULL)
+      return;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if (png_ptr->free_fn != NULL)
+   {
+      (*(png_ptr->free_fn))(png_ptr, ptr);
+      return;
+   }
+   else png_free_default(png_ptr, ptr);
+}
+
+void PNGAPI
+png_free_default(png_structp png_ptr, png_voidp ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+   if (png_ptr->offset_table != NULL)
+   {
+      int i;
+
+      for (i = 0; i < png_ptr->offset_table_count; i++)
+      {
+         if (ptr == png_ptr->offset_table_ptr[i])
+         {
+            ptr = NULL;
+            png_ptr->offset_table_count_free++;
+            break;
+         }
+      }
+      if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
+      {
+         farfree(png_ptr->offset_table);
+         farfree(png_ptr->offset_table_ptr);
+         png_ptr->offset_table = NULL;
+         png_ptr->offset_table_ptr = NULL;
+      }
+   }
+
+   if (ptr != NULL)
+   {
+      farfree(ptr);
+   }
+}
+
+#else /* Not the Borland DOS special memory handler */
+
+/* Allocate memory for a png_struct or a png_info.  The malloc and
+   memset can be replaced by a single call to calloc() if this is thought
+   to improve performance noticably.*/
+png_voidp /* PRIVATE */
+png_create_struct(int type)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_struct_2(type, NULL, NULL));
+}
+
+/* Allocate memory for a png_struct or a png_info.  The malloc and
+   memset can be replaced by a single call to calloc() if this is thought
+   to improve performance noticably.*/
+png_voidp /* PRIVATE */
+png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+   png_size_t size;
+   png_voidp struct_ptr;
+
+   if (type == PNG_STRUCT_INFO)
+      size = sizeof(png_info);
+   else if (type == PNG_STRUCT_PNG)
+      size = sizeof(png_struct);
+   else
+      return ((png_voidp)NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(malloc_fn != NULL)
+   {
+      if (mem_ptr != NULL)
+      {
+         png_struct dummy_struct;
+         png_structp png_ptr = &dummy_struct;
+         png_ptr->mem_ptr=mem_ptr;
+         struct_ptr = (*(malloc_fn))(png_ptr, size);
+      }
+      else
+         struct_ptr = (*(malloc_fn))(NULL, size);
+      if (struct_ptr != NULL)
+         png_memset(struct_ptr, 0, size);
+      return (struct_ptr);
+   }
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#if defined(__TURBOC__) && !defined(__FLAT__)
+   if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+   if ((struct_ptr = (png_voidp)halloc(size,1)) != NULL)
+# else
+   if ((struct_ptr = (png_voidp)malloc(size)) != NULL)
+# endif
+#endif
+   {
+      png_memset(struct_ptr, 0, size);
+   }
+
+   return (struct_ptr);
+}
+
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct(png_voidp struct_ptr)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL, (png_voidp)NULL);
+}
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
+    png_voidp mem_ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+   if (struct_ptr != NULL)
+   {
+#ifdef PNG_USER_MEM_SUPPORTED
+      if(free_fn != NULL)
+      {
+         png_struct dummy_struct;
+         png_structp png_ptr = &dummy_struct;
+         png_ptr->mem_ptr=mem_ptr;
+         (*(free_fn))(png_ptr, struct_ptr);
+         return;
+      }
+#endif /* PNG_USER_MEM_SUPPORTED */
+#if defined(__TURBOC__) && !defined(__FLAT__)
+      farfree(struct_ptr);
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+      hfree(struct_ptr);
+# else
+      free(struct_ptr);
+# endif
+#endif
+   }
+}
+
+
+/* Allocate memory.  For reasonable files, size should never exceed
+   64K.  However, zlib may allocate more then 64K if you don't tell
+   it not to.  See zconf.h and png.h for more information.  zlib does
+   need to allocate exactly 64K, so whatever you call here must
+   have the ability to do that. */
+
+png_voidp PNGAPI
+png_malloc(png_structp png_ptr, png_uint_32 size)
+{
+   png_voidp ret;
+   if (png_ptr == NULL || size == 0)
+      return ((png_voidp)NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if(png_ptr->malloc_fn != NULL)
+   {
+       ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
+       if (ret == NULL)
+          png_error(png_ptr, "Out of Memory!");
+       return (ret);
+   }
+   else
+       return (png_malloc_default(png_ptr, size));
+}
+png_voidp /* PRIVATE */
+png_malloc_default(png_structp png_ptr, png_uint_32 size)
+{
+   png_voidp ret;
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#ifdef PNG_MAX_MALLOC_64K
+   if (size > (png_uint_32)65536L)
+      png_error(png_ptr, "Cannot Allocate > 64K");
+#endif
+
+#if defined(__TURBOC__) && !defined(__FLAT__)
+   ret = farmalloc(size);
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+   ret = halloc(size, 1);
+# else
+   ret = malloc((size_t)size);
+# endif
+#endif
+
+   if (ret == NULL)
+      png_error(png_ptr, "Out of Memory");
+
+   return (ret);
+}
+
+/* Free a pointer allocated by png_malloc().  If ptr is NULL, return
+   without taking any action. */
+void PNGAPI
+png_free(png_structp png_ptr, png_voidp ptr)
+{
+   if (png_ptr == NULL || ptr == NULL)
+      return;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   if (png_ptr->free_fn != NULL)
+   {
+      (*(png_ptr->free_fn))(png_ptr, ptr);
+      return;
+   }
+   else png_free_default(png_ptr, ptr);
+}
+void /* PRIVATE */
+png_free_default(png_structp png_ptr, png_voidp ptr)
+{
+   if (png_ptr == NULL || ptr == NULL)
+      return;
+
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#if defined(__TURBOC__) && !defined(__FLAT__)
+   farfree(ptr);
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+   hfree(ptr);
+# else
+   free(ptr);
+# endif
+#endif
+}
+
+#endif /* Not Borland DOS special memory handler */
+
+png_voidp /* PRIVATE */
+png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
+   png_uint_32 length)
+{
+   png_size_t size;
+
+   size = (png_size_t)length;
+   if ((png_uint_32)size != length)
+      png_error(png_ptr,"Overflow in png_memcpy_check.");
+
+   return(png_memcpy (s1, s2, size));
+}
+
+png_voidp /* PRIVATE */
+png_memset_check (png_structp png_ptr, png_voidp s1, int value,
+   png_uint_32 length)
+{
+   png_size_t size;
+
+   size = (png_size_t)length;
+   if ((png_uint_32)size != length)
+      png_error(png_ptr,"Overflow in png_memset_check.");
+
+   return (png_memset (s1, value, size));
+
+}
+
+#ifdef PNG_USER_MEM_SUPPORTED
+/* This function is called when the application wants to use another method
+ * of allocating and freeing memory.
+ */
+void PNGAPI
+png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
+  malloc_fn, png_free_ptr free_fn)
+{
+   png_ptr->mem_ptr = mem_ptr;
+   png_ptr->malloc_fn = malloc_fn;
+   png_ptr->free_fn = free_fn;
+}
+
+/* This function returns a pointer to the mem_ptr associated with the user
+ * functions.  The application should free any memory associated with this
+ * pointer before png_write_destroy and png_read_destroy are called.
+ */
+png_voidp PNGAPI
+png_get_mem_ptr(png_structp png_ptr)
+{
+   return ((png_voidp)png_ptr->mem_ptr);
+}
+#endif /* PNG_USER_MEM_SUPPORTED */
diff --git a/libraries/libpng-1.2.0/pngnow.png b/libraries/libpng-1.2.0/pngnow.png
new file mode 100644 (file)
index 0000000..4b5c9ac
Binary files /dev/null and b/libraries/libpng-1.2.0/pngnow.png differ
diff --git a/libraries/libpng-1.2.0/pngpread.c b/libraries/libpng-1.2.0/pngpread.c
new file mode 100644 (file)
index 0000000..4f7baf6
--- /dev/null
@@ -0,0 +1,1502 @@
+
+/* pngpread.c - read a png file in push mode
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+
+/* push model modes */
+#define PNG_READ_SIG_MODE   0
+#define PNG_READ_CHUNK_MODE 1
+#define PNG_READ_IDAT_MODE  2
+#define PNG_SKIP_MODE       3
+#define PNG_READ_tEXt_MODE  4
+#define PNG_READ_zTXt_MODE  5
+#define PNG_READ_DONE_MODE  6
+#define PNG_READ_iTXt_MODE  7
+#define PNG_ERROR_MODE      8
+
+void PNGAPI
+png_process_data(png_structp png_ptr, png_infop info_ptr,
+   png_bytep buffer, png_size_t buffer_size)
+{
+   png_push_restore_buffer(png_ptr, buffer, buffer_size);
+
+   while (png_ptr->buffer_size)
+   {
+      png_process_some_data(png_ptr, info_ptr);
+   }
+}
+
+/* What we do with the incoming data depends on what we were previously
+ * doing before we ran out of data...
+ */
+void /* PRIVATE */
+png_process_some_data(png_structp png_ptr, png_infop info_ptr)
+{
+   switch (png_ptr->process_mode)
+   {
+      case PNG_READ_SIG_MODE:
+      {
+         png_push_read_sig(png_ptr, info_ptr);
+         break;
+      }
+      case PNG_READ_CHUNK_MODE:
+      {
+         png_push_read_chunk(png_ptr, info_ptr);
+         break;
+      }
+      case PNG_READ_IDAT_MODE:
+      {
+         png_push_read_IDAT(png_ptr);
+         break;
+      }
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      case PNG_READ_tEXt_MODE:
+      {
+         png_push_read_tEXt(png_ptr, info_ptr);
+         break;
+      }
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      case PNG_READ_zTXt_MODE:
+      {
+         png_push_read_zTXt(png_ptr, info_ptr);
+         break;
+      }
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+      case PNG_READ_iTXt_MODE:
+      {
+         png_push_read_iTXt(png_ptr, info_ptr);
+         break;
+      }
+#endif
+      case PNG_SKIP_MODE:
+      {
+         png_push_crc_finish(png_ptr);
+         break;
+      }
+      default:
+      {
+         png_ptr->buffer_size = 0;
+         break;
+      }
+   }
+}
+
+/* Read any remaining signature bytes from the stream and compare them with
+ * the correct PNG signature.  It is possible that this routine is called
+ * with bytes already read from the signature, either because they have been
+ * checked by the calling application, or because of multiple calls to this
+ * routine.
+ */
+void /* PRIVATE */
+png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
+{
+   png_size_t num_checked = png_ptr->sig_bytes,
+             num_to_check = 8 - num_checked;
+
+   if (png_ptr->buffer_size < num_to_check)
+   {
+      num_to_check = png_ptr->buffer_size;
+   }
+
+   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
+      num_to_check);
+   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check);
+
+   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
+   {
+      if (num_checked < 4 &&
+          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
+         png_error(png_ptr, "Not a PNG file");
+      else
+         png_error(png_ptr, "PNG file corrupted by ASCII conversion");
+   }
+   else
+   {
+      if (png_ptr->sig_bytes >= 8)
+      {
+         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
+      }
+   }
+}
+
+void /* PRIVATE */
+png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+      PNG_IHDR;
+      PNG_IDAT;
+      PNG_IEND;
+      PNG_PLTE;
+#if defined(PNG_READ_bKGD_SUPPORTED)
+      PNG_bKGD;
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+      PNG_cHRM;
+#endif
+#if defined(PNG_READ_gAMA_SUPPORTED)
+      PNG_gAMA;
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+      PNG_hIST;
+#endif
+#if defined(PNG_READ_iCCP_SUPPORTED)
+      PNG_iCCP;
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+      PNG_iTXt;
+#endif
+#if defined(PNG_READ_oFFs_SUPPORTED)
+      PNG_oFFs;
+#endif
+#if defined(PNG_READ_pCAL_SUPPORTED)
+      PNG_pCAL;
+#endif
+#if defined(PNG_READ_pHYs_SUPPORTED)
+      PNG_pHYs;
+#endif
+#if defined(PNG_READ_sBIT_SUPPORTED)
+      PNG_sBIT;
+#endif
+#if defined(PNG_READ_sCAL_SUPPORTED)
+      PNG_sCAL;
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      PNG_sRGB;
+#endif
+#if defined(PNG_READ_sPLT_SUPPORTED)
+      PNG_sPLT;
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      PNG_tEXt;
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+      PNG_tIME;
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+      PNG_tRNS;
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      PNG_zTXt;
+#endif
+#endif /* PNG_USE_LOCAL_ARRAYS */
+   /* First we make sure we have enough data for the 4 byte chunk name
+    * and the 4 byte chunk length before proceeding with decoding the
+    * chunk data.  To fully decode each of these chunks, we also make
+    * sure we have enough data in the buffer for the 4 byte CRC at the
+    * end of every chunk (except IDAT, which is handled separately).
+    */
+   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
+   {
+      png_byte chunk_length[4];
+
+      if (png_ptr->buffer_size < 8)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_push_fill_buffer(png_ptr, chunk_length, 4);
+      png_ptr->push_length = png_get_uint_32(chunk_length);
+      png_reset_crc(png_ptr);
+      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
+   }
+
+   if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
+   }
+   else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
+   }
+   else if (!png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
+   {
+      /* If we reach an IDAT chunk, this means we have read all of the
+       * header chunks, and we can start reading the image (or if this
+       * is called after the image has been read - we have an error).
+       */
+      if (png_ptr->mode & PNG_HAVE_IDAT)
+      {
+         if (png_ptr->push_length == 0)
+            return;
+
+         if (png_ptr->mode & PNG_AFTER_IDAT)
+            png_error(png_ptr, "Too many IDAT's found");
+      }
+
+      png_ptr->idat_size = png_ptr->push_length;
+      png_ptr->mode |= PNG_HAVE_IDAT;
+      png_ptr->process_mode = PNG_READ_IDAT_MODE;
+      png_push_have_info(png_ptr, info_ptr);
+      png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
+      png_ptr->zstream.next_out = png_ptr->row_buf;
+      return;
+   }
+   else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
+      png_ptr->process_mode = PNG_READ_DONE_MODE;
+      png_push_have_end(png_ptr, info_ptr);
+   }
+#if defined(PNG_READ_gAMA_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_sBIT_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_iCCP_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_sPLT_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_bKGD_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_pHYs_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_oFFs_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_pCAL_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_sCAL_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
+   {
+      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
+   {
+      png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
+   {
+      png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+   else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
+   {
+      png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
+   }
+#endif
+   else
+   {
+      png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+   }
+
+   png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+}
+
+void /* PRIVATE */
+png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
+{
+   png_ptr->process_mode = PNG_SKIP_MODE;
+   png_ptr->skip_length = skip;
+}
+
+void /* PRIVATE */
+png_push_crc_finish(png_structp png_ptr)
+{
+   if (png_ptr->skip_length && png_ptr->save_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size)
+         save_size = (png_size_t)png_ptr->skip_length;
+      else
+         save_size = png_ptr->save_buffer_size;
+
+      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
+
+      png_ptr->skip_length -= save_size;
+      png_ptr->buffer_size -= save_size;
+      png_ptr->save_buffer_size -= save_size;
+      png_ptr->save_buffer_ptr += save_size;
+   }
+   if (png_ptr->skip_length && png_ptr->current_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size)
+         save_size = (png_size_t)png_ptr->skip_length;
+      else
+         save_size = png_ptr->current_buffer_size;
+
+      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
+
+      png_ptr->skip_length -= save_size;
+      png_ptr->buffer_size -= save_size;
+      png_ptr->current_buffer_size -= save_size;
+      png_ptr->current_buffer_ptr += save_size;
+   }
+   if (!png_ptr->skip_length)
+   {
+      if (png_ptr->buffer_size < 4)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_crc_finish(png_ptr, 0);
+      png_ptr->process_mode = PNG_READ_CHUNK_MODE;
+   }
+}
+
+void /* PRIVATE */
+png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
+{
+   png_bytep ptr;
+
+   ptr = buffer;
+   if (png_ptr->save_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (length < png_ptr->save_buffer_size)
+         save_size = length;
+      else
+         save_size = png_ptr->save_buffer_size;
+
+      png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
+      length -= save_size;
+      ptr += save_size;
+      png_ptr->buffer_size -= save_size;
+      png_ptr->save_buffer_size -= save_size;
+      png_ptr->save_buffer_ptr += save_size;
+   }
+   if (length && png_ptr->current_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (length < png_ptr->current_buffer_size)
+         save_size = length;
+      else
+         save_size = png_ptr->current_buffer_size;
+
+      png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
+      png_ptr->buffer_size -= save_size;
+      png_ptr->current_buffer_size -= save_size;
+      png_ptr->current_buffer_ptr += save_size;
+   }
+}
+
+void /* PRIVATE */
+png_push_save_buffer(png_structp png_ptr)
+{
+   if (png_ptr->save_buffer_size)
+   {
+      if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
+      {
+         png_size_t i,istop;
+         png_bytep sp;
+         png_bytep dp;
+
+         istop = png_ptr->save_buffer_size;
+         for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
+            i < istop; i++, sp++, dp++)
+         {
+            *dp = *sp;
+         }
+      }
+   }
+   if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
+      png_ptr->save_buffer_max)
+   {
+      png_size_t new_max;
+      png_bytep old_buffer;
+
+      new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
+      old_buffer = png_ptr->save_buffer;
+      png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr,
+         (png_uint_32)new_max);
+      png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
+      png_free(png_ptr, old_buffer);
+      png_ptr->save_buffer_max = new_max;
+   }
+   if (png_ptr->current_buffer_size)
+   {
+      png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
+         png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
+      png_ptr->save_buffer_size += png_ptr->current_buffer_size;
+      png_ptr->current_buffer_size = 0;
+   }
+   png_ptr->save_buffer_ptr = png_ptr->save_buffer;
+   png_ptr->buffer_size = 0;
+}
+
+void /* PRIVATE */
+png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
+   png_size_t buffer_length)
+{
+   png_ptr->current_buffer = buffer;
+   png_ptr->current_buffer_size = buffer_length;
+   png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
+   png_ptr->current_buffer_ptr = png_ptr->current_buffer;
+}
+
+void /* PRIVATE */
+png_push_read_IDAT(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_IDAT;
+#endif
+   if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
+   {
+      png_byte chunk_length[4];
+
+      if (png_ptr->buffer_size < 8)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_push_fill_buffer(png_ptr, chunk_length, 4);
+      png_ptr->push_length = png_get_uint_32(chunk_length);
+
+      png_reset_crc(png_ptr);
+      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
+
+      if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
+      {
+         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
+         if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+            png_error(png_ptr, "Not enough compressed data");
+         return;
+      }
+
+      png_ptr->idat_size = png_ptr->push_length;
+   }
+   if (png_ptr->idat_size && png_ptr->save_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
+      {
+         save_size = (png_size_t)png_ptr->idat_size;
+         /* check for overflow */
+         if((png_uint_32)save_size != png_ptr->idat_size)
+            png_error(png_ptr, "save_size overflowed in pngpread");
+      }
+      else
+         save_size = png_ptr->save_buffer_size;
+
+      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
+      png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
+
+      png_ptr->idat_size -= save_size;
+      png_ptr->buffer_size -= save_size;
+      png_ptr->save_buffer_size -= save_size;
+      png_ptr->save_buffer_ptr += save_size;
+   }
+   if (png_ptr->idat_size && png_ptr->current_buffer_size)
+   {
+      png_size_t save_size;
+
+      if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
+      {
+         save_size = (png_size_t)png_ptr->idat_size;
+         /* check for overflow */
+         if((png_uint_32)save_size != png_ptr->idat_size)
+            png_error(png_ptr, "save_size overflowed in pngpread");
+      }
+      else
+         save_size = png_ptr->current_buffer_size;
+
+      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
+      png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
+
+      png_ptr->idat_size -= save_size;
+      png_ptr->buffer_size -= save_size;
+      png_ptr->current_buffer_size -= save_size;
+      png_ptr->current_buffer_ptr += save_size;
+   }
+   if (!png_ptr->idat_size)
+   {
+      if (png_ptr->buffer_size < 4)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_crc_finish(png_ptr, 0);
+      png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+   }
+}
+
+void /* PRIVATE */
+png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
+   png_size_t buffer_length)
+{
+   int ret;
+
+   if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
+      png_error(png_ptr, "Extra compression data");
+
+   png_ptr->zstream.next_in = buffer;
+   png_ptr->zstream.avail_in = (uInt)buffer_length;
+   for(;;)
+   {
+      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+      if (ret != Z_OK)
+      {
+         if (ret == Z_STREAM_END)
+         {
+            if (png_ptr->zstream.avail_in)
+               png_error(png_ptr, "Extra compressed data");
+            if (!(png_ptr->zstream.avail_out))
+            {
+               png_push_process_row(png_ptr);
+            }
+
+            png_ptr->mode |= PNG_AFTER_IDAT;
+            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+            break;
+         }
+         else if (ret == Z_BUF_ERROR)
+            break;
+         else
+            png_error(png_ptr, "Decompression Error");
+      }
+      if (!(png_ptr->zstream.avail_out))
+      {
+         png_push_process_row(png_ptr);
+         png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
+         png_ptr->zstream.next_out = png_ptr->row_buf;
+      }
+      else
+         break;
+   }
+}
+
+void /* PRIVATE */
+png_push_process_row(png_structp png_ptr)
+{
+   png_ptr->row_info.color_type = png_ptr->color_type;
+   png_ptr->row_info.width = png_ptr->iwidth;
+   png_ptr->row_info.channels = png_ptr->channels;
+   png_ptr->row_info.bit_depth = png_ptr->bit_depth;
+   png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
+
+   png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
+      (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
+
+   png_read_filter_row(png_ptr, &(png_ptr->row_info),
+      png_ptr->row_buf + 1, png_ptr->prev_row + 1,
+      (int)(png_ptr->row_buf[0]));
+
+   png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
+      png_ptr->rowbytes + 1);
+
+   if (png_ptr->transformations)
+      png_do_read_transformations(png_ptr);
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+   /* blow up interlaced rows to full size */
+   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+   {
+      if (png_ptr->pass < 6)
+/*       old interface (pre-1.0.9):
+         png_do_read_interlace(&(png_ptr->row_info),
+            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
+ */
+         png_do_read_interlace(png_ptr);
+
+    switch (png_ptr->pass)
+    {
+         case 0:
+         {
+            int i;
+            for (i = 0; i < 8 && png_ptr->pass == 0; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */
+            }
+            if (png_ptr->pass == 2) /* pass 1 might be empty */
+            {
+               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+               {
+                  png_push_have_row(png_ptr, NULL);
+                  png_read_push_finish_row(png_ptr);
+               }
+            }
+           if (png_ptr->pass == 4 && png_ptr->height <= 4)
+           {
+               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+                {
+                   png_push_have_row(png_ptr, NULL);
+                   png_read_push_finish_row(png_ptr);
+                }
+            }
+            if (png_ptr->pass == 6 && png_ptr->height <= 4)
+            {
+                png_push_have_row(png_ptr, NULL);
+                png_read_push_finish_row(png_ptr);
+            }
+            break;
+         }
+         case 1:
+         {
+            int i;
+            for (i = 0; i < 8 && png_ptr->pass == 1; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr);
+            }
+            if (png_ptr->pass == 2) /* skip top 4 generated rows */
+            {
+               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+               {
+                  png_push_have_row(png_ptr, NULL);
+                  png_read_push_finish_row(png_ptr);
+               }
+            }
+            break;
+         }
+         case 2:
+         {
+            int i;
+            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr);
+            }
+            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+            {
+               png_push_have_row(png_ptr, NULL);
+               png_read_push_finish_row(png_ptr);
+            }
+            if (png_ptr->pass == 4) /* pass 3 might be empty */
+            {
+               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+               {
+                  png_push_have_row(png_ptr, NULL);
+                  png_read_push_finish_row(png_ptr);
+               }
+            }
+            break;
+         }
+         case 3:
+         {
+            int i;
+            for (i = 0; i < 4 && png_ptr->pass == 3; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr);
+            }
+            if (png_ptr->pass == 4) /* skip top two generated rows */
+            {
+               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+               {
+                  png_push_have_row(png_ptr, NULL);
+                  png_read_push_finish_row(png_ptr);
+               }
+            }
+            break;
+         }
+         case 4:
+         {
+            int i;
+            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr);
+            }
+            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+            {
+               png_push_have_row(png_ptr, NULL);
+               png_read_push_finish_row(png_ptr);
+            }
+            if (png_ptr->pass == 6) /* pass 5 might be empty */
+            {
+               png_push_have_row(png_ptr, NULL);
+               png_read_push_finish_row(png_ptr);
+            }
+            break;
+         }
+         case 5:
+         {
+            int i;
+            for (i = 0; i < 2 && png_ptr->pass == 5; i++)
+            {
+               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+               png_read_push_finish_row(png_ptr);
+            }
+            if (png_ptr->pass == 6) /* skip top generated row */
+            {
+               png_push_have_row(png_ptr, NULL);
+               png_read_push_finish_row(png_ptr);
+            }
+            break;
+         }
+         case 6:
+         {
+            png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+            png_read_push_finish_row(png_ptr);
+            if (png_ptr->pass != 6)
+               break;
+            png_push_have_row(png_ptr, NULL);
+            png_read_push_finish_row(png_ptr);
+         }
+      }
+   }
+   else
+#endif
+   {
+      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+      png_read_push_finish_row(png_ptr);
+   }
+}
+
+void /* PRIVATE */
+png_read_push_finish_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+
+   /* start of interlace block in the y direction */
+   const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+
+   /* offset to next interlace block in the y direction */
+   const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+
+   /* Width of interlace block.  This is not currently used - if you need
+    * it, uncomment it here and in png.h
+   const int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
+   */
+
+   /* Height of interlace block.  This is not currently used - if you need
+    * it, uncomment it here and in png.h
+   const int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+   */
+#endif
+
+   png_ptr->row_number++;
+   if (png_ptr->row_number < png_ptr->num_rows)
+      return;
+
+   if (png_ptr->interlaced)
+   {
+      png_ptr->row_number = 0;
+      png_memset_check(png_ptr, png_ptr->prev_row, 0,
+         png_ptr->rowbytes + 1);
+      do
+      {
+         png_ptr->pass++;
+         if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
+             (png_ptr->pass == 3 && png_ptr->width < 3) ||
+             (png_ptr->pass == 5 && png_ptr->width < 2))
+           png_ptr->pass++;
+
+         if (png_ptr->pass >= 7)
+            break;
+
+         png_ptr->iwidth = (png_ptr->width +
+            png_pass_inc[png_ptr->pass] - 1 -
+            png_pass_start[png_ptr->pass]) /
+            png_pass_inc[png_ptr->pass];
+
+         png_ptr->irowbytes = ((png_ptr->iwidth *
+            png_ptr->pixel_depth + 7) >> 3) + 1;
+
+         if (png_ptr->transformations & PNG_INTERLACE)
+            break;
+
+         png_ptr->num_rows = (png_ptr->height +
+            png_pass_yinc[png_ptr->pass] - 1 -
+            png_pass_ystart[png_ptr->pass]) /
+            png_pass_yinc[png_ptr->pass];
+
+      } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
+   }
+}
+
+#if defined(PNG_READ_tEXt_SUPPORTED)
+void /* PRIVATE */
+png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
+   length)
+{
+   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
+      {
+         png_error(png_ptr, "Out of place tEXt");
+         /* to quiet some compiler warnings */
+         if(info_ptr == NULL) return;
+      }
+
+#ifdef PNG_MAX_MALLOC_64K
+   png_ptr->skip_length = 0;  /* This may not be necessary */
+
+   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
+   {
+      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
+      png_ptr->skip_length = length - (png_uint_32)65535L;
+      length = (png_uint_32)65535L;
+   }
+#endif
+
+   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
+         (png_uint_32)(length+1));
+   png_ptr->current_text[length] = '\0';
+   png_ptr->current_text_ptr = png_ptr->current_text;
+   png_ptr->current_text_size = (png_size_t)length;
+   png_ptr->current_text_left = (png_size_t)length;
+   png_ptr->process_mode = PNG_READ_tEXt_MODE;
+}
+
+void /* PRIVATE */
+png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr->buffer_size && png_ptr->current_text_left)
+   {
+      png_size_t text_size;
+
+      if (png_ptr->buffer_size < png_ptr->current_text_left)
+         text_size = png_ptr->buffer_size;
+      else
+         text_size = png_ptr->current_text_left;
+      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
+      png_ptr->current_text_left -= text_size;
+      png_ptr->current_text_ptr += text_size;
+   }
+   if (!(png_ptr->current_text_left))
+   {
+      png_textp text_ptr;
+      png_charp text;
+      png_charp key;
+
+      if (png_ptr->buffer_size < 4)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_push_crc_finish(png_ptr);
+
+#if defined(PNG_MAX_MALLOC_64K)
+      if (png_ptr->skip_length)
+         return;
+#endif
+
+      key = png_ptr->current_text;
+      png_ptr->current_text = 0;
+
+      for (text = key; *text; text++)
+         /* empty loop */ ;
+
+      if (text != key + png_ptr->current_text_size)
+         text++;
+
+      text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
+      text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
+      text_ptr->key = key;
+#ifdef PNG_iTXt_SUPPORTED
+      text_ptr->lang = (char *)NULL;
+      text_ptr->lang_key = (char *)NULL;
+#endif
+      text_ptr->text = text;
+
+      png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+      png_free(png_ptr, key);
+      png_free(png_ptr, text_ptr);
+   }
+}
+#endif
+
+#if defined(PNG_READ_zTXt_SUPPORTED)
+void /* PRIVATE */
+png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
+   length)
+{
+   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
+      {
+         png_error(png_ptr, "Out of place zTXt");
+         /* to quiet some compiler warnings */
+         if(info_ptr == NULL) return;
+      }
+
+#ifdef PNG_MAX_MALLOC_64K
+   /* We can't handle zTXt chunks > 64K, since we don't have enough space
+    * to be able to store the uncompressed data.  Actually, the threshold
+    * is probably around 32K, but it isn't as definite as 64K is.
+    */
+   if (length > (png_uint_32)65535L)
+   {
+      png_warning(png_ptr, "zTXt chunk too large to fit in memory");
+      png_push_crc_skip(png_ptr, length);
+      return;
+   }
+#endif
+
+   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
+       (png_uint_32)(length+1));
+   png_ptr->current_text[length] = '\0';
+   png_ptr->current_text_ptr = png_ptr->current_text;
+   png_ptr->current_text_size = (png_size_t)length;
+   png_ptr->current_text_left = (png_size_t)length;
+   png_ptr->process_mode = PNG_READ_zTXt_MODE;
+}
+
+void /* PRIVATE */
+png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr->buffer_size && png_ptr->current_text_left)
+   {
+      png_size_t text_size;
+
+      if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
+         text_size = png_ptr->buffer_size;
+      else
+         text_size = png_ptr->current_text_left;
+      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
+      png_ptr->current_text_left -= text_size;
+      png_ptr->current_text_ptr += text_size;
+   }
+   if (!(png_ptr->current_text_left))
+   {
+      png_textp text_ptr;
+      png_charp text;
+      png_charp key;
+      int ret;
+      png_size_t text_size, key_size;
+
+      if (png_ptr->buffer_size < 4)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_push_crc_finish(png_ptr);
+
+      key = png_ptr->current_text;
+      png_ptr->current_text = 0;
+
+      for (text = key; *text; text++)
+         /* empty loop */ ;
+
+      /* zTXt can't have zero text */
+      if (text == key + png_ptr->current_text_size)
+      {
+         png_free(png_ptr, key);
+         return;
+      }
+
+      text++;
+
+      if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */
+      {
+         png_free(png_ptr, key);
+         return;
+      }
+
+      text++;
+
+      png_ptr->zstream.next_in = (png_bytep )text;
+      png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
+         (text - key));
+      png_ptr->zstream.next_out = png_ptr->zbuf;
+      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+      key_size = text - key;
+      text_size = 0;
+      text = NULL;
+      ret = Z_STREAM_END;
+
+      while (png_ptr->zstream.avail_in)
+      {
+         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+         if (ret != Z_OK && ret != Z_STREAM_END)
+         {
+            inflateReset(&png_ptr->zstream);
+            png_ptr->zstream.avail_in = 0;
+            png_free(png_ptr, key);
+            png_free(png_ptr, text);
+            return;
+         }
+         if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
+         {
+            if (text == NULL)
+            {
+               text = (png_charp)png_malloc(png_ptr,
+                  (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out
+                     + key_size + 1));
+               png_memcpy(text + key_size, png_ptr->zbuf,
+                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
+               png_memcpy(text, key, key_size);
+               text_size = key_size + png_ptr->zbuf_size -
+                  png_ptr->zstream.avail_out;
+               *(text + text_size) = '\0';
+            }
+            else
+            {
+               png_charp tmp;
+
+               tmp = text;
+               text = (png_charp)png_malloc(png_ptr, text_size +
+                  (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out
+                   + 1));
+               png_memcpy(text, tmp, text_size);
+               png_free(png_ptr, tmp);
+               png_memcpy(text + text_size, png_ptr->zbuf,
+                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
+               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
+               *(text + text_size) = '\0';
+            }
+            if (ret != Z_STREAM_END)
+            {
+               png_ptr->zstream.next_out = png_ptr->zbuf;
+               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+            }
+         }
+         else
+         {
+            break;
+         }
+
+         if (ret == Z_STREAM_END)
+            break;
+      }
+
+      inflateReset(&png_ptr->zstream);
+      png_ptr->zstream.avail_in = 0;
+
+      if (ret != Z_STREAM_END)
+      {
+         png_free(png_ptr, key);
+         png_free(png_ptr, text);
+         return;
+      }
+
+      png_free(png_ptr, key);
+      key = text;
+      text += key_size;
+
+      text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
+      text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
+      text_ptr->key = key;
+#ifdef PNG_iTXt_SUPPORTED
+      text_ptr->lang = (char *)NULL;
+      text_ptr->lang_key = (char *)NULL;
+#endif
+      text_ptr->text = text;
+
+      png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+      png_free(png_ptr, key);
+      png_free(png_ptr, text_ptr);
+   }
+}
+#endif
+
+#if defined(PNG_READ_iTXt_SUPPORTED)
+void /* PRIVATE */
+png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
+   length)
+{
+   if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
+      {
+         png_error(png_ptr, "Out of place iTXt");
+         /* to quiet some compiler warnings */
+         if(info_ptr == NULL) return;
+      }
+
+#ifdef PNG_MAX_MALLOC_64K
+   png_ptr->skip_length = 0;  /* This may not be necessary */
+
+   if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
+   {
+      png_warning(png_ptr, "iTXt chunk too large to fit in memory");
+      png_ptr->skip_length = length - (png_uint_32)65535L;
+      length = (png_uint_32)65535L;
+   }
+#endif
+
+   png_ptr->current_text = (png_charp)png_malloc(png_ptr,
+         (png_uint_32)(length+1));
+   png_ptr->current_text[length] = '\0';
+   png_ptr->current_text_ptr = png_ptr->current_text;
+   png_ptr->current_text_size = (png_size_t)length;
+   png_ptr->current_text_left = (png_size_t)length;
+   png_ptr->process_mode = PNG_READ_iTXt_MODE;
+}
+
+void /* PRIVATE */
+png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
+{
+
+   if (png_ptr->buffer_size && png_ptr->current_text_left)
+   {
+      png_size_t text_size;
+
+      if (png_ptr->buffer_size < png_ptr->current_text_left)
+         text_size = png_ptr->buffer_size;
+      else
+         text_size = png_ptr->current_text_left;
+      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
+      png_ptr->current_text_left -= text_size;
+      png_ptr->current_text_ptr += text_size;
+   }
+   if (!(png_ptr->current_text_left))
+   {
+      png_textp text_ptr;
+      png_charp key;
+      int comp_flag;
+      png_charp lang;
+      png_charp lang_key;
+      png_charp text;
+
+      if (png_ptr->buffer_size < 4)
+      {
+         png_push_save_buffer(png_ptr);
+         return;
+      }
+
+      png_push_crc_finish(png_ptr);
+
+#if defined(PNG_MAX_MALLOC_64K)
+      if (png_ptr->skip_length)
+         return;
+#endif
+
+      key = png_ptr->current_text;
+      png_ptr->current_text = 0;
+
+      for (lang = key; *lang; lang++)
+         /* empty loop */ ;
+
+      if (lang != key + png_ptr->current_text_size)
+         lang++;
+
+      comp_flag = *lang++;
+      lang++;     /* skip comp_type, always zero */
+
+      for (lang_key = lang; *lang_key; lang_key++)
+         /* empty loop */ ;
+      lang_key++;        /* skip NUL separator */
+
+      for (text = lang_key; *text; text++)
+         /* empty loop */ ;
+
+      if (text != key + png_ptr->current_text_size)
+         text++;
+
+      text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
+      text_ptr->compression = comp_flag + 2;
+      text_ptr->key = key;
+      text_ptr->lang = lang;
+      text_ptr->lang_key = lang_key;
+      text_ptr->text = text;
+      text_ptr->text_length = 0;
+      text_ptr->itxt_length = png_strlen(text);
+
+      png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+      png_free(png_ptr, text_ptr);
+   }
+}
+#endif
+
+/* This function is called when we haven't found a handler for this
+ * chunk.  If there isn't a problem with the chunk itself (ie a bad chunk
+ * name or a critical chunk), the chunk is (currently) silently ignored.
+ */
+void /* PRIVATE */
+png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32
+   length)
+{
+   png_uint_32 skip=0;
+   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+
+   if (!(png_ptr->chunk_name[0] & 0x20))
+   {
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+      if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+           HANDLE_CHUNK_ALWAYS
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+           && png_ptr->read_user_chunk_fn == NULL
+#endif
+         )
+#endif
+         png_chunk_error(png_ptr, "unknown critical chunk");
+
+      /* to quiet compiler warnings about unused info_ptr */
+      if (info_ptr == NULL)
+         return;
+   }
+
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+   if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
+   {
+       png_unknown_chunk chunk;
+
+#ifdef PNG_MAX_MALLOC_64K
+       if (length > (png_uint_32)65535L)
+       {
+           png_warning(png_ptr, "unknown chunk too large to fit in memory");
+           skip = length - (png_uint_32)65535L;
+           length = (png_uint_32)65535L;
+       }
+#endif
+
+       png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
+       chunk.data = (png_bytep)png_malloc(png_ptr, length);
+       png_crc_read(png_ptr, chunk.data, length);
+       chunk.size = length;
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+       if(png_ptr->read_user_chunk_fn != NULL)
+       {
+          /* callback to user unknown chunk handler */
+          if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
+          {
+             if (!(png_ptr->chunk_name[0] & 0x20))
+                if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+                     HANDLE_CHUNK_ALWAYS)
+                   png_chunk_error(png_ptr, "unknown critical chunk");
+          }
+             png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
+       }
+       else
+#endif
+          png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
+       png_free(png_ptr, chunk.data);
+   }
+   else
+#endif
+      skip=length;
+   png_push_crc_skip(png_ptr, skip);
+}
+
+void /* PRIVATE */
+png_push_have_info(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr->info_fn != NULL)
+      (*(png_ptr->info_fn))(png_ptr, info_ptr);
+}
+
+void /* PRIVATE */
+png_push_have_end(png_structp png_ptr, png_infop info_ptr)
+{
+   if (png_ptr->end_fn != NULL)
+      (*(png_ptr->end_fn))(png_ptr, info_ptr);
+}
+
+void /* PRIVATE */
+png_push_have_row(png_structp png_ptr, png_bytep row)
+{
+   if (png_ptr->row_fn != NULL)
+      (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
+         (int)png_ptr->pass);
+}
+
+void PNGAPI
+png_progressive_combine_row (png_structp png_ptr,
+   png_bytep old_row, png_bytep new_row)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   const int FARDATA png_pass_dsp_mask[7] =
+      {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
+#endif
+   if (new_row != NULL)    /* new_row must == png_ptr->row_buf here. */
+      png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
+}
+
+void PNGAPI
+png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
+   png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
+   png_progressive_end_ptr end_fn)
+{
+   png_ptr->info_fn = info_fn;
+   png_ptr->row_fn = row_fn;
+   png_ptr->end_fn = end_fn;
+
+   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
+}
+
+png_voidp PNGAPI
+png_get_progressive_ptr(png_structp png_ptr)
+{
+   return png_ptr->io_ptr;
+}
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
diff --git a/libraries/libpng-1.2.0/pngread.c b/libraries/libpng-1.2.0/pngread.c
new file mode 100644 (file)
index 0000000..cec672a
--- /dev/null
@@ -0,0 +1,1400 @@
+
+/* pngread.c - read a PNG file
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file contains routines that an application calls directly to
+ * read a PNG file or stream.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+/* Create a PNG structure for reading, and allocate any memory needed. */
+png_structp PNGAPI
+png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn)
+{
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
+      warn_fn, NULL, NULL, NULL));
+}
+
+/* Alternate create PNG structure for reading, and allocate any memory needed. */
+png_structp PNGAPI
+png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+   png_structp png_ptr;
+
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+   jmp_buf jmpbuf;
+#endif
+#endif
+
+   int i;
+
+   png_debug(1, "in png_create_read_struct\n");
+#ifdef PNG_USER_MEM_SUPPORTED
+   if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
+      (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr)) == NULL)
+#else
+   if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
+#endif
+   {
+      return (png_structp)NULL;
+   }
+
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+   png_init_mmx_flags(png_ptr);   /* 1.2.0 addition */
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+   if (setjmp(jmpbuf))
+#else
+   if (setjmp(png_ptr->jmpbuf))
+#endif
+   {
+      png_free(png_ptr, png_ptr->zbuf);
+      png_ptr->zbuf=NULL;
+      png_destroy_struct(png_ptr);
+      return (png_structp)NULL;
+   }
+#ifdef USE_FAR_KEYWORD
+   png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
+#endif
+#endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
+#endif
+
+   png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
+
+   i=0;
+   do
+   {
+     if(user_png_ver[i] != png_libpng_ver[i])
+        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+   } while (png_libpng_ver[i++]);
+
+   if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+   {
+     /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
+      * we must recompile any applications that use any older library version.
+      * For versions after libpng 1.0, we will be compatible, so we need
+      * only check the first digit.
+      */
+     if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
+         (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
+         (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
+     {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+        char msg[80];
+        if (user_png_ver)
+        {
+          sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
+             user_png_ver);
+          png_warning(png_ptr, msg);
+        }
+        sprintf(msg, "Application  is running with png.c from libpng-%.20s",
+           png_libpng_ver);
+        png_warning(png_ptr, msg);
+#endif
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+        png_ptr->flags=0;
+#endif
+        png_error(png_ptr,
+           "Incompatible libpng version in application and library");
+     }
+   }
+
+   /* initialize zbuf - compression buffer */
+   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+     (png_uint_32)png_ptr->zbuf_size);
+   png_ptr->zstream.zalloc = png_zalloc;
+   png_ptr->zstream.zfree = png_zfree;
+   png_ptr->zstream.opaque = (voidpf)png_ptr;
+
+   switch (inflateInit(&png_ptr->zstream))
+   {
+     case Z_OK: /* Do nothing */ break;
+     case Z_MEM_ERROR:
+     case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
+     case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break;
+     default: png_error(png_ptr, "Unknown zlib error");
+   }
+
+   png_ptr->zstream.next_out = png_ptr->zbuf;
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+   png_set_read_fn(png_ptr, NULL, NULL);
+
+   return (png_ptr);
+}
+
+/* Initialize PNG structure for reading, and allocate any memory needed.
+   This interface is deprecated in favour of the png_create_read_struct(),
+   and it will eventually disappear. */
+#undef png_read_init
+void PNGAPI
+png_read_init(png_structp png_ptr)
+{
+   /* We only come here via pre-1.0.7-compiled applications */
+   png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0);
+}
+
+#undef png_read_init_2
+void PNGAPI
+png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver,
+   png_size_t png_struct_size, png_size_t png_info_size)
+{
+   /* We only come here via pre-1.0.12-compiled applications */
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+   if(sizeof(png_struct) > png_struct_size || sizeof(png_info) > png_info_size)
+   {
+      char msg[80];
+      png_ptr->warning_fn=(png_error_ptr)NULL;
+      if (user_png_ver)
+      {
+        sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
+           user_png_ver);
+        png_warning(png_ptr, msg);
+      }
+      sprintf(msg, "Application  is running with png.c from libpng-%.20s",
+         png_libpng_ver);
+      png_warning(png_ptr, msg);
+   }
+#endif
+   if(sizeof(png_struct) > png_struct_size)
+     {
+       png_ptr->error_fn=(png_error_ptr)NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+       png_ptr->flags=0;
+#endif
+       png_error(png_ptr,
+       "The png struct allocated by the application for reading is too small.");
+     }
+   if(sizeof(png_info) > png_info_size)
+     {
+       png_ptr->error_fn=(png_error_ptr)NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+       png_ptr->flags=0;
+#endif
+       png_error(png_ptr,
+         "The info struct allocated by application for reading is too small.");
+     }
+   png_read_init_3(&png_ptr, user_png_ver, png_struct_size);
+}
+
+void PNGAPI
+png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
+   png_size_t png_struct_size)
+{
+#ifdef PNG_SETJMP_SUPPORTED
+   jmp_buf tmp_jmp;  /* to save current jump buffer */
+#endif
+
+   int i=0;
+
+   png_structp png_ptr=*ptr_ptr;
+
+   do
+   {
+     if(user_png_ver[i] != png_libpng_ver[i])
+     {
+#ifdef PNG_LEGACY_SUPPORTED
+       png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+#else
+       png_ptr->warning_fn=(png_error_ptr)NULL;
+       png_warning(png_ptr,
+        "Application uses deprecated png_read_init() and should be recompiled.");
+       break;
+#endif
+     }
+   } while (png_libpng_ver[i++]);
+
+   png_debug(1, "in png_read_init_3\n");
+
+#ifdef PNG_SETJMP_SUPPORTED
+   /* save jump buffer and error functions */
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
+#endif
+
+   if(sizeof(png_struct) > png_struct_size)
+     {
+       png_destroy_struct(png_ptr);
+       *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
+       png_ptr = *ptr_ptr;
+     }
+
+   /* reset all variables to 0 */
+   png_memset(png_ptr, 0, sizeof (png_struct));
+
+#ifdef PNG_SETJMP_SUPPORTED
+   /* restore jump buffer */
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
+#endif
+
+   /* initialize zbuf - compression buffer */
+   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+     (png_uint_32)png_ptr->zbuf_size);
+   png_ptr->zstream.zalloc = png_zalloc;
+   png_ptr->zstream.zfree = png_zfree;
+   png_ptr->zstream.opaque = (voidpf)png_ptr;
+
+   switch (inflateInit(&png_ptr->zstream))
+   {
+     case Z_OK: /* Do nothing */ break;
+     case Z_MEM_ERROR:
+     case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break;
+     case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break;
+     default: png_error(png_ptr, "Unknown zlib error");
+   }
+
+   png_ptr->zstream.next_out = png_ptr->zbuf;
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+   png_set_read_fn(png_ptr, NULL, NULL);
+}
+
+/* Read the information before the actual image data.  This has been
+ * changed in v0.90 to allow reading a file that already has the magic
+ * bytes read from the stream.  You can tell libpng how many bytes have
+ * been read from the beginning of the stream (up to the maximum of 8)
+ * via png_set_sig_bytes(), and we will only check the remaining bytes
+ * here.  The application can then have access to the signature bytes we
+ * read if it is determined that this isn't a valid PNG file.
+ */
+void PNGAPI
+png_read_info(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_read_info\n");
+   /* save jump buffer and error functions */
+   /* If we haven't checked all of the PNG signature bytes, do so now. */
+   if (png_ptr->sig_bytes < 8)
+   {
+      png_size_t num_checked = png_ptr->sig_bytes,
+                 num_to_check = 8 - num_checked;
+
+      png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
+      png_ptr->sig_bytes = 8;
+
+      if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
+      {
+         if (num_checked < 4 &&
+             png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
+            png_error(png_ptr, "Not a PNG file");
+         else
+            png_error(png_ptr, "PNG file corrupted by ASCII conversion");
+      }
+      if (num_checked < 3)
+         png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
+   }
+
+   for(;;)
+   {
+#ifdef PNG_USE_LOCAL_ARRAYS
+      PNG_IHDR;
+      PNG_IDAT;
+      PNG_IEND;
+      PNG_PLTE;
+#if defined(PNG_READ_bKGD_SUPPORTED)
+      PNG_bKGD;
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+      PNG_cHRM;
+#endif
+#if defined(PNG_READ_gAMA_SUPPORTED)
+      PNG_gAMA;
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+      PNG_hIST;
+#endif
+#if defined(PNG_READ_iCCP_SUPPORTED)
+      PNG_iCCP;
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+      PNG_iTXt;
+#endif
+#if defined(PNG_READ_oFFs_SUPPORTED)
+      PNG_oFFs;
+#endif
+#if defined(PNG_READ_pCAL_SUPPORTED)
+      PNG_pCAL;
+#endif
+#if defined(PNG_READ_pHYs_SUPPORTED)
+      PNG_pHYs;
+#endif
+#if defined(PNG_READ_sBIT_SUPPORTED)
+      PNG_sBIT;
+#endif
+#if defined(PNG_READ_sCAL_SUPPORTED)
+      PNG_sCAL;
+#endif
+#if defined(PNG_READ_sPLT_SUPPORTED)
+      PNG_sPLT;
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      PNG_sRGB;
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      PNG_tEXt;
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+      PNG_tIME;
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+      PNG_tRNS;
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      PNG_zTXt;
+#endif
+#endif /* PNG_GLOBAL_ARRAYS */
+      png_byte chunk_length[4];
+      png_uint_32 length;
+
+      png_read_data(png_ptr, chunk_length, 4);
+      length = png_get_uint_32(chunk_length);
+
+      png_reset_crc(png_ptr);
+      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+
+      png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name,
+         length);
+
+      /* This should be a binary subdivision search or a hash for
+       * matching the chunk name rather than a linear search.
+       */
+      if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
+         png_handle_IHDR(png_ptr, info_ptr, length);
+      else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
+         png_handle_IEND(png_ptr, info_ptr, length);
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+      else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
+      {
+         if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+            png_ptr->mode |= PNG_HAVE_IDAT;
+         png_handle_unknown(png_ptr, info_ptr, length);
+         if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+            png_ptr->mode |= PNG_HAVE_PLTE;
+         else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+         {
+            if (!(png_ptr->mode & PNG_HAVE_IHDR))
+               png_error(png_ptr, "Missing IHDR before IDAT");
+            else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+                     !(png_ptr->mode & PNG_HAVE_PLTE))
+               png_error(png_ptr, "Missing PLTE before IDAT");
+            break;
+         }
+      }
+#endif
+      else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+         png_handle_PLTE(png_ptr, info_ptr, length);
+      else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+      {
+         if (!(png_ptr->mode & PNG_HAVE_IHDR))
+            png_error(png_ptr, "Missing IHDR before IDAT");
+         else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+                  !(png_ptr->mode & PNG_HAVE_PLTE))
+            png_error(png_ptr, "Missing PLTE before IDAT");
+
+         png_ptr->idat_size = length;
+         png_ptr->mode |= PNG_HAVE_IDAT;
+         break;
+      }
+#if defined(PNG_READ_bKGD_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
+         png_handle_bKGD(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
+         png_handle_cHRM(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_gAMA_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
+         png_handle_gAMA(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
+         png_handle_hIST(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_oFFs_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
+         png_handle_oFFs(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_pCAL_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
+         png_handle_pCAL(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sCAL_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
+         png_handle_sCAL(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_pHYs_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
+         png_handle_pHYs(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sBIT_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
+         png_handle_sBIT(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
+         png_handle_sRGB(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_iCCP_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
+         png_handle_iCCP(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sPLT_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
+         png_handle_sPLT(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
+         png_handle_tEXt(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
+         png_handle_tIME(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
+         png_handle_tRNS(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
+         png_handle_zTXt(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
+         png_handle_iTXt(png_ptr, info_ptr, length);
+#endif
+      else
+         png_handle_unknown(png_ptr, info_ptr, length);
+   }
+}
+
+/* optional call to update the users info_ptr structure */
+void PNGAPI
+png_read_update_info(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_read_update_info\n");
+   /* save jump buffer and error functions */
+   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+      png_read_start_row(png_ptr);
+   else
+      png_warning(png_ptr,
+      "Ignoring extra png_read_update_info() call; row buffer not reallocated");
+   png_read_transform_info(png_ptr, info_ptr);
+}
+
+/* Initialize palette, background, etc, after transformations
+ * are set, but before any reading takes place.  This allows
+ * the user to obtain a gamma-corrected palette, for example.
+ * If the user doesn't call this, we will do it ourselves.
+ */
+void PNGAPI
+png_start_read_image(png_structp png_ptr)
+{
+   png_debug(1, "in png_start_read_image\n");
+   /* save jump buffer and error functions */
+   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+      png_read_start_row(png_ptr);
+}
+
+void PNGAPI
+png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_IDAT;
+   const int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
+   const int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
+#endif
+   int ret;
+   png_debug2(1, "in png_read_row (row %lu, pass %d)\n",
+      png_ptr->row_number, png_ptr->pass);
+   /* save jump buffer and error functions */
+   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+      png_read_start_row(png_ptr);
+   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
+   {
+   /* check for transforms that have been set but were defined out */
+#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_MONO)
+      png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
+   if (png_ptr->transformations & PNG_FILLER)
+      png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACKSWAP)
+      png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACK)
+      png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
+   if (png_ptr->transformations & PNG_SHIFT)
+      png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
+   if (png_ptr->transformations & PNG_BGR)
+      png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined.");
+#endif
+   }
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+   /* if interlaced and we do not need a new row, combine row and return */
+   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+   {
+      switch (png_ptr->pass)
+      {
+         case 0:
+            if (png_ptr->row_number & 0x07)
+            {
+               if (dsp_row != NULL)
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 1:
+            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
+            {
+               if (dsp_row != NULL)
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 2:
+            if ((png_ptr->row_number & 0x07) != 4)
+            {
+               if (dsp_row != NULL && (png_ptr->row_number & 4))
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 3:
+            if ((png_ptr->row_number & 3) || png_ptr->width < 3)
+            {
+               if (dsp_row != NULL)
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 4:
+            if ((png_ptr->row_number & 3) != 2)
+            {
+               if (dsp_row != NULL && (png_ptr->row_number & 2))
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 5:
+            if ((png_ptr->row_number & 1) || png_ptr->width < 2)
+            {
+               if (dsp_row != NULL)
+                  png_combine_row(png_ptr, dsp_row,
+                     png_pass_dsp_mask[png_ptr->pass]);
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 6:
+            if (!(png_ptr->row_number & 1))
+            {
+               png_read_finish_row(png_ptr);
+               return;
+            }
+            break;
+      }
+   }
+#endif
+
+   if (!(png_ptr->mode & PNG_HAVE_IDAT))
+      png_error(png_ptr, "Invalid attempt to read row data");
+
+   png_ptr->zstream.next_out = png_ptr->row_buf;
+   png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
+   do
+   {
+      if (!(png_ptr->zstream.avail_in))
+      {
+         while (!png_ptr->idat_size)
+         {
+            png_byte chunk_length[4];
+
+            png_crc_finish(png_ptr, 0);
+
+            png_read_data(png_ptr, chunk_length, 4);
+            png_ptr->idat_size = png_get_uint_32(chunk_length);
+
+            png_reset_crc(png_ptr);
+            png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+            if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+               png_error(png_ptr, "Not enough image data");
+         }
+         png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
+         png_ptr->zstream.next_in = png_ptr->zbuf;
+         if (png_ptr->zbuf_size > png_ptr->idat_size)
+            png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
+         png_crc_read(png_ptr, png_ptr->zbuf,
+            (png_size_t)png_ptr->zstream.avail_in);
+         png_ptr->idat_size -= png_ptr->zstream.avail_in;
+      }
+      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+      if (ret == Z_STREAM_END)
+      {
+         if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
+            png_ptr->idat_size)
+            png_error(png_ptr, "Extra compressed data");
+         png_ptr->mode |= PNG_AFTER_IDAT;
+         png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+         break;
+      }
+      if (ret != Z_OK)
+         png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
+                   "Decompression error");
+
+   } while (png_ptr->zstream.avail_out);
+
+   png_ptr->row_info.color_type = png_ptr->color_type;
+   png_ptr->row_info.width = png_ptr->iwidth;
+   png_ptr->row_info.channels = png_ptr->channels;
+   png_ptr->row_info.bit_depth = png_ptr->bit_depth;
+   png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
+   png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
+      (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
+
+   if(png_ptr->row_buf[0])
+   png_read_filter_row(png_ptr, &(png_ptr->row_info),
+      png_ptr->row_buf + 1, png_ptr->prev_row + 1,
+      (int)(png_ptr->row_buf[0]));
+
+   png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
+      png_ptr->rowbytes + 1);
+   
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+      (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
+   {
+      /* Intrapixel differencing */
+      png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
+   }
+#endif
+
+   if (png_ptr->transformations)
+      png_do_read_transformations(png_ptr);
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+   /* blow up interlaced rows to full size */
+   if (png_ptr->interlaced &&
+      (png_ptr->transformations & PNG_INTERLACE))
+   {
+      if (png_ptr->pass < 6)
+/*       old interface (pre-1.0.9):
+         png_do_read_interlace(&(png_ptr->row_info),
+            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
+ */
+         png_do_read_interlace(png_ptr);
+
+      if (dsp_row != NULL)
+         png_combine_row(png_ptr, dsp_row,
+            png_pass_dsp_mask[png_ptr->pass]);
+      if (row != NULL)
+         png_combine_row(png_ptr, row,
+            png_pass_mask[png_ptr->pass]);
+   }
+   else
+#endif
+   {
+      if (row != NULL)
+         png_combine_row(png_ptr, row, 0xff);
+      if (dsp_row != NULL)
+         png_combine_row(png_ptr, dsp_row, 0xff);
+   }
+   png_read_finish_row(png_ptr);
+
+   if (png_ptr->read_row_fn != NULL)
+      (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
+}
+
+/* Read one or more rows of image data.  If the image is interlaced,
+ * and png_set_interlace_handling() has been called, the rows need to
+ * contain the contents of the rows from the previous pass.  If the
+ * image has alpha or transparency, and png_handle_alpha()[*] has been
+ * called, the rows contents must be initialized to the contents of the
+ * screen.
+ *
+ * "row" holds the actual image, and pixels are placed in it
+ * as they arrive.  If the image is displayed after each pass, it will
+ * appear to "sparkle" in.  "display_row" can be used to display a
+ * "chunky" progressive image, with finer detail added as it becomes
+ * available.  If you do not want this "chunky" display, you may pass
+ * NULL for display_row.  If you do not want the sparkle display, and
+ * you have not called png_handle_alpha(), you may pass NULL for rows.
+ * If you have called png_handle_alpha(), and the image has either an
+ * alpha channel or a transparency chunk, you must provide a buffer for
+ * rows.  In this case, you do not have to provide a display_row buffer
+ * also, but you may.  If the image is not interlaced, or if you have
+ * not called png_set_interlace_handling(), the display_row buffer will
+ * be ignored, so pass NULL to it.
+ *
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.2.0
+ */
+
+void PNGAPI
+png_read_rows(png_structp png_ptr, png_bytepp row,
+   png_bytepp display_row, png_uint_32 num_rows)
+{
+   png_uint_32 i;
+   png_bytepp rp;
+   png_bytepp dp;
+
+   png_debug(1, "in png_read_rows\n");
+   /* save jump buffer and error functions */
+   rp = row;
+   dp = display_row;
+   if (rp != NULL && dp != NULL)
+      for (i = 0; i < num_rows; i++)
+      {
+         png_bytep rptr = *rp++;
+         png_bytep dptr = *dp++;
+
+         png_read_row(png_ptr, rptr, dptr);
+      }
+   else if(rp != NULL)
+      for (i = 0; i < num_rows; i++)
+      {
+         png_bytep rptr = *rp;
+         png_read_row(png_ptr, rptr, NULL);
+         rp++;
+      }
+   else if(dp != NULL)
+      for (i = 0; i < num_rows; i++)
+      {
+         png_bytep dptr = *dp;
+         png_read_row(png_ptr, NULL, dptr);
+         dp++;
+      }
+}
+
+/* Read the entire image.  If the image has an alpha channel or a tRNS
+ * chunk, and you have called png_handle_alpha()[*], you will need to
+ * initialize the image to the current image that PNG will be overlaying.
+ * We set the num_rows again here, in case it was incorrectly set in
+ * png_read_start_row() by a call to png_read_update_info() or
+ * png_start_read_image() if png_set_interlace_handling() wasn't called
+ * prior to either of these functions like it should have been.  You can
+ * only call this function once.  If you desire to have an image for
+ * each pass of a interlaced image, use png_read_rows() instead.
+ *
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.2.0
+ */
+void PNGAPI
+png_read_image(png_structp png_ptr, png_bytepp image)
+{
+   png_uint_32 i,image_height;
+   int pass, j;
+   png_bytepp rp;
+
+   png_debug(1, "in png_read_image\n");
+   /* save jump buffer and error functions */
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+   pass = png_set_interlace_handling(png_ptr);
+#else
+   if (png_ptr->interlaced)
+      png_error(png_ptr,
+        "Cannot read interlaced image -- interlace handler disabled.");
+   pass = 1;
+#endif
+
+
+   image_height=png_ptr->height;
+   png_ptr->num_rows = image_height; /* Make sure this is set correctly */
+
+   for (j = 0; j < pass; j++)
+   {
+      rp = image;
+      for (i = 0; i < image_height; i++)
+      {
+         png_read_row(png_ptr, *rp, NULL);
+         rp++;
+      }
+   }
+}
+
+/* Read the end of the PNG file.  Will not read past the end of the
+ * file, will verify the end is accurate, and will read any comments
+ * or time information at the end of the file, if info is not NULL.
+ */
+void PNGAPI
+png_read_end(png_structp png_ptr, png_infop info_ptr)
+{
+   png_byte chunk_length[4];
+   png_uint_32 length;
+
+   png_debug(1, "in png_read_end\n");
+   /* save jump buffer and error functions */
+   png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
+
+   do
+   {
+#ifdef PNG_USE_LOCAL_ARRAYS
+      PNG_IHDR;
+      PNG_IDAT;
+      PNG_IEND;
+      PNG_PLTE;
+#if defined(PNG_READ_bKGD_SUPPORTED)
+      PNG_bKGD;
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+      PNG_cHRM;
+#endif
+#if defined(PNG_READ_gAMA_SUPPORTED)
+      PNG_gAMA;
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+      PNG_hIST;
+#endif
+#if defined(PNG_READ_iCCP_SUPPORTED)
+      PNG_iCCP;
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+      PNG_iTXt;
+#endif
+#if defined(PNG_READ_oFFs_SUPPORTED)
+      PNG_oFFs;
+#endif
+#if defined(PNG_READ_pCAL_SUPPORTED)
+      PNG_pCAL;
+#endif
+#if defined(PNG_READ_pHYs_SUPPORTED)
+      PNG_pHYs;
+#endif
+#if defined(PNG_READ_sBIT_SUPPORTED)
+      PNG_sBIT;
+#endif
+#if defined(PNG_READ_sCAL_SUPPORTED)
+      PNG_sCAL;
+#endif
+#if defined(PNG_READ_sPLT_SUPPORTED)
+      PNG_sPLT;
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      PNG_sRGB;
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      PNG_tEXt;
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+      PNG_tIME;
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+      PNG_tRNS;
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      PNG_zTXt;
+#endif
+#endif /* PNG_GLOBAL_ARRAYS */
+
+      png_read_data(png_ptr, chunk_length, 4);
+      length = png_get_uint_32(chunk_length);
+
+      png_reset_crc(png_ptr);
+      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+
+      png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
+
+      if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
+         png_handle_IHDR(png_ptr, info_ptr, length);
+      else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
+         png_handle_IEND(png_ptr, info_ptr, length);
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+      else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
+      {
+         if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+         {
+            if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
+               png_error(png_ptr, "Too many IDAT's found");
+         }
+         else
+            png_ptr->mode |= PNG_AFTER_IDAT;
+         png_handle_unknown(png_ptr, info_ptr, length);
+         if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+            png_ptr->mode |= PNG_HAVE_PLTE;
+      }
+#endif
+      else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+      {
+         /* Zero length IDATs are legal after the last IDAT has been
+          * read, but not after other chunks have been read.
+          */
+         if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
+            png_error(png_ptr, "Too many IDAT's found");
+         png_crc_finish(png_ptr, length);
+      }
+      else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+         png_handle_PLTE(png_ptr, info_ptr, length);
+#if defined(PNG_READ_bKGD_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
+         png_handle_bKGD(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_cHRM_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
+         png_handle_cHRM(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_gAMA_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
+         png_handle_gAMA(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
+         png_handle_hIST(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_oFFs_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
+         png_handle_oFFs(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_pCAL_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
+         png_handle_pCAL(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sCAL_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
+         png_handle_sCAL(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_pHYs_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
+         png_handle_pHYs(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sBIT_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
+         png_handle_sBIT(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
+         png_handle_sRGB(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_iCCP_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
+         png_handle_iCCP(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_sPLT_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
+         png_handle_sPLT(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tEXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
+         png_handle_tEXt(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tIME_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
+         png_handle_tIME(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_tRNS_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
+         png_handle_tRNS(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_zTXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
+         png_handle_zTXt(png_ptr, info_ptr, length);
+#endif
+#if defined(PNG_READ_iTXt_SUPPORTED)
+      else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
+         png_handle_iTXt(png_ptr, info_ptr, length);
+#endif
+      else
+         png_handle_unknown(png_ptr, info_ptr, length);
+   } while (!(png_ptr->mode & PNG_HAVE_IEND));
+}
+
+/* free all memory used by the read */
+void PNGAPI
+png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
+   png_infopp end_info_ptr_ptr)
+{
+   png_structp png_ptr = NULL;
+   png_infop info_ptr = NULL, end_info_ptr = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn = NULL;
+   png_voidp mem_ptr = NULL;
+#endif
+
+   png_debug(1, "in png_destroy_read_struct\n");
+   /* save jump buffer and error functions */
+   if (png_ptr_ptr != NULL)
+      png_ptr = *png_ptr_ptr;
+
+   if (info_ptr_ptr != NULL)
+      info_ptr = *info_ptr_ptr;
+
+   if (end_info_ptr_ptr != NULL)
+      end_info_ptr = *end_info_ptr_ptr;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   free_fn = png_ptr->free_fn;
+   mem_ptr = png_ptr->mem_ptr;
+#endif
+
+   png_read_destroy(png_ptr, info_ptr, end_info_ptr);
+
+   if (info_ptr != NULL)
+   {
+#if defined(PNG_TEXT_SUPPORTED)
+      png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
+#endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
+          (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)info_ptr);
+#endif
+      *info_ptr_ptr = (png_infop)NULL;
+   }
+
+   if (end_info_ptr != NULL)
+   {
+#if defined(PNG_READ_TEXT_SUPPORTED)
+      png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
+#endif
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn,
+         (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)end_info_ptr);
+#endif
+      *end_info_ptr_ptr = (png_infop)NULL;
+   }
+
+   if (png_ptr != NULL)
+   {
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
+          (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)png_ptr);
+#endif
+      *png_ptr_ptr = (png_structp)NULL;
+   }
+}
+
+/* free all memory used by the read (old method) */
+void /* PRIVATE */
+png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)
+{
+#ifdef PNG_SETJMP_SUPPORTED
+   jmp_buf tmp_jmp;
+#endif
+   png_error_ptr error_fn;
+   png_error_ptr warning_fn;
+   png_voidp error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn;
+#endif
+
+   png_debug(1, "in png_read_destroy\n");
+   /* save jump buffer and error functions */
+   if (info_ptr != NULL)
+      png_info_destroy(png_ptr, info_ptr);
+
+   if (end_info_ptr != NULL)
+      png_info_destroy(png_ptr, end_info_ptr);
+
+   png_free(png_ptr, png_ptr->zbuf);
+   png_free(png_ptr, png_ptr->big_row_buf);
+   png_free(png_ptr, png_ptr->prev_row);
+#if defined(PNG_READ_DITHER_SUPPORTED)
+   png_free(png_ptr, png_ptr->palette_lookup);
+   png_free(png_ptr, png_ptr->dither_index);
+#endif
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   png_free(png_ptr, png_ptr->gamma_table);
+#endif
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   png_free(png_ptr, png_ptr->gamma_from_1);
+   png_free(png_ptr, png_ptr->gamma_to_1);
+#endif
+#ifdef PNG_FREE_ME_SUPPORTED
+   if (png_ptr->free_me & PNG_FREE_PLTE)
+      png_zfree(png_ptr, png_ptr->palette);
+   png_ptr->free_me &= ~PNG_FREE_PLTE;
+#else
+   if (png_ptr->flags & PNG_FLAG_FREE_PLTE)
+      png_zfree(png_ptr, png_ptr->palette);
+   png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;
+#endif
+#if defined(PNG_tRNS_SUPPORTED) || \
+    defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_FREE_ME_SUPPORTED
+   if (png_ptr->free_me & PNG_FREE_TRNS)
+      png_free(png_ptr, png_ptr->trans);
+   png_ptr->free_me &= ~PNG_FREE_TRNS;
+#else
+   if (png_ptr->flags & PNG_FLAG_FREE_TRNS)
+      png_free(png_ptr, png_ptr->trans);
+   png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
+#endif
+#endif
+#if defined(PNG_READ_hIST_SUPPORTED)
+#ifdef PNG_FREE_ME_SUPPORTED
+   if (png_ptr->free_me & PNG_FREE_HIST)
+      png_free(png_ptr, png_ptr->hist);
+   png_ptr->free_me &= ~PNG_FREE_HIST;
+#else
+   if (png_ptr->flags & PNG_FLAG_FREE_HIST)
+      png_free(png_ptr, png_ptr->hist);
+   png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
+#endif
+#endif
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   if (png_ptr->gamma_16_table != NULL)
+   {
+      int i;
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
+      {
+         png_free(png_ptr, png_ptr->gamma_16_table[i]);
+      }
+   png_free(png_ptr, png_ptr->gamma_16_table);
+   }
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if (png_ptr->gamma_16_from_1 != NULL)
+   {
+      int i;
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
+      {
+         png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
+      }
+   png_free(png_ptr, png_ptr->gamma_16_from_1);
+   }
+   if (png_ptr->gamma_16_to_1 != NULL)
+   {
+      int i;
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
+      {
+         png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
+      }
+   png_free(png_ptr, png_ptr->gamma_16_to_1);
+   }
+#endif
+#endif
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+   png_free(png_ptr, png_ptr->time_buffer);
+#endif
+
+   inflateEnd(&png_ptr->zstream);
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+   png_free(png_ptr, png_ptr->save_buffer);
+#endif
+
+   /* Save the important info out of the png_struct, in case it is
+    * being used again.
+    */
+#ifdef PNG_SETJMP_SUPPORTED
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
+#endif
+
+   error_fn = png_ptr->error_fn;
+   warning_fn = png_ptr->warning_fn;
+   error_ptr = png_ptr->error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   free_fn = png_ptr->free_fn;
+#endif
+
+   png_memset(png_ptr, 0, sizeof (png_struct));
+
+   png_ptr->error_fn = error_fn;
+   png_ptr->warning_fn = warning_fn;
+   png_ptr->error_ptr = error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_ptr->free_fn = free_fn;
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
+#endif
+
+}
+
+void PNGAPI
+png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
+{
+   png_ptr->read_row_fn = read_row_fn;
+}
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+void PNGAPI
+png_read_png(png_structp png_ptr, png_infop info_ptr,
+                           int transforms,
+                           voidp params)
+{
+   int row;
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+   /* invert the alpha channel from opacity to transparency */
+   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+       png_set_invert_alpha(png_ptr);
+#endif
+
+   /* The call to png_read_info() gives us all of the information from the
+    * PNG file before the first IDAT (image data chunk).
+    */
+   png_read_info(png_ptr, info_ptr);
+
+   /* -------------- image transformations start here ------------------- */
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+   /* tell libpng to strip 16 bit/color files down to 8 bits/color */
+   if (transforms & PNG_TRANSFORM_STRIP_16)
+       png_set_strip_16(png_ptr);
+#endif
+
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+   /* Strip alpha bytes from the input data without combining with the
+    * background (not recommended).
+    */
+   if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
+       png_set_strip_alpha(png_ptr);
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
+   /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
+    * byte into separate bytes (useful for paletted and grayscale images).
+    */
+   if (transforms & PNG_TRANSFORM_PACKING)
+       png_set_packing(png_ptr);
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+   /* Change the order of packed pixels to least significant bit first
+    * (not useful if you are using png_set_packing). */
+   if (transforms & PNG_TRANSFORM_PACKSWAP)
+       png_set_packswap(png_ptr);
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+   /* Expand paletted colors into true RGB triplets
+    * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
+    * Expand paletted or RGB images with transparency to full alpha
+    * channels so the data will be available as RGBA quartets.
+    */
+   if (transforms & PNG_TRANSFORM_EXPAND)
+       if ((png_ptr->bit_depth < 8) ||
+           (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
+           (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
+         png_set_expand(png_ptr);
+#endif
+
+   /* We don't handle background color or gamma transformation or dithering. */
+
+#if defined(PNG_READ_INVERT_SUPPORTED)
+   /* invert monochrome files to have 0 as white and 1 as black */
+   if (transforms & PNG_TRANSFORM_INVERT_MONO)
+       png_set_invert_mono(png_ptr);
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED)
+   /* If you want to shift the pixel values from the range [0,255] or
+    * [0,65535] to the original [0,7] or [0,31], or whatever range the
+    * colors were originally in:
+    */
+   if ((transforms & PNG_TRANSFORM_SHIFT)
+       && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
+   {
+      png_color_8p sig_bit;
+
+      png_get_sBIT(png_ptr, info_ptr, &sig_bit);
+      png_set_shift(png_ptr, sig_bit);
+   }
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED)
+   /* flip the RGB pixels to BGR (or RGBA to BGRA) */
+   if (transforms & PNG_TRANSFORM_BGR)
+       png_set_bgr(png_ptr);
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+   /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
+   if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+       png_set_swap_alpha(png_ptr);
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED)
+   /* swap bytes of 16 bit files to least significant byte first */
+   if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+       png_set_swap(png_ptr);
+#endif
+
+   /* We don't handle adding filler bytes */
+
+   /* Optional call to gamma correct and add the background to the palette
+    * and update info structure.  REQUIRED if you are expecting libpng to
+    * update the palette for you (i.e., you selected such a transform above).
+    */
+   png_read_update_info(png_ptr, info_ptr);
+
+   /* -------------- image transformations end here ------------------- */
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
+#endif
+   if(info_ptr->row_pointers == NULL)
+   {
+      info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
+         info_ptr->height * sizeof(png_bytep));
+#ifdef PNG_FREE_ME_SUPPORTED
+      info_ptr->free_me |= PNG_FREE_ROWS;
+#endif
+      for (row = 0; row < (int)info_ptr->height; row++)
+      {
+         info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
+            png_get_rowbytes(png_ptr, info_ptr));
+      }
+   }
+
+   png_read_image(png_ptr, info_ptr->row_pointers);
+   info_ptr->valid |= PNG_INFO_IDAT;
+
+   /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
+   png_read_end(png_ptr, info_ptr);
+
+   if(transforms == 0 || params == NULL)
+      /* quiet compiler warnings */ return;
+
+}
+#endif
diff --git a/libraries/libpng-1.2.0/pngrio.c b/libraries/libpng-1.2.0/pngrio.c
new file mode 100644 (file)
index 0000000..97fcdaa
--- /dev/null
@@ -0,0 +1,161 @@
+
+/* pngrio.c - functions for data input
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file provides a location for all input.  Users who need
+ * special handling are expected to write a function that has the same
+ * arguments as this and performs a similar function, but that possibly
+ * has a different input method.  Note that you shouldn't change this
+ * function, but rather write a replacement function and then make
+ * libpng use it at run time with png_set_read_fn(...).
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+/* Read the data from whatever input you are using.  The default routine
+   reads from a file pointer.  Note that this routine sometimes gets called
+   with very small lengths, so you should implement some kind of simple
+   buffering if you are using unbuffered reads.  This should never be asked
+   to read more then 64K on a 16 bit machine. */
+void /* PRIVATE */
+png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_debug1(4,"reading %d bytes\n", (int)length);
+   if (png_ptr->read_data_fn != NULL)
+      (*(png_ptr->read_data_fn))(png_ptr, data, length);
+   else
+      png_error(png_ptr, "Call to NULL read function");
+}
+
+#if !defined(PNG_NO_STDIO)
+/* This is the function that does the actual reading of data.  If you are
+   not reading from a standard C stream, you should create a replacement
+   read_data function and use it at run time with png_set_read_fn(), rather
+   than changing the library. */
+#ifndef USE_FAR_KEYWORD
+static void /* PRIVATE */
+png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_size_t check;
+
+   /* fread() returns 0 on error, so it is OK to store this in a png_size_t
+    * instead of an int, which is what fread() actually returns.
+    */
+#if defined(_WIN32_WCE)
+   if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
+      check = 0;
+#else
+   check = (png_size_t)fread(data, (png_size_t)1, length,
+      (png_FILE_p)png_ptr->io_ptr);
+#endif
+
+   if (check != length)
+      png_error(png_ptr, "Read Error");
+}
+#else
+/* this is the model-independent version. Since the standard I/O library
+   can't handle far buffers in the medium and small models, we have to copy
+   the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void /* PRIVATE */
+png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   int check;
+   png_byte *n_data;
+   png_FILE_p io_ptr;
+
+   /* Check if data really is near. If so, use usual code. */
+   n_data = (png_byte *)CVT_PTR_NOCHECK(data);
+   io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+   if ((png_bytep)n_data == data)
+   {
+#if defined(_WIN32_WCE)
+      if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
+         check = 0;
+#else
+      check = fread(n_data, 1, length, io_ptr);
+#endif
+   }
+   else
+   {
+      png_byte buf[NEAR_BUF_SIZE];
+      png_size_t read, remaining, err;
+      check = 0;
+      remaining = length;
+      do
+      {
+         read = MIN(NEAR_BUF_SIZE, remaining);
+#if defined(_WIN32_WCE)
+         if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) )
+            err = 0;
+#else
+         err = fread(buf, (png_size_t)1, read, io_ptr);
+#endif
+         png_memcpy(data, buf, read); /* copy far buffer to near buffer */
+         if(err != read)
+            break;
+         else
+            check += err;
+         data += read;
+         remaining -= read;
+      }
+      while (remaining != 0);
+   }
+   if ((png_uint_32)check != (png_uint_32)length)
+      png_error(png_ptr, "read Error");
+}
+#endif
+#endif
+
+/* This function allows the application to supply a new input function
+   for libpng if standard C streams aren't being used.
+
+   This function takes as its arguments:
+   png_ptr      - pointer to a png input data structure
+   io_ptr       - pointer to user supplied structure containing info about
+                  the input functions.  May be NULL.
+   read_data_fn - pointer to a new input function that takes as its
+                  arguments a pointer to a png_struct, a pointer to
+                  a location where input data can be stored, and a 32-bit
+                  unsigned int that is the number of bytes to be read.
+                  To exit and output any fatal error messages the new write
+                  function should call png_error(png_ptr, "Error msg"). */
+void PNGAPI
+png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
+   png_rw_ptr read_data_fn)
+{
+   png_ptr->io_ptr = io_ptr;
+
+#if !defined(PNG_NO_STDIO)
+   if (read_data_fn != NULL)
+      png_ptr->read_data_fn = read_data_fn;
+   else
+      png_ptr->read_data_fn = png_default_read_data;
+#else
+   png_ptr->read_data_fn = read_data_fn;
+#endif
+
+   /* It is an error to write to a read device */
+   if (png_ptr->write_data_fn != NULL)
+   {
+      png_ptr->write_data_fn = NULL;
+      png_warning(png_ptr,
+         "It's an error to set both read_data_fn and write_data_fn in the ");
+      png_warning(png_ptr,
+         "same structure.  Resetting write_data_fn to NULL.");
+   }
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+   png_ptr->output_flush_fn = NULL;
+#endif
+}
diff --git a/libraries/libpng-1.2.0/pngrtran.c b/libraries/libpng-1.2.0/pngrtran.c
new file mode 100644 (file)
index 0000000..e045c94
--- /dev/null
@@ -0,0 +1,4115 @@
+
+/* pngrtran.c - transforms the data in a row for PNG readers
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file contains functions optionally called by an application
+ * in order to tell libpng how to handle data when reading a PNG.
+ * Transformations that are used in both reading and writing are
+ * in pngtrans.c.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+/* Set the action on getting a CRC error for an ancillary or critical chunk. */
+void PNGAPI
+png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
+{
+   png_debug(1, "in png_set_crc_action\n");
+   /* Tell libpng how we react to CRC errors in critical chunks */
+   switch (crit_action)
+   {
+      case PNG_CRC_NO_CHANGE:                        /* leave setting as is */
+         break;
+      case PNG_CRC_WARN_USE:                               /* warn/use data */
+         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
+         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
+         break;
+      case PNG_CRC_QUIET_USE:                             /* quiet/use data */
+         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
+         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
+                           PNG_FLAG_CRC_CRITICAL_IGNORE;
+         break;
+      case PNG_CRC_WARN_DISCARD:    /* not a valid action for critical data */
+         png_warning(png_ptr, "Can't discard critical data on CRC error.");
+      case PNG_CRC_ERROR_QUIT:                                /* error/quit */
+      case PNG_CRC_DEFAULT:
+      default:
+         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
+         break;
+   }
+
+   switch (ancil_action)
+   {
+      case PNG_CRC_NO_CHANGE:                       /* leave setting as is */
+         break;
+      case PNG_CRC_WARN_USE:                              /* warn/use data */
+         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
+         break;
+      case PNG_CRC_QUIET_USE:                            /* quiet/use data */
+         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
+                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
+         break;
+      case PNG_CRC_ERROR_QUIT:                               /* error/quit */
+         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
+         break;
+      case PNG_CRC_WARN_DISCARD:                      /* warn/discard data */
+      case PNG_CRC_DEFAULT:
+      default:
+         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+         break;
+   }
+}
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
+    defined(PNG_FLOATING_POINT_SUPPORTED)
+/* handle alpha and tRNS via a background color */
+void PNGAPI
+png_set_background(png_structp png_ptr,
+   png_color_16p background_color, int background_gamma_code,
+   int need_expand, double background_gamma)
+{
+   png_debug(1, "in png_set_background\n");
+   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
+   {
+      png_warning(png_ptr, "Application must supply a known background gamma");
+      return;
+   }
+
+   png_ptr->transformations |= PNG_BACKGROUND;
+   png_memcpy(&(png_ptr->background), background_color, sizeof(png_color_16));
+   png_ptr->background_gamma = (float)background_gamma;
+   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
+   png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
+
+   /* Note:  if need_expand is set and color_type is either RGB or RGB_ALPHA
+    * (in which case need_expand is superfluous anyway), the background color
+    * might actually be gray yet not be flagged as such. This is not a problem
+    * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to
+    * decide when to do the png_do_gray_to_rgb() transformation.
+    */
+   if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
+       (!need_expand && background_color->red == background_color->green &&
+        background_color->red == background_color->blue))
+      png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
+}
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+/* strip 16 bit depth files to 8 bit depth */
+void PNGAPI
+png_set_strip_16(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_strip_16\n");
+   png_ptr->transformations |= PNG_16_TO_8;
+}
+#endif
+
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+void PNGAPI
+png_set_strip_alpha(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_strip_alpha\n");
+   png_ptr->transformations |= PNG_STRIP_ALPHA;
+}
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+/* Dither file to 8 bit.  Supply a palette, the current number
+ * of elements in the palette, the maximum number of elements
+ * allowed, and a histogram if possible.  If the current number
+ * of colors is greater then the maximum number, the palette will be
+ * modified to fit in the maximum number.  "full_dither" indicates
+ * whether we need a dithering cube set up for RGB images, or if we
+ * simply are reducing the number of colors in a paletted image.
+ */
+
+typedef struct png_dsort_struct
+{
+   struct png_dsort_struct FAR * next;
+   png_byte left;
+   png_byte right;
+} png_dsort;
+typedef png_dsort FAR *       png_dsortp;
+typedef png_dsort FAR * FAR * png_dsortpp;
+
+void PNGAPI
+png_set_dither(png_structp png_ptr, png_colorp palette,
+   int num_palette, int maximum_colors, png_uint_16p histogram,
+   int full_dither)
+{
+   png_debug(1, "in png_set_dither\n");
+   png_ptr->transformations |= PNG_DITHER;
+
+   if (!full_dither)
+   {
+      int i;
+
+      png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
+         (png_uint_32)(num_palette * sizeof (png_byte)));
+      for (i = 0; i < num_palette; i++)
+         png_ptr->dither_index[i] = (png_byte)i;
+   }
+
+   if (num_palette > maximum_colors)
+   {
+      if (histogram != NULL)
+      {
+         /* This is easy enough, just throw out the least used colors.
+            Perhaps not the best solution, but good enough. */
+
+         int i;
+         png_bytep sort;
+
+         /* initialize an array to sort colors */
+         sort = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_palette
+            * sizeof (png_byte)));
+
+         /* initialize the sort array */
+         for (i = 0; i < num_palette; i++)
+            sort[i] = (png_byte)i;
+
+         /* Find the least used palette entries by starting a
+            bubble sort, and running it until we have sorted
+            out enough colors.  Note that we don't care about
+            sorting all the colors, just finding which are
+            least used. */
+
+         for (i = num_palette - 1; i >= maximum_colors; i--)
+         {
+            int done; /* to stop early if the list is pre-sorted */
+            int j;
+
+            done = 1;
+            for (j = 0; j < i; j++)
+            {
+               if (histogram[sort[j]] < histogram[sort[j + 1]])
+               {
+                  png_byte t;
+
+                  t = sort[j];
+                  sort[j] = sort[j + 1];
+                  sort[j + 1] = t;
+                  done = 0;
+               }
+            }
+            if (done)
+               break;
+         }
+
+         /* swap the palette around, and set up a table, if necessary */
+         if (full_dither)
+         {
+            int j = num_palette;
+
+            /* put all the useful colors within the max, but don't
+               move the others */
+            for (i = 0; i < maximum_colors; i++)
+            {
+               if ((int)sort[i] >= maximum_colors)
+               {
+                  do
+                     j--;
+                  while ((int)sort[j] >= maximum_colors);
+                  palette[i] = palette[j];
+               }
+            }
+         }
+         else
+         {
+            int j = num_palette;
+
+            /* move all the used colors inside the max limit, and
+               develop a translation table */
+            for (i = 0; i < maximum_colors; i++)
+            {
+               /* only move the colors we need to */
+               if ((int)sort[i] >= maximum_colors)
+               {
+                  png_color tmp_color;
+
+                  do
+                     j--;
+                  while ((int)sort[j] >= maximum_colors);
+
+                  tmp_color = palette[j];
+                  palette[j] = palette[i];
+                  palette[i] = tmp_color;
+                  /* indicate where the color went */
+                  png_ptr->dither_index[j] = (png_byte)i;
+                  png_ptr->dither_index[i] = (png_byte)j;
+               }
+            }
+
+            /* find closest color for those colors we are not using */
+            for (i = 0; i < num_palette; i++)
+            {
+               if ((int)png_ptr->dither_index[i] >= maximum_colors)
+               {
+                  int min_d, k, min_k, d_index;
+
+                  /* find the closest color to one we threw out */
+                  d_index = png_ptr->dither_index[i];
+                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
+                  for (k = 1, min_k = 0; k < maximum_colors; k++)
+                  {
+                     int d;
+
+                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
+
+                     if (d < min_d)
+                     {
+                        min_d = d;
+                        min_k = k;
+                     }
+                  }
+                  /* point to closest color */
+                  png_ptr->dither_index[i] = (png_byte)min_k;
+               }
+            }
+         }
+         png_free(png_ptr, sort);
+      }
+      else
+      {
+         /* This is much harder to do simply (and quickly).  Perhaps
+            we need to go through a median cut routine, but those
+            don't always behave themselves with only a few colors
+            as input.  So we will just find the closest two colors,
+            and throw out one of them (chosen somewhat randomly).
+            [We don't understand this at all, so if someone wants to
+             work on improving it, be our guest - AED, GRP]
+            */
+         int i;
+         int max_d;
+         int num_new_palette;
+         png_dsortpp hash;
+         png_bytep index_to_palette;
+            /* where the original index currently is in the palette */
+         png_bytep palette_to_index;
+            /* which original index points to this palette color */
+
+         /* initialize palette index arrays */
+         index_to_palette = (png_bytep)png_malloc(png_ptr,
+            (png_uint_32)(num_palette * sizeof (png_byte)));
+         palette_to_index = (png_bytep)png_malloc(png_ptr,
+            (png_uint_32)(num_palette * sizeof (png_byte)));
+
+         /* initialize the sort array */
+         for (i = 0; i < num_palette; i++)
+         {
+            index_to_palette[i] = (png_byte)i;
+            palette_to_index[i] = (png_byte)i;
+         }
+
+         hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
+            sizeof (png_dsortp)));
+         for (i = 0; i < 769; i++)
+            hash[i] = NULL;
+/*         png_memset(hash, 0, 769 * sizeof (png_dsortp)); */
+
+         num_new_palette = num_palette;
+
+         /* initial wild guess at how far apart the farthest pixel
+            pair we will be eliminating will be.  Larger
+            numbers mean more areas will be allocated, Smaller
+            numbers run the risk of not saving enough data, and
+            having to do this all over again.
+
+            I have not done extensive checking on this number.
+            */
+         max_d = 96;
+
+         while (num_new_palette > maximum_colors)
+         {
+            for (i = 0; i < num_new_palette - 1; i++)
+            {
+               int j;
+
+               for (j = i + 1; j < num_new_palette; j++)
+               {
+                  int d;
+
+                  d = PNG_COLOR_DIST(palette[i], palette[j]);
+
+                  if (d <= max_d)
+                  {
+                     png_dsortp t;
+
+                     t = (png_dsortp)png_malloc(png_ptr, (png_uint_32)(sizeof
+                         (png_dsort)));
+                     t->next = hash[d];
+                     t->left = (png_byte)i;
+                     t->right = (png_byte)j;
+                     hash[d] = t;
+                  }
+               }
+            }
+
+            for (i = 0; i <= max_d; i++)
+            {
+               if (hash[i] != NULL)
+               {
+                  png_dsortp p;
+
+                  for (p = hash[i]; p; p = p->next)
+                  {
+                     if ((int)index_to_palette[p->left] < num_new_palette &&
+                        (int)index_to_palette[p->right] < num_new_palette)
+                     {
+                        int j, next_j;
+
+                        if (num_new_palette & 0x01)
+                        {
+                           j = p->left;
+                           next_j = p->right;
+                        }
+                        else
+                        {
+                           j = p->right;
+                           next_j = p->left;
+                        }
+
+                        num_new_palette--;
+                        palette[index_to_palette[j]] = palette[num_new_palette];
+                        if (!full_dither)
+                        {
+                           int k;
+
+                           for (k = 0; k < num_palette; k++)
+                           {
+                              if (png_ptr->dither_index[k] ==
+                                 index_to_palette[j])
+                                 png_ptr->dither_index[k] =
+                                    index_to_palette[next_j];
+                              if ((int)png_ptr->dither_index[k] ==
+                                 num_new_palette)
+                                 png_ptr->dither_index[k] =
+                                    index_to_palette[j];
+                           }
+                        }
+
+                        index_to_palette[palette_to_index[num_new_palette]] =
+                           index_to_palette[j];
+                        palette_to_index[index_to_palette[j]] =
+                           palette_to_index[num_new_palette];
+
+                        index_to_palette[j] = (png_byte)num_new_palette;
+                        palette_to_index[num_new_palette] = (png_byte)j;
+                     }
+                     if (num_new_palette <= maximum_colors)
+                        break;
+                  }
+                  if (num_new_palette <= maximum_colors)
+                     break;
+               }
+            }
+
+            for (i = 0; i < 769; i++)
+            {
+               if (hash[i] != NULL)
+               {
+                  png_dsortp p = hash[i];
+                  while (p)
+                  {
+                     png_dsortp t;
+
+                     t = p->next;
+                     png_free(png_ptr, p);
+                     p = t;
+                  }
+               }
+               hash[i] = 0;
+            }
+            max_d += 96;
+         }
+         png_free(png_ptr, hash);
+         png_free(png_ptr, palette_to_index);
+         png_free(png_ptr, index_to_palette);
+      }
+      num_palette = maximum_colors;
+   }
+   if (png_ptr->palette == NULL)
+   {
+      png_ptr->palette = palette;
+   }
+   png_ptr->num_palette = (png_uint_16)num_palette;
+
+   if (full_dither)
+   {
+      int i;
+      png_bytep distance;
+      int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
+         PNG_DITHER_BLUE_BITS;
+      int num_red = (1 << PNG_DITHER_RED_BITS);
+      int num_green = (1 << PNG_DITHER_GREEN_BITS);
+      int num_blue = (1 << PNG_DITHER_BLUE_BITS);
+      png_size_t num_entries = ((png_size_t)1 << total_bits);
+
+      png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
+         (png_uint_32)(num_entries * sizeof (png_byte)));
+
+      png_memset(png_ptr->palette_lookup, 0, num_entries * sizeof (png_byte));
+
+      distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
+         sizeof(png_byte)));
+
+      png_memset(distance, 0xff, num_entries * sizeof(png_byte));
+
+      for (i = 0; i < num_palette; i++)
+      {
+         int ir, ig, ib;
+         int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
+         int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
+         int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
+
+         for (ir = 0; ir < num_red; ir++)
+         {
+            int dr = abs(ir - r);
+            int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
+
+            for (ig = 0; ig < num_green; ig++)
+            {
+               int dg = abs(ig - g);
+               int dt = dr + dg;
+               int dm = ((dr > dg) ? dr : dg);
+               int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
+
+               for (ib = 0; ib < num_blue; ib++)
+               {
+                  int d_index = index_g | ib;
+                  int db = abs(ib - b);
+                  int dmax = ((dm > db) ? dm : db);
+                  int d = dmax + dt + db;
+
+                  if (d < (int)distance[d_index])
+                  {
+                     distance[d_index] = (png_byte)d;
+                     png_ptr->palette_lookup[d_index] = (png_byte)i;
+                  }
+               }
+            }
+         }
+      }
+
+      png_free(png_ptr, distance);
+   }
+}
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+/* Transform the image from the file_gamma to the screen_gamma.  We
+ * only do transformations on images where the file_gamma and screen_gamma
+ * are not close reciprocals, otherwise it slows things down slightly, and
+ * also needlessly introduces small errors.
+ */
+void PNGAPI
+png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
+{
+   png_debug(1, "in png_set_gamma\n");
+   if (fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD)
+      png_ptr->transformations |= PNG_GAMMA;
+   png_ptr->gamma = (float)file_gamma;
+   png_ptr->screen_gamma = (float)scrn_gamma;
+}
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+/* Expand paletted images to RGB, expand grayscale images of
+ * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
+ * to alpha channels.
+ */
+void PNGAPI
+png_set_expand(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_expand\n");
+   png_ptr->transformations |= PNG_EXPAND;
+}
+
+/* GRR 19990627:  the following three functions currently are identical
+ *  to png_set_expand().  However, it is entirely reasonable that someone
+ *  might wish to expand an indexed image to RGB but *not* expand a single,
+ *  fully transparent palette entry to a full alpha channel--perhaps instead
+ *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
+ *  the transparent color with a particular RGB value, or drop tRNS entirely.
+ *  IOW, a future version of the library may make the transformations flag
+ *  a bit more fine-grained, with separate bits for each of these three
+ *  functions.
+ *
+ *  More to the point, these functions make it obvious what libpng will be
+ *  doing, whereas "expand" can (and does) mean any number of things.
+ */
+
+/* Expand paletted images to RGB. */
+void PNGAPI
+png_set_palette_to_rgb(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_expand\n");
+   png_ptr->transformations |= PNG_EXPAND;
+}
+
+/* Expand grayscale images of less than 8-bit depth to 8 bits. */
+void PNGAPI
+png_set_gray_1_2_4_to_8(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_expand\n");
+   png_ptr->transformations |= PNG_EXPAND;
+}
+
+/* Expand tRNS chunks to alpha channels. */
+void PNGAPI
+png_set_tRNS_to_alpha(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_expand\n");
+   png_ptr->transformations |= PNG_EXPAND;
+}
+#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+void PNGAPI
+png_set_gray_to_rgb(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_gray_to_rgb\n");
+   png_ptr->transformations |= PNG_GRAY_TO_RGB;
+}
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+#if defined(PNG_FLOATING_POINT_SUPPORTED)
+/* Convert a RGB image to a grayscale of the same width.  This allows us,
+ * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
+ */
+
+void PNGAPI
+png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
+   double green)
+{
+      int red_fixed = (int)((float)red*100000.0 + 0.5);
+      int green_fixed = (int)((float)green*100000.0 + 0.5);
+      png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
+}
+#endif
+
+void PNGAPI
+png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
+   png_fixed_point red, png_fixed_point green)
+{
+   png_debug(1, "in png_set_rgb_to_gray\n");
+   switch(error_action)
+   {
+      case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
+              break;
+      case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
+              break;
+      case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
+   }
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+      png_ptr->transformations |= PNG_EXPAND;
+#else
+   {
+      png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
+      png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
+   }
+#endif
+   {
+      png_uint_16 red_int, green_int;
+      if(red < 0 || green < 0)
+      {
+         red_int   =  6968; /* .212671 * 32768 + .5 */
+         green_int = 23434; /* .715160 * 32768 + .5 */
+      }
+      else if(red + green < 100000L)
+      {
+        red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
+        green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
+      }
+      else
+      {
+         png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
+         red_int   =  6968;
+         green_int = 23434;
+      }
+      png_ptr->rgb_to_gray_red_coeff   = red_int;
+      png_ptr->rgb_to_gray_green_coeff = green_int;
+      png_ptr->rgb_to_gray_blue_coeff  = (png_uint_16)(32768-red_int-green_int);
+   }
+}
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+void PNGAPI
+png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+   read_user_transform_fn)
+{
+   png_debug(1, "in png_set_read_user_transform_fn\n");
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   png_ptr->transformations |= PNG_USER_TRANSFORM;
+   png_ptr->read_user_transform_fn = read_user_transform_fn;
+#endif
+#ifdef PNG_LEGACY_SUPPORTED
+   if(read_user_transform_fn)
+      png_warning(png_ptr,
+        "This version of libpng does not support user transforms");
+#endif
+}
+#endif
+
+/* Initialize everything needed for the read.  This includes modifying
+ * the palette.
+ */
+void /* PRIVATE */
+png_init_read_transformations(png_structp png_ptr)
+{
+   png_debug(1, "in png_init_read_transformations\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if(png_ptr != NULL)
+#endif
+  {
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
+ || defined(PNG_READ_GAMMA_SUPPORTED)
+   int color_type = png_ptr->color_type;
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
+       (png_ptr->transformations & PNG_EXPAND))
+   {
+      if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
+      {
+         /* expand background chunk. */
+         switch (png_ptr->bit_depth)
+         {
+            case 1:
+               png_ptr->background.gray *= (png_uint_16)0xff;
+               png_ptr->background.red = png_ptr->background.green =
+               png_ptr->background.blue = png_ptr->background.gray;
+               break;
+            case 2:
+               png_ptr->background.gray *= (png_uint_16)0x55;
+               png_ptr->background.red = png_ptr->background.green =
+               png_ptr->background.blue = png_ptr->background.gray;
+               break;
+            case 4:
+               png_ptr->background.gray *= (png_uint_16)0x11;
+               png_ptr->background.red = png_ptr->background.green =
+               png_ptr->background.blue = png_ptr->background.gray;
+               break;
+            case 8:
+            case 16:
+               png_ptr->background.red = png_ptr->background.green =
+               png_ptr->background.blue = png_ptr->background.gray;
+               break;
+         }
+      }
+      else if (color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         png_ptr->background.red   =
+            png_ptr->palette[png_ptr->background.index].red;
+         png_ptr->background.green =
+            png_ptr->palette[png_ptr->background.index].green;
+         png_ptr->background.blue  =
+            png_ptr->palette[png_ptr->background.index].blue;
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+        if (png_ptr->transformations & PNG_INVERT_ALPHA)
+        {
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+           if (!(png_ptr->transformations & PNG_EXPAND))
+#endif
+           {
+           /* invert the alpha channel (in tRNS) unless the pixels are
+              going to be expanded, in which case leave it for later */
+              int i,istop;
+              istop=(int)png_ptr->num_trans;
+              for (i=0; i<istop; i++)
+                 png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
+           }
+        }
+#endif
+
+      }
+   }
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   png_ptr->background_1 = png_ptr->background;
+#endif
+#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+   if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
+   {
+      png_build_gamma_table(png_ptr);
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+      if (png_ptr->transformations & PNG_BACKGROUND)
+      {
+         if (color_type == PNG_COLOR_TYPE_PALETTE)
+         {
+            png_color back, back_1;
+            png_colorp palette = png_ptr->palette;
+            int num_palette = png_ptr->num_palette;
+            int i;
+            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
+            {
+               back.red = png_ptr->gamma_table[png_ptr->background.red];
+               back.green = png_ptr->gamma_table[png_ptr->background.green];
+               back.blue = png_ptr->gamma_table[png_ptr->background.blue];
+
+               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
+               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
+               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
+            }
+            else
+            {
+               double g, gs;
+
+               switch (png_ptr->background_gamma_type)
+               {
+                  case PNG_BACKGROUND_GAMMA_SCREEN:
+                     g = (png_ptr->screen_gamma);
+                     gs = 1.0;
+                     break;
+                  case PNG_BACKGROUND_GAMMA_FILE:
+                     g = 1.0 / (png_ptr->gamma);
+                     gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+                     break;
+                  case PNG_BACKGROUND_GAMMA_UNIQUE:
+                     g = 1.0 / (png_ptr->background_gamma);
+                     gs = 1.0 / (png_ptr->background_gamma *
+                                 png_ptr->screen_gamma);
+                     break;
+                  default:
+                     g = 1.0;    /* back_1 */
+                     gs = 1.0;   /* back */
+               }
+
+               if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
+               {
+                  back.red   = (png_byte)png_ptr->background.red;
+                  back.green = (png_byte)png_ptr->background.green;
+                  back.blue  = (png_byte)png_ptr->background.blue;
+               }
+               else
+               {
+                  back.red = (png_byte)(pow(
+                     (double)png_ptr->background.red/255, gs) * 255.0 + .5);
+                  back.green = (png_byte)(pow(
+                     (double)png_ptr->background.green/255, gs) * 255.0 + .5);
+                  back.blue = (png_byte)(pow(
+                     (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
+               }
+
+               back_1.red = (png_byte)(pow(
+                  (double)png_ptr->background.red/255, g) * 255.0 + .5);
+               back_1.green = (png_byte)(pow(
+                  (double)png_ptr->background.green/255, g) * 255.0 + .5);
+               back_1.blue = (png_byte)(pow(
+                  (double)png_ptr->background.blue/255, g) * 255.0 + .5);
+            }
+            for (i = 0; i < num_palette; i++)
+            {
+               if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
+               {
+                  if (png_ptr->trans[i] == 0)
+                  {
+                     palette[i] = back;
+                  }
+                  else /* if (png_ptr->trans[i] != 0xff) */
+                  {
+                     png_byte v, w;
+
+                     v = png_ptr->gamma_to_1[palette[i].red];
+                     png_composite(w, v, png_ptr->trans[i], back_1.red);
+                     palette[i].red = png_ptr->gamma_from_1[w];
+
+                     v = png_ptr->gamma_to_1[palette[i].green];
+                     png_composite(w, v, png_ptr->trans[i], back_1.green);
+                     palette[i].green = png_ptr->gamma_from_1[w];
+
+                     v = png_ptr->gamma_to_1[palette[i].blue];
+                     png_composite(w, v, png_ptr->trans[i], back_1.blue);
+                     palette[i].blue = png_ptr->gamma_from_1[w];
+                  }
+               }
+               else
+               {
+                  palette[i].red = png_ptr->gamma_table[palette[i].red];
+                  palette[i].green = png_ptr->gamma_table[palette[i].green];
+                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+               }
+            }
+         }
+         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN)*/
+         else
+         /* color_type != PNG_COLOR_TYPE_PALETTE */
+         {
+            double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
+            double g = 1.0;
+            double gs = 1.0;
+
+            switch (png_ptr->background_gamma_type)
+            {
+               case PNG_BACKGROUND_GAMMA_SCREEN:
+                  g = (png_ptr->screen_gamma);
+                  gs = 1.0;
+                  break;
+               case PNG_BACKGROUND_GAMMA_FILE:
+                  g = 1.0 / (png_ptr->gamma);
+                  gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+                  break;
+               case PNG_BACKGROUND_GAMMA_UNIQUE:
+                  g = 1.0 / (png_ptr->background_gamma);
+                  gs = 1.0 / (png_ptr->background_gamma *
+                     png_ptr->screen_gamma);
+                  break;
+            }
+
+            if (color_type & PNG_COLOR_MASK_COLOR)
+            {
+               /* RGB or RGBA */
+               png_ptr->background_1.red = (png_uint_16)(pow(
+                  (double)png_ptr->background.red / m, g) * m + .5);
+               png_ptr->background_1.green = (png_uint_16)(pow(
+                  (double)png_ptr->background.green / m, g) * m + .5);
+               png_ptr->background_1.blue = (png_uint_16)(pow(
+                  (double)png_ptr->background.blue / m, g) * m + .5);
+               png_ptr->background.red = (png_uint_16)(pow(
+                  (double)png_ptr->background.red / m, gs) * m + .5);
+               png_ptr->background.green = (png_uint_16)(pow(
+                  (double)png_ptr->background.green / m, gs) * m + .5);
+               png_ptr->background.blue = (png_uint_16)(pow(
+                  (double)png_ptr->background.blue / m, gs) * m + .5);
+            }
+            else
+            {
+               /* GRAY or GRAY ALPHA */
+               png_ptr->background_1.gray = (png_uint_16)(pow(
+                  (double)png_ptr->background.gray / m, g) * m + .5);
+               png_ptr->background.gray = (png_uint_16)(pow(
+                  (double)png_ptr->background.gray / m, gs) * m + .5);
+            }
+         }
+      }
+      else
+      /* transformation does not include PNG_BACKGROUND */
+#endif
+      if (color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         png_colorp palette = png_ptr->palette;
+         int num_palette = png_ptr->num_palette;
+         int i;
+
+         for (i = 0; i < num_palette; i++)
+         {
+            palette[i].red = png_ptr->gamma_table[palette[i].red];
+            palette[i].green = png_ptr->gamma_table[palette[i].green];
+            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+         }
+      }
+   }
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   else
+#endif
+#endif
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   /* No GAMMA transformation */
+   if ((png_ptr->transformations & PNG_BACKGROUND) &&
+       (color_type == PNG_COLOR_TYPE_PALETTE))
+   {
+      int i;
+      int istop = (int)png_ptr->num_trans;
+      png_color back;
+      png_colorp palette = png_ptr->palette;
+
+      back.red   = (png_byte)png_ptr->background.red;
+      back.green = (png_byte)png_ptr->background.green;
+      back.blue  = (png_byte)png_ptr->background.blue;
+
+      for (i = 0; i < istop; i++)
+      {
+         if (png_ptr->trans[i] == 0)
+         {
+            palette[i] = back;
+         }
+         else if (png_ptr->trans[i] != 0xff)
+         {
+            /* The png_composite() macro is defined in png.h */
+            png_composite(palette[i].red, palette[i].red,
+               png_ptr->trans[i], back.red);
+            png_composite(palette[i].green, palette[i].green,
+               png_ptr->trans[i], back.green);
+            png_composite(palette[i].blue, palette[i].blue,
+               png_ptr->trans[i], back.blue);
+         }
+      }
+   }
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED)
+   if ((png_ptr->transformations & PNG_SHIFT) &&
+      (color_type == PNG_COLOR_TYPE_PALETTE))
+   {
+      png_uint_16 i;
+      png_uint_16 istop = png_ptr->num_palette;
+      int sr = 8 - png_ptr->sig_bit.red;
+      int sg = 8 - png_ptr->sig_bit.green;
+      int sb = 8 - png_ptr->sig_bit.blue;
+
+      if (sr < 0 || sr > 8)
+         sr = 0;
+      if (sg < 0 || sg > 8)
+         sg = 0;
+      if (sb < 0 || sb > 8)
+         sb = 0;
+      for (i = 0; i < istop; i++)
+      {
+         png_ptr->palette[i].red >>= sr;
+         png_ptr->palette[i].green >>= sg;
+         png_ptr->palette[i].blue >>= sb;
+      }
+   }
+#endif
+ }
+#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
+ && !defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if(png_ptr)
+      return;
+#endif
+}
+
+/* Modify the info structure to reflect the transformations.  The
+ * info should be updated so a PNG file could be written with it,
+ * assuming the transformations result in valid PNG data.
+ */
+void /* PRIVATE */
+png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_read_transform_info\n");
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+   if (png_ptr->transformations & PNG_EXPAND)
+   {
+      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         if (png_ptr->num_trans)
+            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+         else
+            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
+         info_ptr->bit_depth = 8;
+         info_ptr->num_trans = 0;
+      }
+      else
+      {
+         if (png_ptr->num_trans)
+            info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
+         if (info_ptr->bit_depth < 8)
+            info_ptr->bit_depth = 8;
+         info_ptr->num_trans = 0;
+      }
+   }
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if (png_ptr->transformations & PNG_BACKGROUND)
+   {
+      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
+      info_ptr->num_trans = 0;
+      info_ptr->background = png_ptr->background;
+   }
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   if (png_ptr->transformations & PNG_GAMMA)
+   {
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+      info_ptr->gamma = png_ptr->gamma;
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+      info_ptr->int_gamma = png_ptr->int_gamma;
+#endif
+   }
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+   if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
+      info_ptr->bit_depth = 8;
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+   if (png_ptr->transformations & PNG_DITHER)
+   {
+      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
+         (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
+         png_ptr->palette_lookup && info_ptr->bit_depth == 8)
+      {
+         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
+      }
+   }
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+   if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
+      info_ptr->bit_depth = 8;
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+      info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+      info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
+#endif
+
+   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      info_ptr->channels = 1;
+   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+      info_ptr->channels = 3;
+   else
+      info_ptr->channels = 1;
+
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_STRIP_ALPHA)
+      info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
+#endif
+
+   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+      info_ptr->channels++;
+
+#if defined(PNG_READ_FILLER_SUPPORTED)
+   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
+   if ((png_ptr->transformations & PNG_FILLER) &&
+       ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
+       (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
+   {
+      info_ptr->channels++;
+#if 0 /* if adding a true alpha channel not just filler */
+      info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
+#endif
+   }
+#endif
+
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
+defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   if(png_ptr->transformations & PNG_USER_TRANSFORM)
+     {
+       if(info_ptr->bit_depth < png_ptr->user_transform_depth)
+         info_ptr->bit_depth = png_ptr->user_transform_depth;
+       if(info_ptr->channels < png_ptr->user_transform_channels)
+         info_ptr->channels = png_ptr->user_transform_channels;
+     }
+#endif
+
+   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
+      info_ptr->bit_depth);
+   info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
+
+#if !defined(PNG_READ_EXPAND_SUPPORTED)
+   if(png_ptr)
+      return;
+#endif
+}
+
+/* Transform the row.  The order of transformations is significant,
+ * and is very touchy.  If you add a transformation, take care to
+ * decide how it fits in with the other transformations here.
+ */
+void /* PRIVATE */
+png_do_read_transformations(png_structp png_ptr)
+{
+   png_debug(1, "in png_do_read_transformations\n");
+#if !defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (png_ptr->row_buf == NULL)
+   {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+      char msg[50];
+
+      sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
+         png_ptr->pass);
+      png_error(png_ptr, msg);
+#else
+      png_error(png_ptr, "NULL row buffer");
+#endif
+   }
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+   if (png_ptr->transformations & PNG_EXPAND)
+   {
+      if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
+            png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
+      }
+      else
+      {
+         if (png_ptr->num_trans)
+            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
+               &(png_ptr->trans_values));
+         else
+            png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
+               NULL);
+      }
+   }
+#endif
+
+#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_STRIP_ALPHA)
+      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         PNG_FLAG_FILLER_AFTER);
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+   if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+   {
+      int rgb_error =
+         png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
+      if(rgb_error)
+      {
+         png_ptr->rgb_to_gray_status=1;
+         if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
+            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
+         if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
+            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
+      }
+   }
+#endif
+
+/*
+From Andreas Dilger e-mail to png-implement, 26 March 1998:
+
+  In most cases, the "simple transparency" should be done prior to doing
+  gray-to-RGB, or you will have to test 3x as many bytes to check if a
+  pixel is transparent.  You would also need to make sure that the
+  transparency information is upgraded to RGB.
+
+  To summarize, the current flow is:
+  - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
+                                  with background "in place" if transparent,
+                                  convert to RGB if necessary
+  - Gray + alpha -> composite with gray background and remove alpha bytes,
+                                  convert to RGB if necessary
+
+  To support RGB backgrounds for gray images we need:
+  - Gray + simple transparency -> convert to RGB + simple transparency, compare
+                                  3 or 6 bytes and composite with background
+                                  "in place" if transparent (3x compare/pixel
+                                  compared to doing composite with gray bkgrnd)
+  - Gray + alpha -> convert to RGB + alpha, composite with background and
+                                  remove alpha bytes (3x float operations/pixel
+                                  compared with composite on gray background)
+
+  Greg's change will do this.  The reason it wasn't done before is for
+  performance, as this increases the per-pixel operations.  If we would check
+  in advance if the background was gray or RGB, and position the gray-to-RGB
+  transform appropriately, then it would save a lot of work/time.
+ */
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+   /* if gray -> RGB, do so now only if background is non-gray; else do later
+    * for performance reasons */
+   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
+       !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
+      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if ((png_ptr->transformations & PNG_BACKGROUND) &&
+      ((png_ptr->num_trans != 0 ) ||
+      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
+      png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         &(png_ptr->trans_values), &(png_ptr->background),
+         &(png_ptr->background_1),
+         png_ptr->gamma_table, png_ptr->gamma_from_1,
+         png_ptr->gamma_to_1, png_ptr->gamma_16_table,
+         png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
+         png_ptr->gamma_shift);
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   if ((png_ptr->transformations & PNG_GAMMA) &&
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+      !((png_ptr->transformations & PNG_BACKGROUND) &&
+      ((png_ptr->num_trans != 0) ||
+      (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
+#endif
+      (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
+      png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         png_ptr->gamma_table, png_ptr->gamma_16_table,
+         png_ptr->gamma_shift);
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+   if (png_ptr->transformations & PNG_16_TO_8)
+      png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+   if (png_ptr->transformations & PNG_DITHER)
+   {
+      png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
+         png_ptr->palette_lookup, png_ptr->dither_index);
+      if(png_ptr->row_info.rowbytes == (png_uint_32)0)
+         png_error(png_ptr, "png_do_dither returned rowbytes=0");
+   }
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_MONO)
+      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED)
+   if (png_ptr->transformations & PNG_SHIFT)
+      png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         &(png_ptr->shift));
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACK)
+      png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED)
+   if (png_ptr->transformations & PNG_BGR)
+      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACKSWAP)
+      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+   /* if gray -> RGB, do so now only if we did not do so above */
+   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
+       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
+      png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED)
+   if (png_ptr->transformations & PNG_FILLER)
+      png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         (png_uint_32)png_ptr->filler, png_ptr->flags);
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_ALPHA)
+      png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_ALPHA)
+      png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   if (png_ptr->transformations & PNG_USER_TRANSFORM)
+    {
+      if(png_ptr->read_user_transform_fn != NULL)
+        (*(png_ptr->read_user_transform_fn)) /* user read transform function */
+          (png_ptr,                    /* png_ptr */
+           &(png_ptr->row_info),       /* row_info:     */
+             /*  png_uint_32 width;          width of row */
+             /*  png_uint_32 rowbytes;       number of bytes in row */
+             /*  png_byte color_type;        color type of pixels */
+             /*  png_byte bit_depth;         bit depth of samples */
+             /*  png_byte channels;          number of channels (1-4) */
+             /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
+           png_ptr->row_buf + 1);      /* start of pixel data for row */
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+      if(png_ptr->user_transform_depth)
+         png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
+      if(png_ptr->user_transform_channels)
+         png_ptr->row_info.channels = png_ptr->user_transform_channels;
+#endif
+      png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
+         png_ptr->row_info.channels);
+      png_ptr->row_info.rowbytes = (png_ptr->row_info.width *
+         png_ptr->row_info.pixel_depth+7)>>3;
+   }
+#endif
+
+}
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
+ * without changing the actual values.  Thus, if you had a row with
+ * a bit depth of 1, you would end up with bytes that only contained
+ * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
+ * png_do_shift() after this.
+ */
+void /* PRIVATE */
+png_do_unpack(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_unpack\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
+#else
+   if (row_info->bit_depth < 8)
+#endif
+   {
+      png_uint_32 i;
+      png_uint_32 row_width=row_info->width;
+
+      switch (row_info->bit_depth)
+      {
+         case 1:
+         {
+            png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
+            png_bytep dp = row + (png_size_t)row_width - 1;
+            png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
+            for (i = 0; i < row_width; i++)
+            {
+               *dp = (png_byte)((*sp >> shift) & 0x01);
+               if (shift == 7)
+               {
+                  shift = 0;
+                  sp--;
+               }
+               else
+                  shift++;
+
+               dp--;
+            }
+            break;
+         }
+         case 2:
+         {
+
+            png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
+            png_bytep dp = row + (png_size_t)row_width - 1;
+            png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
+            for (i = 0; i < row_width; i++)
+            {
+               *dp = (png_byte)((*sp >> shift) & 0x03);
+               if (shift == 6)
+               {
+                  shift = 0;
+                  sp--;
+               }
+               else
+                  shift += 2;
+
+               dp--;
+            }
+            break;
+         }
+         case 4:
+         {
+            png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
+            png_bytep dp = row + (png_size_t)row_width - 1;
+            png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
+            for (i = 0; i < row_width; i++)
+            {
+               *dp = (png_byte)((*sp >> shift) & 0x0f);
+               if (shift == 4)
+               {
+                  shift = 0;
+                  sp--;
+               }
+               else
+                  shift = 4;
+
+               dp--;
+            }
+            break;
+         }
+      }
+      row_info->bit_depth = 8;
+      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
+      row_info->rowbytes = row_width * row_info->channels;
+   }
+}
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED)
+/* Reverse the effects of png_do_shift.  This routine merely shifts the
+ * pixels back to their significant bits values.  Thus, if you have
+ * a row of bit depth 8, but only 5 are significant, this will shift
+ * the values back to 0 through 31.
+ */
+void /* PRIVATE */
+png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
+{
+   png_debug(1, "in png_do_unshift\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL && sig_bits != NULL &&
+#endif
+       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
+   {
+      int shift[4];
+      int channels = 0;
+      int c;
+      png_uint_16 value = 0;
+      png_uint_32 row_width = row_info->width;
+
+      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+      {
+         shift[channels++] = row_info->bit_depth - sig_bits->red;
+         shift[channels++] = row_info->bit_depth - sig_bits->green;
+         shift[channels++] = row_info->bit_depth - sig_bits->blue;
+      }
+      else
+      {
+         shift[channels++] = row_info->bit_depth - sig_bits->gray;
+      }
+      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+      {
+         shift[channels++] = row_info->bit_depth - sig_bits->alpha;
+      }
+
+      for (c = 0; c < channels; c++)
+      {
+         if (shift[c] <= 0)
+            shift[c] = 0;
+         else
+            value = 1;
+      }
+
+      if (!value)
+         return;
+
+      switch (row_info->bit_depth)
+      {
+         case 2:
+         {
+            png_bytep bp;
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+
+            for (bp = row, i = 0; i < istop; i++)
+            {
+               *bp >>= 1;
+               *bp++ &= 0x55;
+            }
+            break;
+         }
+         case 4:
+         {
+            png_bytep bp = row;
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+            png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
+               (png_byte)((int)0xf >> shift[0]));
+
+            for (i = 0; i < istop; i++)
+            {
+               *bp >>= shift[0];
+               *bp++ &= mask;
+            }
+            break;
+         }
+         case 8:
+         {
+            png_bytep bp = row;
+            png_uint_32 i;
+            png_uint_32 istop = row_width * channels;
+
+            for (i = 0; i < istop; i++)
+            {
+               *bp++ >>= shift[i%channels];
+            }
+            break;
+         }
+         case 16:
+         {
+            png_bytep bp = row;
+            png_uint_32 i;
+            png_uint_32 istop = channels * row_width;
+
+            for (i = 0; i < istop; i++)
+            {
+               value = (png_uint_16)((*bp << 8) + *(bp + 1));
+               value >>= shift[i%channels];
+               *bp++ = (png_byte)(value >> 8);
+               *bp++ = (png_byte)(value & 0xff);
+            }
+            break;
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_16_TO_8_SUPPORTED)
+/* chop rows of bit depth 16 down to 8 */
+void /* PRIVATE */
+png_do_chop(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_chop\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
+#else
+   if (row_info->bit_depth == 16)
+#endif
+   {
+      png_bytep sp = row;
+      png_bytep dp = row;
+      png_uint_32 i;
+      png_uint_32 istop = row_info->width * row_info->channels;
+
+      for (i = 0; i<istop; i++, sp += 2, dp++)
+      {
+#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
+      /* This does a more accurate scaling of the 16-bit color
+       * value, rather than a simple low-byte truncation.
+       *
+       * What the ideal calculation should be:
+       *   *dp = (((((png_uint_32)(*sp) << 8) |
+       *          (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
+       *
+       * GRR: no, I think this is what it really should be:
+       *   *dp = (((((png_uint_32)(*sp) << 8) |
+       *           (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
+       *
+       * GRR: here's the exact calculation with shifts:
+       *   temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
+       *   *dp = (temp - (temp >> 8)) >> 8;
+       *
+       * Approximate calculation with shift/add instead of multiply/divide:
+       *   *dp = ((((png_uint_32)(*sp) << 8) |
+       *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
+       *
+       * What we actually do to avoid extra shifting and conversion:
+       */
+
+         *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
+#else
+       /* Simply discard the low order byte */
+         *dp = *sp;
+#endif
+      }
+      row_info->bit_depth = 8;
+      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
+      row_info->rowbytes = row_info->width * row_info->channels;
+   }
+}
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
+void /* PRIVATE */
+png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_read_swap_alpha\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      png_uint_32 row_width = row_info->width;
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         /* This converts from RGBA to ARGB */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_byte save;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               save = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = save;
+            }
+         }
+         /* This converts from RRGGBBAA to AARRGGBB */
+         else
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_byte save[2];
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               save[0] = *(--sp);
+               save[1] = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = save[0];
+               *(--dp) = save[1];
+            }
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         /* This converts from GA to AG */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_byte save;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               save = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = save;
+            }
+         }
+         /* This converts from GGAA to AAGG */
+         else
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_byte save[2];
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               save[0] = *(--sp);
+               save[1] = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = save[0];
+               *(--dp) = save[1];
+            }
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
+void /* PRIVATE */
+png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_read_invert_alpha\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      png_uint_32 row_width = row_info->width;
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         /* This inverts the alpha channel in RGBA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = (png_byte)(255 - *(--sp));
+
+/*             This does nothing:
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               We can replace it with:
+*/
+               sp-=3;
+               dp=sp;
+            }
+         }
+         /* This inverts the alpha channel in RRGGBBAA */
+         else
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = (png_byte)(255 - *(--sp));
+               *(--dp) = (png_byte)(255 - *(--sp));
+
+/*             This does nothing:
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               We can replace it with:
+*/
+               sp-=6;
+               dp=sp;
+            }
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         /* This inverts the alpha channel in GA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = (png_byte)(255 - *(--sp));
+               *(--dp) = *(--sp);
+            }
+         }
+         /* This inverts the alpha channel in GGAA */
+         else
+         {
+            png_bytep sp  = row + row_info->rowbytes;
+            png_bytep dp = sp;
+            png_uint_32 i;
+
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = (png_byte)(255 - *(--sp));
+               *(--dp) = (png_byte)(255 - *(--sp));
+/*
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+*/
+               sp-=2;
+               dp=sp;
+            }
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED)
+/* Add filler channel if we have RGB color */
+void /* PRIVATE */
+png_do_read_filler(png_row_infop row_info, png_bytep row,
+   png_uint_32 filler, png_uint_32 flags)
+{
+   png_uint_32 i;
+   png_uint_32 row_width = row_info->width;
+
+   png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
+   png_byte lo_filler = (png_byte)(filler & 0xff);
+
+   png_debug(1, "in png_do_read_filler\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL  && row_info != NULL &&
+#endif
+       row_info->color_type == PNG_COLOR_TYPE_GRAY)
+   {
+      if(row_info->bit_depth == 8)
+      {
+         /* This changes the data from G to GX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp =  sp + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = lo_filler;
+            row_info->channels = 2;
+            row_info->pixel_depth = 16;
+            row_info->rowbytes = row_width * 2;
+         }
+      /* This changes the data from G to XG */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 2;
+            row_info->pixel_depth = 16;
+            row_info->rowbytes = row_width * 2;
+         }
+      }
+      else if(row_info->bit_depth == 16)
+      {
+         /* This changes the data from GG to GGXX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = hi_filler;
+            *(--dp) = lo_filler;
+            row_info->channels = 2;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 4;
+         }
+         /* This changes the data from GG to XXGG */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 2;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 4;
+         }
+      }
+   } /* COLOR_TYPE == GRAY */
+   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+   {
+      if(row_info->bit_depth == 8)
+      {
+         /* This changes the data from RGB to RGBX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = lo_filler;
+            row_info->channels = 4;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 4;
+         }
+      /* This changes the data from RGB to XRGB */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 4;
+            row_info->pixel_depth = 32;
+            row_info->rowbytes = row_width * 4;
+         }
+      }
+      else if(row_info->bit_depth == 16)
+      {
+         /* This changes the data from RRGGBB to RRGGBBXX */
+         if (flags & PNG_FLAG_FILLER_AFTER)
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 1; i < row_width; i++)
+            {
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+            }
+            *(--dp) = hi_filler;
+            *(--dp) = lo_filler;
+            row_info->channels = 4;
+            row_info->pixel_depth = 64;
+            row_info->rowbytes = row_width * 8;
+         }
+         /* This changes the data from RRGGBB to XXRRGGBB */
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width * 3;
+            png_bytep dp = sp  + (png_size_t)row_width;
+            for (i = 0; i < row_width; i++)
+            {
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = *(--sp);
+               *(--dp) = hi_filler;
+               *(--dp) = lo_filler;
+            }
+            row_info->channels = 4;
+            row_info->pixel_depth = 64;
+            row_info->rowbytes = row_width * 8;
+         }
+      }
+   } /* COLOR_TYPE == RGB */
+}
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+/* expand grayscale files to RGB, with or without alpha */
+void /* PRIVATE */
+png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
+{
+   png_uint_32 i;
+   png_uint_32 row_width = row_info->width;
+
+   png_debug(1, "in png_do_gray_to_rgb\n");
+   if (row_info->bit_depth >= 8 &&
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+      !(row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
+      {
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + (png_size_t)row_width - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 2;
+            for (i = 0; i < row_width; i++)
+            {
+               *(dp--) = *sp;
+               *(dp--) = *sp;
+               *(dp--) = *(sp--);
+            }
+         }
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 4;
+            for (i = 0; i < row_width; i++)
+            {
+               *(dp--) = *sp;
+               *(dp--) = *(sp - 1);
+               *(dp--) = *sp;
+               *(dp--) = *(sp - 1);
+               *(dp--) = *(sp--);
+               *(dp--) = *(sp--);
+            }
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp = row + (png_size_t)row_width * 2 - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 2;
+            for (i = 0; i < row_width; i++)
+            {
+               *(dp--) = *(sp--);
+               *(dp--) = *sp;
+               *(dp--) = *sp;
+               *(dp--) = *(sp--);
+            }
+         }
+         else
+         {
+            png_bytep sp = row + (png_size_t)row_width * 4 - 1;
+            png_bytep dp = sp  + (png_size_t)row_width * 4;
+            for (i = 0; i < row_width; i++)
+            {
+               *(dp--) = *(sp--);
+               *(dp--) = *(sp--);
+               *(dp--) = *sp;
+               *(dp--) = *(sp - 1);
+               *(dp--) = *sp;
+               *(dp--) = *(sp - 1);
+               *(dp--) = *(sp--);
+               *(dp--) = *(sp--);
+            }
+         }
+      }
+      row_info->channels += (png_byte)2;
+      row_info->color_type |= PNG_COLOR_MASK_COLOR;
+      row_info->pixel_depth = (png_byte)(row_info->channels *
+         row_info->bit_depth);
+      row_info->rowbytes = ((row_width *
+         row_info->pixel_depth + 7) >> 3);
+   }
+}
+#endif
+
+#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+/* reduce RGB files to grayscale, with or without alpha
+ * using the equation given in Poynton's ColorFAQ at
+ * <http://www.inforamp.net/~poynton/>
+ * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net
+ *
+ *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+ *
+ *  We approximate this with
+ *
+ *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
+ *
+ *  which can be expressed with integers as
+ *
+ *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
+ *
+ *  The calculation is to be done in a linear colorspace.
+ *
+ *  Other integer coefficents can be used via png_set_rgb_to_gray().
+ */
+int /* PRIVATE */
+png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
+
+{
+   png_uint_32 i;
+
+   png_uint_32 row_width = row_info->width;
+   int rgb_error = 0;
+
+   png_debug(1, "in png_do_rgb_to_gray\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+      (row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
+      png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
+      png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
+
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+      {
+         if (row_info->bit_depth == 8)
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
+                  if(red != green || red != blue)
+                  {
+                     rgb_error |= 1;
+                     *(dp++) = png_ptr->gamma_from_1[
+                       (rc*red+gc*green+bc*blue)>>15];
+                  }
+                  else
+                     *(dp++) = *(sp-1);
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = *(sp++);
+                  png_byte green = *(sp++);
+                  png_byte blue  = *(sp++);
+                  if(red != green || red != blue)
+                  {
+                     rgb_error |= 1;
+                     *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
+                  }
+                  else
+                     *(dp++) = *(sp-1);
+               }
+            }
+         }
+
+         else /* RGB bit_depth == 16 */
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_16_to_1 != NULL &&
+                png_ptr->gamma_16_from_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, w;
+
+                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+
+                  if(red == green && red == blue)
+                     w = red;
+                  else
+                  {
+                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
+                                  png_ptr->gamma_shift][red>>8];
+                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
+                                  png_ptr->gamma_shift][green>>8];
+                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
+                                  png_ptr->gamma_shift][blue>>8];
+                     png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
+                                  + bc*blue_1)>>15);
+                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+                         png_ptr->gamma_shift][gray16 >> 8];
+                     rgb_error |= 1;
+                  }
+
+                  *(dp++) = (png_byte)((w>>8) & 0xff);
+                  *(dp++) = (png_byte)(w & 0xff);
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, gray16;
+
+                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
+                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
+                  *(dp++) = (png_byte)(gray16 & 0xff);
+               }
+            }
+         }
+      }
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         if (row_info->bit_depth == 8)
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte green = png_ptr->gamma_to_1[*(sp++)];
+                  png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  *(dp++) =  png_ptr->gamma_from_1
+                             [(rc*red + gc*green + bc*blue)>>15];
+                  *(dp++) = *(sp++);  /* alpha */
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_byte red   = *(sp++);
+                  png_byte green = *(sp++);
+                  png_byte blue  = *(sp++);
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  *(dp++) =  (png_byte)((gc*red + gc*green + bc*blue)>>8);
+                  *(dp++) = *(sp++);  /* alpha */
+               }
+            }
+         }
+         else /* RGBA bit_depth == 16 */
+         {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+            if (png_ptr->gamma_16_to_1 != NULL &&
+                png_ptr->gamma_16_from_1 != NULL)
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, w;
+
+                  red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+                  blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+
+                  if(red == green && red == blue)
+                     w = red;
+                  else
+                  {
+                     png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
+                                  png_ptr->gamma_shift][red>>8];
+                     png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
+                                  png_ptr->gamma_shift][green>>8];
+                     png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
+                                  png_ptr->gamma_shift][blue>>8];
+                     png_uint_16 gray16  = (png_uint_16)((rc * red_1
+                                  + gc * green_1 + bc * blue_1)>>15);
+                     w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+                         png_ptr->gamma_shift][gray16 >> 8];
+                     rgb_error |= 1;
+                  }
+
+                  *(dp++) = (png_byte)((w>>8) & 0xff);
+                  *(dp++) = (png_byte)(w & 0xff);
+                  *(dp++) = *(sp++);  /* alpha */
+                  *(dp++) = *(sp++);
+               }
+            }
+            else
+#endif
+            {
+               png_bytep sp = row;
+               png_bytep dp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 red, green, blue, gray16;
+                  red   = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
+                  green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
+                  blue  = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
+                  if(red != green || red != blue)
+                     rgb_error |= 1;
+                  gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
+                  *(dp++) = (png_byte)((gray16>>8) & 0xff);
+                  *(dp++) = (png_byte)(gray16 & 0xff);
+                  *(dp++) = *(sp++);  /* alpha */
+                  *(dp++) = *(sp++);
+               }
+            }
+         }
+      }
+   row_info->channels -= (png_byte)2;
+      row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
+      row_info->pixel_depth = (png_byte)(row_info->channels *
+         row_info->bit_depth);
+      row_info->rowbytes = ((row_width *
+         row_info->pixel_depth + 7) >> 3);
+   }
+   return rgb_error;
+}
+#endif
+
+/* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
+ * large of png_color.  This lets grayscale images be treated as
+ * paletted.  Most useful for gamma correction and simplification
+ * of code.
+ */
+void /* PRIVATE */
+png_build_grayscale_palette(int bit_depth, png_colorp palette)
+{
+   int num_palette;
+   int color_inc;
+   int i;
+   int v;
+
+   png_debug(1, "in png_do_build_grayscale_palette\n");
+   if (palette == NULL)
+      return;
+
+   switch (bit_depth)
+   {
+      case 1:
+         num_palette = 2;
+         color_inc = 0xff;
+         break;
+      case 2:
+         num_palette = 4;
+         color_inc = 0x55;
+         break;
+      case 4:
+         num_palette = 16;
+         color_inc = 0x11;
+         break;
+      case 8:
+         num_palette = 256;
+         color_inc = 1;
+         break;
+      default:
+         num_palette = 0;
+         color_inc = 0;
+         break;
+   }
+
+   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
+   {
+      palette[i].red = (png_byte)v;
+      palette[i].green = (png_byte)v;
+      palette[i].blue = (png_byte)v;
+   }
+}
+
+/* This function is currently unused.  Do we really need it? */
+#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
+void /* PRIVATE */
+png_correct_palette(png_structp png_ptr, png_colorp palette,
+   int num_palette)
+{
+   png_debug(1, "in png_correct_palette\n");
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
+    defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+   if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
+   {
+      png_color back, back_1;
+
+      if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
+      {
+         back.red = png_ptr->gamma_table[png_ptr->background.red];
+         back.green = png_ptr->gamma_table[png_ptr->background.green];
+         back.blue = png_ptr->gamma_table[png_ptr->background.blue];
+
+         back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
+         back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
+         back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
+      }
+      else
+      {
+         double g;
+
+         g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
+
+         if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
+             fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
+         {
+            back.red = png_ptr->background.red;
+            back.green = png_ptr->background.green;
+            back.blue = png_ptr->background.blue;
+         }
+         else
+         {
+            back.red =
+               (png_byte)(pow((double)png_ptr->background.red/255, g) *
+                255.0 + 0.5);
+            back.green =
+               (png_byte)(pow((double)png_ptr->background.green/255, g) *
+                255.0 + 0.5);
+            back.blue =
+               (png_byte)(pow((double)png_ptr->background.blue/255, g) *
+                255.0 + 0.5);
+         }
+
+         g = 1.0 / png_ptr->background_gamma;
+
+         back_1.red =
+            (png_byte)(pow((double)png_ptr->background.red/255, g) *
+             255.0 + 0.5);
+         back_1.green =
+            (png_byte)(pow((double)png_ptr->background.green/255, g) *
+             255.0 + 0.5);
+         back_1.blue =
+            (png_byte)(pow((double)png_ptr->background.blue/255, g) *
+             255.0 + 0.5);
+      }
+
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         png_uint_32 i;
+
+         for (i = 0; i < (png_uint_32)num_palette; i++)
+         {
+            if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
+            {
+               palette[i] = back;
+            }
+            else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
+            {
+               png_byte v, w;
+
+               v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
+               png_composite(w, v, png_ptr->trans[i], back_1.red);
+               palette[i].red = png_ptr->gamma_from_1[w];
+
+               v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
+               png_composite(w, v, png_ptr->trans[i], back_1.green);
+               palette[i].green = png_ptr->gamma_from_1[w];
+
+               v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
+               png_composite(w, v, png_ptr->trans[i], back_1.blue);
+               palette[i].blue = png_ptr->gamma_from_1[w];
+            }
+            else
+            {
+               palette[i].red = png_ptr->gamma_table[palette[i].red];
+               palette[i].green = png_ptr->gamma_table[palette[i].green];
+               palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+            }
+         }
+      }
+      else
+      {
+         int i;
+
+         for (i = 0; i < num_palette; i++)
+         {
+            if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
+            {
+               palette[i] = back;
+            }
+            else
+            {
+               palette[i].red = png_ptr->gamma_table[palette[i].red];
+               palette[i].green = png_ptr->gamma_table[palette[i].green];
+               palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+            }
+         }
+      }
+   }
+   else
+#endif
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+   if (png_ptr->transformations & PNG_GAMMA)
+   {
+      int i;
+
+      for (i = 0; i < num_palette; i++)
+      {
+         palette[i].red = png_ptr->gamma_table[palette[i].red];
+         palette[i].green = png_ptr->gamma_table[palette[i].green];
+         palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+      }
+   }
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   else
+#endif
+#endif
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+   if (png_ptr->transformations & PNG_BACKGROUND)
+   {
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         png_color back;
+
+         back.red   = (png_byte)png_ptr->background.red;
+         back.green = (png_byte)png_ptr->background.green;
+         back.blue  = (png_byte)png_ptr->background.blue;
+
+         for (i = 0; i < (int)png_ptr->num_trans; i++)
+         {
+            if (png_ptr->trans[i] == 0)
+            {
+               palette[i].red = back.red;
+               palette[i].green = back.green;
+               palette[i].blue = back.blue;
+            }
+            else if (png_ptr->trans[i] != 0xff)
+            {
+               png_composite(palette[i].red, png_ptr->palette[i].red,
+                  png_ptr->trans[i], back.red);
+               png_composite(palette[i].green, png_ptr->palette[i].green,
+                  png_ptr->trans[i], back.green);
+               png_composite(palette[i].blue, png_ptr->palette[i].blue,
+                  png_ptr->trans[i], back.blue);
+            }
+         }
+      }
+      else /* assume grayscale palette (what else could it be?) */
+      {
+         int i;
+
+         for (i = 0; i < num_palette; i++)
+         {
+            if (i == (png_byte)png_ptr->trans_values.gray)
+            {
+               palette[i].red = (png_byte)png_ptr->background.red;
+               palette[i].green = (png_byte)png_ptr->background.green;
+               palette[i].blue = (png_byte)png_ptr->background.blue;
+            }
+         }
+      }
+   }
+#endif
+}
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED)
+/* Replace any alpha or transparency with the supplied background color.
+ * "background" is already in the screen gamma, while "background_1" is
+ * at a gamma of 1.0.  Paletted files have already been taken care of.
+ */
+void /* PRIVATE */
+png_do_background(png_row_infop row_info, png_bytep row,
+   png_color_16p trans_values, png_color_16p background,
+   png_color_16p background_1,
+   png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
+   png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
+   png_uint_16pp gamma_16_to_1, int gamma_shift)
+{
+   png_bytep sp, dp;
+   png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
+   int shift;
+
+   png_debug(1, "in png_do_background\n");
+   if (background != NULL &&
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+      (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
+      (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
+   {
+      switch (row_info->color_type)
+      {
+         case PNG_COLOR_TYPE_GRAY:
+         {
+            switch (row_info->bit_depth)
+            {
+               case 1:
+               {
+                  sp = row;
+                  shift = 7;
+                  for (i = 0; i < row_width; i++)
+                  {
+                     if ((png_uint_16)((*sp >> shift) & 0x01)
+                        == trans_values->gray)
+                     {
+                        *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
+                        *sp |= (png_byte)(background->gray << shift);
+                     }
+                     if (!shift)
+                     {
+                        shift = 7;
+                        sp++;
+                     }
+                     else
+                        shift--;
+                  }
+                  break;
+               }
+               case 2:
+               {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+                  if (gamma_table != NULL)
+                  {
+                     sp = row;
+                     shift = 6;
+                     for (i = 0; i < row_width; i++)
+                     {
+                        if ((png_uint_16)((*sp >> shift) & 0x03)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        else
+                        {
+                           png_byte p = (png_byte)((*sp >> shift) & 0x03);
+                           png_byte g = (png_byte)((gamma_table [p | (p << 2) |
+                               (p << 4) | (p << 6)] >> 6) & 0x03);
+                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                           *sp |= (png_byte)(g << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 6;
+                           sp++;
+                        }
+                        else
+                           shift -= 2;
+                     }
+                  }
+                  else
+#endif
+                  {
+                     sp = row;
+                     shift = 6;
+                     for (i = 0; i < row_width; i++)
+                     {
+                        if ((png_uint_16)((*sp >> shift) & 0x03)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 6;
+                           sp++;
+                        }
+                        else
+                           shift -= 2;
+                     }
+                  }
+                  break;
+               }
+               case 4:
+               {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+                  if (gamma_table != NULL)
+                  {
+                     sp = row;
+                     shift = 4;
+                     for (i = 0; i < row_width; i++)
+                     {
+                        if ((png_uint_16)((*sp >> shift) & 0x0f)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        else
+                        {
+                           png_byte p = (png_byte)((*sp >> shift) & 0x0f);
+                           png_byte g = (png_byte)((gamma_table[p |
+                             (p << 4)] >> 4) & 0x0f);
+                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                           *sp |= (png_byte)(g << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 4;
+                           sp++;
+                        }
+                        else
+                           shift -= 4;
+                     }
+                  }
+                  else
+#endif
+                  {
+                     sp = row;
+                     shift = 4;
+                     for (i = 0; i < row_width; i++)
+                     {
+                        if ((png_uint_16)((*sp >> shift) & 0x0f)
+                            == trans_values->gray)
+                        {
+                           *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                           *sp |= (png_byte)(background->gray << shift);
+                        }
+                        if (!shift)
+                        {
+                           shift = 4;
+                           sp++;
+                        }
+                        else
+                           shift -= 4;
+                     }
+                  }
+                  break;
+               }
+               case 8:
+               {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+                  if (gamma_table != NULL)
+                  {
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp++)
+                     {
+                        if (*sp == trans_values->gray)
+                        {
+                           *sp = (png_byte)background->gray;
+                        }
+                        else
+                        {
+                           *sp = gamma_table[*sp];
+                        }
+                     }
+                  }
+                  else
+#endif
+                  {
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp++)
+                     {
+                        if (*sp == trans_values->gray)
+                        {
+                           *sp = (png_byte)background->gray;
+                        }
+                     }
+                  }
+                  break;
+               }
+               case 16:
+               {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+                  if (gamma_16 != NULL)
+                  {
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp += 2)
+                     {
+                        png_uint_16 v;
+
+                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+                        if (v == trans_values->gray)
+                        {
+                           /* background is already in screen gamma */
+                           *sp = (png_byte)((background->gray >> 8) & 0xff);
+                           *(sp + 1) = (png_byte)(background->gray & 0xff);
+                        }
+                        else
+                        {
+                           v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+                           *sp = (png_byte)((v >> 8) & 0xff);
+                           *(sp + 1) = (png_byte)(v & 0xff);
+                        }
+                     }
+                  }
+                  else
+#endif
+                  {
+                     sp = row;
+                     for (i = 0; i < row_width; i++, sp += 2)
+                     {
+                        png_uint_16 v;
+
+                        v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+                        if (v == trans_values->gray)
+                        {
+                           *sp = (png_byte)((background->gray >> 8) & 0xff);
+                           *(sp + 1) = (png_byte)(background->gray & 0xff);
+                        }
+                     }
+                  }
+                  break;
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_RGB:
+         {
+            if (row_info->bit_depth == 8)
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_table != NULL)
+               {
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 3)
+                  {
+                     if (*sp == trans_values->red &&
+                        *(sp + 1) == trans_values->green &&
+                        *(sp + 2) == trans_values->blue)
+                     {
+                        *sp = (png_byte)background->red;
+                        *(sp + 1) = (png_byte)background->green;
+                        *(sp + 2) = (png_byte)background->blue;
+                     }
+                     else
+                     {
+                        *sp = gamma_table[*sp];
+                        *(sp + 1) = gamma_table[*(sp + 1)];
+                        *(sp + 2) = gamma_table[*(sp + 2)];
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 3)
+                  {
+                     if (*sp == trans_values->red &&
+                        *(sp + 1) == trans_values->green &&
+                        *(sp + 2) == trans_values->blue)
+                     {
+                        *sp = (png_byte)background->red;
+                        *(sp + 1) = (png_byte)background->green;
+                        *(sp + 2) = (png_byte)background->blue;
+                     }
+                  }
+               }
+            }
+            else /* if (row_info->bit_depth == 16) */
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_16 != NULL)
+               {
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 6)
+                  {
+                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+                     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+                     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
+                     if (r == trans_values->red && g == trans_values->green &&
+                        b == trans_values->blue)
+                     {
+                        /* background is already in screen gamma */
+                        *sp = (png_byte)((background->red >> 8) & 0xff);
+                        *(sp + 1) = (png_byte)(background->red & 0xff);
+                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
+                        *(sp + 3) = (png_byte)(background->green & 0xff);
+                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+                        *(sp + 5) = (png_byte)(background->blue & 0xff);
+                     }
+                     else
+                     {
+                        png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+                        *sp = (png_byte)((v >> 8) & 0xff);
+                        *(sp + 1) = (png_byte)(v & 0xff);
+                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
+                        *(sp + 2) = (png_byte)((v >> 8) & 0xff);
+                        *(sp + 3) = (png_byte)(v & 0xff);
+                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
+                        *(sp + 4) = (png_byte)((v >> 8) & 0xff);
+                        *(sp + 5) = (png_byte)(v & 0xff);
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  for (i = 0; i < row_width; i++, sp += 6)
+                  {
+                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
+                     png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+                     png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
+
+                     if (r == trans_values->red && g == trans_values->green &&
+                        b == trans_values->blue)
+                     {
+                        *sp = (png_byte)((background->red >> 8) & 0xff);
+                        *(sp + 1) = (png_byte)(background->red & 0xff);
+                        *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
+                        *(sp + 3) = (png_byte)(background->green & 0xff);
+                        *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+                        *(sp + 5) = (png_byte)(background->blue & 0xff);
+                     }
+                  }
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_GRAY_ALPHA:
+         {
+            if (row_info->bit_depth == 8)
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
+                   gamma_table != NULL)
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 2, dp++)
+                  {
+                     png_uint_16 a = *(sp + 1);
+
+                     if (a == 0xff)
+                     {
+                        *dp = gamma_table[*sp];
+                     }
+                     else if (a == 0)
+                     {
+                        /* background is already in screen gamma */
+                        *dp = (png_byte)background->gray;
+                     }
+                     else
+                     {
+                        png_byte v, w;
+
+                        v = gamma_to_1[*sp];
+                        png_composite(w, v, a, background_1->gray);
+                        *dp = gamma_from_1[w];
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 2, dp++)
+                  {
+                     png_byte a = *(sp + 1);
+
+                     if (a == 0xff)
+                     {
+                        *dp = *sp;
+                     }
+                     else if (a == 0)
+                     {
+                        *dp = (png_byte)background->gray;
+                     }
+                     else
+                     {
+                        png_composite(*dp, *sp, a, background_1->gray);
+                     }
+                  }
+               }
+            }
+            else /* if (png_ptr->bit_depth == 16) */
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
+                   gamma_16_to_1 != NULL)
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
+                  {
+                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+
+                     if (a == (png_uint_16)0xffff)
+                     {
+                        png_uint_16 v;
+
+                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+                        *dp = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(v & 0xff);
+                     }
+                     else if (a == 0)
+                     {
+                        /* background is already in screen gamma */
+                        *dp = (png_byte)((background->gray >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(background->gray & 0xff);
+                     }
+                     else
+                     {
+                        png_uint_16 g, v, w;
+
+                        g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
+                        png_composite_16(v, g, a, background_1->gray);
+                        w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
+                        *dp = (png_byte)((w >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(w & 0xff);
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 2)
+                  {
+                     png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+                     if (a == (png_uint_16)0xffff)
+                     {
+                        png_memcpy(dp, sp, 2);
+                     }
+                     else if (a == 0)
+                     {
+                        *dp = (png_byte)((background->gray >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(background->gray & 0xff);
+                     }
+                     else
+                     {
+                        png_uint_16 g, v;
+
+                        g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+                        png_composite_16(v, g, a, background_1->gray);
+                        *dp = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(v & 0xff);
+                     }
+                  }
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_RGB_ALPHA:
+         {
+            if (row_info->bit_depth == 8)
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
+                   gamma_table != NULL)
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
+                  {
+                     png_byte a = *(sp + 3);
+
+                     if (a == 0xff)
+                     {
+                        *dp = gamma_table[*sp];
+                        *(dp + 1) = gamma_table[*(sp + 1)];
+                        *(dp + 2) = gamma_table[*(sp + 2)];
+                     }
+                     else if (a == 0)
+                     {
+                        /* background is already in screen gamma */
+                        *dp = (png_byte)background->red;
+                        *(dp + 1) = (png_byte)background->green;
+                        *(dp + 2) = (png_byte)background->blue;
+                     }
+                     else
+                     {
+                        png_byte v, w;
+
+                        v = gamma_to_1[*sp];
+                        png_composite(w, v, a, background_1->red);
+                        *dp = gamma_from_1[w];
+                        v = gamma_to_1[*(sp + 1)];
+                        png_composite(w, v, a, background_1->green);
+                        *(dp + 1) = gamma_from_1[w];
+                        v = gamma_to_1[*(sp + 2)];
+                        png_composite(w, v, a, background_1->blue);
+                        *(dp + 2) = gamma_from_1[w];
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 4, dp += 3)
+                  {
+                     png_byte a = *(sp + 3);
+
+                     if (a == 0xff)
+                     {
+                        *dp = *sp;
+                        *(dp + 1) = *(sp + 1);
+                        *(dp + 2) = *(sp + 2);
+                     }
+                     else if (a == 0)
+                     {
+                        *dp = (png_byte)background->red;
+                        *(dp + 1) = (png_byte)background->green;
+                        *(dp + 2) = (png_byte)background->blue;
+                     }
+                     else
+                     {
+                        png_composite(*dp, *sp, a, background->red);
+                        png_composite(*(dp + 1), *(sp + 1), a,
+                           background->green);
+                        png_composite(*(dp + 2), *(sp + 2), a,
+                           background->blue);
+                     }
+                  }
+               }
+            }
+            else /* if (row_info->bit_depth == 16) */
+            {
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+               if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
+                   gamma_16_to_1 != NULL)
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
+                  {
+                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
+                         << 8) + (png_uint_16)(*(sp + 7)));
+                     if (a == (png_uint_16)0xffff)
+                     {
+                        png_uint_16 v;
+
+                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+                        *dp = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(v & 0xff);
+                        v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
+                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(v & 0xff);
+                        v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
+                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(v & 0xff);
+                     }
+                     else if (a == 0)
+                     {
+                        /* background is already in screen gamma */
+                        *dp = (png_byte)((background->red >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(background->red & 0xff);
+                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(background->green & 0xff);
+                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(background->blue & 0xff);
+                     }
+                     else
+                     {
+                        png_uint_16 v, w, x;
+
+                        v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
+                        png_composite_16(w, v, a, background->red);
+                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+                        *dp = (png_byte)((x >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(x & 0xff);
+                        v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
+                        png_composite_16(w, v, a, background->green);
+                        x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+                        *(dp + 2) = (png_byte)((x >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(x & 0xff);
+                        v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
+                        png_composite_16(w, v, a, background->blue);
+                        x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
+                        *(dp + 4) = (png_byte)((x >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(x & 0xff);
+                     }
+                  }
+               }
+               else
+#endif
+               {
+                  sp = row;
+                  dp = row;
+                  for (i = 0; i < row_width; i++, sp += 8, dp += 6)
+                  {
+                     png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
+                        << 8) + (png_uint_16)(*(sp + 7)));
+                     if (a == (png_uint_16)0xffff)
+                     {
+                        png_memcpy(dp, sp, 6);
+                     }
+                     else if (a == 0)
+                     {
+                        *dp = (png_byte)((background->red >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(background->red & 0xff);
+                        *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(background->green & 0xff);
+                        *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(background->blue & 0xff);
+                     }
+                     else
+                     {
+                        png_uint_16 v;
+
+                        png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+                        png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
+                            + *(sp + 3));
+                        png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
+                            + *(sp + 5));
+
+                        png_composite_16(v, r, a, background->red);
+                        *dp = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 1) = (png_byte)(v & 0xff);
+                        png_composite_16(v, g, a, background->green);
+                        *(dp + 2) = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 3) = (png_byte)(v & 0xff);
+                        png_composite_16(v, b, a, background->blue);
+                        *(dp + 4) = (png_byte)((v >> 8) & 0xff);
+                        *(dp + 5) = (png_byte)(v & 0xff);
+                     }
+                  }
+               }
+            }
+            break;
+         }
+      }
+
+      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+      {
+         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
+         row_info->channels--;
+         row_info->pixel_depth = (png_byte)(row_info->channels *
+            row_info->bit_depth);
+         row_info->rowbytes = ((row_width *
+            row_info->pixel_depth + 7) >> 3);
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+/* Gamma correct the image, avoiding the alpha channel.  Make sure
+ * you do this after you deal with the transparency issue on grayscale
+ * or RGB images. If your bit depth is 8, use gamma_table, if it
+ * is 16, use gamma_16_table and gamma_shift.  Build these with
+ * build_gamma_table().
+ */
+void /* PRIVATE */
+png_do_gamma(png_row_infop row_info, png_bytep row,
+   png_bytep gamma_table, png_uint_16pp gamma_16_table,
+   int gamma_shift)
+{
+   png_bytep sp;
+   png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
+
+   png_debug(1, "in png_do_gamma\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
+        (row_info->bit_depth == 16 && gamma_16_table != NULL)))
+   {
+      switch (row_info->color_type)
+      {
+         case PNG_COLOR_TYPE_RGB:
+         {
+            if (row_info->bit_depth == 8)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  *sp = gamma_table[*sp];
+                  sp++;
+                  *sp = gamma_table[*sp];
+                  sp++;
+                  *sp = gamma_table[*sp];
+                  sp++;
+               }
+            }
+            else /* if (row_info->bit_depth == 16) */
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 v;
+
+                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_RGB_ALPHA:
+         {
+            if (row_info->bit_depth == 8)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  *sp = gamma_table[*sp];
+                  sp++;
+                  *sp = gamma_table[*sp];
+                  sp++;
+                  *sp = gamma_table[*sp];
+                  sp++;
+                  sp++;
+               }
+            }
+            else /* if (row_info->bit_depth == 16) */
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 4;
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_GRAY_ALPHA:
+         {
+            if (row_info->bit_depth == 8)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  *sp = gamma_table[*sp];
+                  sp += 2;
+               }
+            }
+            else /* if (row_info->bit_depth == 16) */
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 4;
+               }
+            }
+            break;
+         }
+         case PNG_COLOR_TYPE_GRAY:
+         {
+            if (row_info->bit_depth == 2)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i += 4)
+               {
+                  int a = *sp & 0xc0;
+                  int b = *sp & 0x30;
+                  int c = *sp & 0x0c;
+                  int d = *sp & 0x03;
+
+                  *sp = (png_byte)(
+                        ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
+                        ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
+                        ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
+                        ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
+                  sp++;
+               }
+            }
+            if (row_info->bit_depth == 4)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i += 2)
+               {
+                  int msb = *sp & 0xf0;
+                  int lsb = *sp & 0x0f;
+
+                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
+                          | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
+                  sp++;
+               }
+            }
+            else if (row_info->bit_depth == 8)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  *sp = gamma_table[*sp];
+                  sp++;
+               }
+            }
+            else if (row_info->bit_depth == 16)
+            {
+               sp = row;
+               for (i = 0; i < row_width; i++)
+               {
+                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+                  *sp = (png_byte)((v >> 8) & 0xff);
+                  *(sp + 1) = (png_byte)(v & 0xff);
+                  sp += 2;
+               }
+            }
+            break;
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+/* Expands a palette row to an RGB or RGBA row depending
+ * upon whether you supply trans and num_trans.
+ */
+void /* PRIVATE */
+png_do_expand_palette(png_row_infop row_info, png_bytep row,
+   png_colorp palette, png_bytep trans, int num_trans)
+{
+   int shift, value;
+   png_bytep sp, dp;
+   png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
+
+   png_debug(1, "in png_do_expand_palette\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       row_info->color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (row_info->bit_depth < 8)
+      {
+         switch (row_info->bit_depth)
+         {
+            case 1:
+            {
+               sp = row + (png_size_t)((row_width - 1) >> 3);
+               dp = row + (png_size_t)row_width - 1;
+               shift = 7 - (int)((row_width + 7) & 0x07);
+               for (i = 0; i < row_width; i++)
+               {
+                  if ((*sp >> shift) & 0x01)
+                     *dp = 1;
+                  else
+                     *dp = 0;
+                  if (shift == 7)
+                  {
+                     shift = 0;
+                     sp--;
+                  }
+                  else
+                     shift++;
+
+                  dp--;
+               }
+               break;
+            }
+            case 2:
+            {
+               sp = row + (png_size_t)((row_width - 1) >> 2);
+               dp = row + (png_size_t)row_width - 1;
+               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
+               for (i = 0; i < row_width; i++)
+               {
+                  value = (*sp >> shift) & 0x03;
+                  *dp = (png_byte)value;
+                  if (shift == 6)
+                  {
+                     shift = 0;
+                     sp--;
+                  }
+                  else
+                     shift += 2;
+
+                  dp--;
+               }
+               break;
+            }
+            case 4:
+            {
+               sp = row + (png_size_t)((row_width - 1) >> 1);
+               dp = row + (png_size_t)row_width - 1;
+               shift = (int)((row_width & 0x01) << 2);
+               for (i = 0; i < row_width; i++)
+               {
+                  value = (*sp >> shift) & 0x0f;
+                  *dp = (png_byte)value;
+                  if (shift == 4)
+                  {
+                     shift = 0;
+                     sp--;
+                  }
+                  else
+                     shift += 4;
+
+                  dp--;
+               }
+               break;
+            }
+         }
+         row_info->bit_depth = 8;
+         row_info->pixel_depth = 8;
+         row_info->rowbytes = row_width;
+      }
+      switch (row_info->bit_depth)
+      {
+         case 8:
+         {
+            if (trans != NULL)
+            {
+               sp = row + (png_size_t)row_width - 1;
+               dp = row + (png_size_t)(row_width << 2) - 1;
+
+               for (i = 0; i < row_width; i++)
+               {
+                  if ((int)(*sp) >= num_trans)
+                     *dp-- = 0xff;
+                  else
+                     *dp-- = trans[*sp];
+                  *dp-- = palette[*sp].blue;
+                  *dp-- = palette[*sp].green;
+                  *dp-- = palette[*sp].red;
+                  sp--;
+               }
+               row_info->bit_depth = 8;
+               row_info->pixel_depth = 32;
+               row_info->rowbytes = row_width * 4;
+               row_info->color_type = 6;
+               row_info->channels = 4;
+            }
+            else
+            {
+               sp = row + (png_size_t)row_width - 1;
+               dp = row + (png_size_t)(row_width * 3) - 1;
+
+               for (i = 0; i < row_width; i++)
+               {
+                  *dp-- = palette[*sp].blue;
+                  *dp-- = palette[*sp].green;
+                  *dp-- = palette[*sp].red;
+                  sp--;
+               }
+               row_info->bit_depth = 8;
+               row_info->pixel_depth = 24;
+               row_info->rowbytes = row_width * 3;
+               row_info->color_type = 2;
+               row_info->channels = 3;
+            }
+            break;
+         }
+      }
+   }
+}
+
+/* If the bit depth < 8, it is expanded to 8.  Also, if the
+ * transparency value is supplied, an alpha channel is built.
+ */
+void /* PRIVATE */
+png_do_expand(png_row_infop row_info, png_bytep row,
+   png_color_16p trans_value)
+{
+   int shift, value;
+   png_bytep sp, dp;
+   png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
+
+   png_debug(1, "in png_do_expand\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
+      {
+         png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
+
+         if (row_info->bit_depth < 8)
+         {
+            switch (row_info->bit_depth)
+            {
+               case 1:
+               {
+                  gray = (png_uint_16)(gray*0xff);
+                  sp = row + (png_size_t)((row_width - 1) >> 3);
+                  dp = row + (png_size_t)row_width - 1;
+                  shift = 7 - (int)((row_width + 7) & 0x07);
+                  for (i = 0; i < row_width; i++)
+                  {
+                     if ((*sp >> shift) & 0x01)
+                        *dp = 0xff;
+                     else
+                        *dp = 0;
+                     if (shift == 7)
+                     {
+                        shift = 0;
+                        sp--;
+                     }
+                     else
+                        shift++;
+
+                     dp--;
+                  }
+                  break;
+               }
+               case 2:
+               {
+                  gray = (png_uint_16)(gray*0x55);
+                  sp = row + (png_size_t)((row_width - 1) >> 2);
+                  dp = row + (png_size_t)row_width - 1;
+                  shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
+                  for (i = 0; i < row_width; i++)
+                  {
+                     value = (*sp >> shift) & 0x03;
+                     *dp = (png_byte)(value | (value << 2) | (value << 4) |
+                        (value << 6));
+                     if (shift == 6)
+                     {
+                        shift = 0;
+                        sp--;
+                     }
+                     else
+                        shift += 2;
+
+                     dp--;
+                  }
+                  break;
+               }
+               case 4:
+               {
+                  gray = (png_uint_16)(gray*0x11);
+                  sp = row + (png_size_t)((row_width - 1) >> 1);
+                  dp = row + (png_size_t)row_width - 1;
+                  shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
+                  for (i = 0; i < row_width; i++)
+                  {
+                     value = (*sp >> shift) & 0x0f;
+                     *dp = (png_byte)(value | (value << 4));
+                     if (shift == 4)
+                     {
+                        shift = 0;
+                        sp--;
+                     }
+                     else
+                        shift = 4;
+
+                     dp--;
+                  }
+                  break;
+               }
+            }
+            row_info->bit_depth = 8;
+            row_info->pixel_depth = 8;
+            row_info->rowbytes = row_width;
+         }
+
+         if (trans_value != NULL)
+         {
+            if (row_info->bit_depth == 8)
+            {
+               sp = row + (png_size_t)row_width - 1;
+               dp = row + (png_size_t)(row_width << 1) - 1;
+               for (i = 0; i < row_width; i++)
+               {
+                  if (*sp == gray)
+                     *dp-- = 0;
+                  else
+                     *dp-- = 0xff;
+                  *dp-- = *sp--;
+               }
+            }
+            else if (row_info->bit_depth == 16)
+            {
+               sp = row + row_info->rowbytes - 1;
+               dp = row + (row_info->rowbytes << 1) - 1;
+               for (i = 0; i < row_width; i++)
+               {
+                  if (((png_uint_16)*(sp) |
+                     ((png_uint_16)*(sp - 1) << 8)) == gray)
+                  {
+                     *dp-- = 0;
+                     *dp-- = 0;
+                  }
+                  else
+                  {
+                     *dp-- = 0xff;
+                     *dp-- = 0xff;
+                  }
+                  *dp-- = *sp--;
+                  *dp-- = *sp--;
+               }
+            }
+            row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
+            row_info->channels = 2;
+            row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
+            row_info->rowbytes =
+               ((row_width * row_info->pixel_depth) >> 3);
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
+      {
+         if (row_info->bit_depth == 8)
+         {
+            sp = row + (png_size_t)row_info->rowbytes - 1;
+            dp = row + (png_size_t)(row_width << 2) - 1;
+            for (i = 0; i < row_width; i++)
+            {
+               if (*(sp - 2) == trans_value->red &&
+                  *(sp - 1) == trans_value->green &&
+                  *(sp - 0) == trans_value->blue)
+                  *dp-- = 0;
+               else
+                  *dp-- = 0xff;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+            }
+         }
+         else if (row_info->bit_depth == 16)
+         {
+            sp = row + row_info->rowbytes - 1;
+            dp = row + (png_size_t)(row_width << 3) - 1;
+            for (i = 0; i < row_width; i++)
+            {
+               if ((((png_uint_16)*(sp - 4) |
+                  ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
+                  (((png_uint_16)*(sp - 2) |
+                  ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
+                  (((png_uint_16)*(sp - 0) |
+                  ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
+               {
+                  *dp-- = 0;
+                  *dp-- = 0;
+               }
+               else
+               {
+                  *dp-- = 0xff;
+                  *dp-- = 0xff;
+               }
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+               *dp-- = *sp--;
+            }
+         }
+         row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+         row_info->channels = 4;
+         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
+         row_info->rowbytes =
+            ((row_width * row_info->pixel_depth) >> 3);
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED)
+void /* PRIVATE */
+png_do_dither(png_row_infop row_info, png_bytep row,
+    png_bytep palette_lookup, png_bytep dither_lookup)
+{
+   png_bytep sp, dp;
+   png_uint_32 i;
+   png_uint_32 row_width=row_info->width;
+
+   png_debug(1, "in png_do_dither\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
+         palette_lookup && row_info->bit_depth == 8)
+      {
+         int r, g, b, p;
+         sp = row;
+         dp = row;
+         for (i = 0; i < row_width; i++)
+         {
+            r = *sp++;
+            g = *sp++;
+            b = *sp++;
+
+            /* this looks real messy, but the compiler will reduce
+               it down to a reasonable formula.  For example, with
+               5 bits per color, we get:
+               p = (((r >> 3) & 0x1f) << 10) |
+                  (((g >> 3) & 0x1f) << 5) |
+                  ((b >> 3) & 0x1f);
+               */
+            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
+               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
+               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
+               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
+               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
+               (PNG_DITHER_BLUE_BITS)) |
+               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
+               ((1 << PNG_DITHER_BLUE_BITS) - 1));
+
+            *dp++ = palette_lookup[p];
+         }
+         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
+         row_info->channels = 1;
+         row_info->pixel_depth = row_info->bit_depth;
+         row_info->rowbytes =
+             ((row_width * row_info->pixel_depth + 7) >> 3);
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
+         palette_lookup != NULL && row_info->bit_depth == 8)
+      {
+         int r, g, b, p;
+         sp = row;
+         dp = row;
+         for (i = 0; i < row_width; i++)
+         {
+            r = *sp++;
+            g = *sp++;
+            b = *sp++;
+            sp++;
+
+            p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
+               ((1 << PNG_DITHER_RED_BITS) - 1)) <<
+               (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
+               (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
+               ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
+               (PNG_DITHER_BLUE_BITS)) |
+               ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
+               ((1 << PNG_DITHER_BLUE_BITS) - 1));
+
+            *dp++ = palette_lookup[p];
+         }
+         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
+         row_info->channels = 1;
+         row_info->pixel_depth = row_info->bit_depth;
+         row_info->rowbytes =
+            ((row_width * row_info->pixel_depth + 7) >> 3);
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
+         dither_lookup && row_info->bit_depth == 8)
+      {
+         sp = row;
+         for (i = 0; i < row_width; i++, sp++)
+         {
+            *sp = dither_lookup[*sp];
+         }
+      }
+   }
+}
+#endif
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+#if defined(PNG_READ_GAMMA_SUPPORTED)
+static int png_gamma_shift[] =
+   {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
+
+/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
+ * tables, we don't make a full table if we are reducing to 8-bit in
+ * the future.  Note also how the gamma_16 tables are segmented so that
+ * we don't need to allocate > 64K chunks for a full 16-bit table.
+ */
+void /* PRIVATE */
+png_build_gamma_table(png_structp png_ptr)
+{
+  png_debug(1, "in png_build_gamma_table\n");
+  if(png_ptr->gamma != 0.0)
+  {
+   if (png_ptr->bit_depth <= 8)
+   {
+      int i;
+      double g;
+
+      if (png_ptr->screen_gamma > .000001)
+         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+      else
+         g = 1.0;
+
+      png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
+         (png_uint_32)256);
+
+      for (i = 0; i < 256; i++)
+      {
+         png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
+            g) * 255.0 + .5);
+      }
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+      if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
+      {
+
+         g = 1.0 / (png_ptr->gamma);
+
+         png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
+            (png_uint_32)256);
+
+         for (i = 0; i < 256; i++)
+         {
+            png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
+               g) * 255.0 + .5);
+         }
+
+
+         png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
+            (png_uint_32)256);
+
+         if(png_ptr->screen_gamma > 0.000001)
+            g = 1.0 / png_ptr->screen_gamma;
+         else
+            g = png_ptr->gamma;   /* probably doing rgb_to_gray */
+
+         for (i = 0; i < 256; i++)
+         {
+            png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
+               g) * 255.0 + .5);
+
+         }
+      }
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
+   }
+   else
+   {
+      double g;
+      int i, j, shift, num;
+      int sig_bit;
+      png_uint_32 ig;
+
+      if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+      {
+         sig_bit = (int)png_ptr->sig_bit.red;
+         if ((int)png_ptr->sig_bit.green > sig_bit)
+            sig_bit = png_ptr->sig_bit.green;
+         if ((int)png_ptr->sig_bit.blue > sig_bit)
+            sig_bit = png_ptr->sig_bit.blue;
+      }
+      else
+      {
+         sig_bit = (int)png_ptr->sig_bit.gray;
+      }
+
+      if (sig_bit > 0)
+         shift = 16 - sig_bit;
+      else
+         shift = 0;
+
+      if (png_ptr->transformations & PNG_16_TO_8)
+      {
+         if (shift < (16 - PNG_MAX_GAMMA_8))
+            shift = (16 - PNG_MAX_GAMMA_8);
+      }
+
+      if (shift > 8)
+         shift = 8;
+      if (shift < 0)
+         shift = 0;
+
+      png_ptr->gamma_shift = (png_byte)shift;
+
+      num = (1 << (8 - shift));
+
+      if (png_ptr->screen_gamma > .000001)
+         g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+      else
+         g = 1.0;
+
+      png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
+         (png_uint_32)(num * sizeof (png_uint_16p)));
+
+      if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
+      {
+         double fin, fout;
+         png_uint_32 last, max;
+
+         for (i = 0; i < num; i++)
+         {
+            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
+               (png_uint_32)(256 * sizeof (png_uint_16)));
+         }
+
+         g = 1.0 / g;
+         last = 0;
+         for (i = 0; i < 256; i++)
+         {
+            fout = ((double)i + 0.5) / 256.0;
+            fin = pow(fout, g);
+            max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
+            while (last <= max)
+            {
+               png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
+                  [(int)(last >> (8 - shift))] = (png_uint_16)(
+                  (png_uint_16)i | ((png_uint_16)i << 8));
+               last++;
+            }
+         }
+         while (last < ((png_uint_32)num << 8))
+         {
+            png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
+               [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
+            last++;
+         }
+      }
+      else
+      {
+         for (i = 0; i < num; i++)
+         {
+            png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
+               (png_uint_32)(256 * sizeof (png_uint_16)));
+
+            ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
+            for (j = 0; j < 256; j++)
+            {
+               png_ptr->gamma_16_table[i][j] =
+                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
+                     65535.0, g) * 65535.0 + .5);
+            }
+         }
+      }
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+      if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
+      {
+
+         g = 1.0 / (png_ptr->gamma);
+
+         png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
+            (png_uint_32)(num * sizeof (png_uint_16p )));
+
+         for (i = 0; i < num; i++)
+         {
+            png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
+               (png_uint_32)(256 * sizeof (png_uint_16)));
+
+            ig = (((png_uint_32)i *
+               (png_uint_32)png_gamma_shift[shift]) >> 4);
+            for (j = 0; j < 256; j++)
+            {
+               png_ptr->gamma_16_to_1[i][j] =
+                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
+                     65535.0, g) * 65535.0 + .5);
+            }
+         }
+
+         if(png_ptr->screen_gamma > 0.000001)
+            g = 1.0 / png_ptr->screen_gamma;
+         else
+            g = png_ptr->gamma;   /* probably doing rgb_to_gray */
+
+         png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
+            (png_uint_32)(num * sizeof (png_uint_16p)));
+
+         for (i = 0; i < num; i++)
+         {
+            png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
+               (png_uint_32)(256 * sizeof (png_uint_16)));
+
+            ig = (((png_uint_32)i *
+               (png_uint_32)png_gamma_shift[shift]) >> 4);
+            for (j = 0; j < 256; j++)
+            {
+               png_ptr->gamma_16_from_1[i][j] =
+                  (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
+                     65535.0, g) * 65535.0 + .5);
+            }
+         }
+      }
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
+   }
+ }
+}
+#endif
+/* To do: install integer version of png_build_gamma_table here */
+#endif
+
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+/* undoes intrapixel differencing  */
+void /* PRIVATE */
+png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_read_intrapixel\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       (row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      int bytes_per_pixel;
+      png_uint_32 row_width = row_info->width;
+      if (row_info->bit_depth == 8)
+      {
+         png_bytep rp;
+         png_uint_32 i;
+
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+            bytes_per_pixel = 3;
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+            bytes_per_pixel = 4;
+         else
+            return;
+
+         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+         {
+            *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
+            *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
+         }
+      }
+      else if (row_info->bit_depth == 16)
+      {
+         png_bytep rp;
+         png_uint_32 i;
+
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+            bytes_per_pixel = 6;
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+            bytes_per_pixel = 8;
+         else
+            return;
+
+         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+         {
+            png_uint_32 s0=*(rp  )<<8 | *(rp+1);
+            png_uint_32 s1=*(rp+2)<<8 | *(rp+3);
+            png_uint_32 s2=*(rp+4)<<8 | *(rp+5);
+            png_uint_32 red=(65536+s0+s1)&0xffff;
+            png_uint_32 blue=(65536+s2+s1)&0xffff;
+            *(rp  ) = (png_byte)((red>>8)&0xff);
+            *(rp+1) = (png_byte)(red&0xff);
+            *(rp+4) = (png_byte)((blue>>8)&0xff);
+            *(rp+5) = (png_byte)(blue&0xff);
+         }
+      }
+   }
+}
+#endif /* PNG_MNG_FEATURES_SUPPORTED */
diff --git a/libraries/libpng-1.2.0/pngrutil.c b/libraries/libpng-1.2.0/pngrutil.c
new file mode 100644 (file)
index 0000000..1977783
--- /dev/null
@@ -0,0 +1,3001 @@
+
+/* pngrutil.c - utilities to read a PNG file
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file contains routines that are only called from within
+ * libpng itself during the course of reading an image.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(_WIN32_WCE)
+/* strtod() function is not supported on WindowsCE */
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+__inline double strtod(const char *nptr, char **endptr)
+{
+   double result = 0;
+   int len;
+   wchar_t *str, *end;
+
+   len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
+   str = (wchar_t *)malloc(len * sizeof(wchar_t));
+   if ( NULL != str )
+   {
+      MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
+      result = wcstod(str, &end);
+      len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
+      *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
+      free(str);
+   }
+   return result;
+}
+#  endif
+#endif
+
+#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
+/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
+png_uint_32 /* PRIVATE */
+png_get_uint_32(png_bytep buf)
+{
+   png_uint_32 i = ((png_uint_32)(*buf) << 24) +
+      ((png_uint_32)(*(buf + 1)) << 16) +
+      ((png_uint_32)(*(buf + 2)) << 8) +
+      (png_uint_32)(*(buf + 3));
+
+   return (i);
+}
+
+#if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED)
+/* Grab a signed 32-bit integer from a buffer in big-endian format.  The
+ * data is stored in the PNG file in two's complement format, and it is
+ * assumed that the machine format for signed integers is the same. */
+png_int_32 /* PRIVATE */
+png_get_int_32(png_bytep buf)
+{
+   png_int_32 i = ((png_int_32)(*buf) << 24) +
+      ((png_int_32)(*(buf + 1)) << 16) +
+      ((png_int_32)(*(buf + 2)) << 8) +
+      (png_int_32)(*(buf + 3));
+
+   return (i);
+}
+#endif /* PNG_READ_pCAL_SUPPORTED */
+
+/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
+png_uint_16 /* PRIVATE */
+png_get_uint_16(png_bytep buf)
+{
+   png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
+      (png_uint_16)(*(buf + 1)));
+
+   return (i);
+}
+#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
+
+/* Read data, and (optionally) run it through the CRC. */
+void /* PRIVATE */
+png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
+{
+   png_read_data(png_ptr, buf, length);
+   png_calculate_crc(png_ptr, buf, length);
+}
+
+/* Optionally skip data and then check the CRC.  Depending on whether we
+   are reading a ancillary or critical chunk, and how the program has set
+   things up, we may calculate the CRC on the data and print a message.
+   Returns '1' if there was a CRC error, '0' otherwise. */
+int /* PRIVATE */
+png_crc_finish(png_structp png_ptr, png_uint_32 skip)
+{
+   png_size_t i;
+   png_size_t istop = png_ptr->zbuf_size;
+
+   for (i = (png_size_t)skip; i > istop; i -= istop)
+   {
+      png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
+   }
+   if (i)
+   {
+      png_crc_read(png_ptr, png_ptr->zbuf, i);
+   }
+
+   if (png_crc_error(png_ptr))
+   {
+      if (((png_ptr->chunk_name[0] & 0x20) &&                /* Ancillary */
+           !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
+          (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
+          (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
+      {
+         png_chunk_warning(png_ptr, "CRC error");
+      }
+      else
+      {
+         png_chunk_error(png_ptr, "CRC error");
+      }
+      return (1);
+   }
+
+   return (0);
+}
+
+/* Compare the CRC stored in the PNG file with that calculated by libpng from
+   the data it has read thus far. */
+int /* PRIVATE */
+png_crc_error(png_structp png_ptr)
+{
+   png_byte crc_bytes[4];
+   png_uint_32 crc;
+   int need_crc = 1;
+
+   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
+   {
+      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
+          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
+         need_crc = 0;
+   }
+   else                                                    /* critical */
+   {
+      if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+         need_crc = 0;
+   }
+
+   png_read_data(png_ptr, crc_bytes, 4);
+
+   if (need_crc)
+   {
+      crc = png_get_uint_32(crc_bytes);
+      return ((int)(crc != png_ptr->crc));
+   }
+   else
+      return (0);
+}
+
+#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
+    defined(PNG_READ_iCCP_SUPPORTED)
+/*
+ * Decompress trailing data in a chunk.  The assumption is that chunkdata
+ * points at an allocated area holding the contents of a chunk with a
+ * trailing compressed part.  What we get back is an allocated area
+ * holding the original prefix part and an uncompressed version of the
+ * trailing part (the malloc area passed in is freed).
+ */
+png_charp /* PRIVATE */
+png_decompress_chunk(png_structp png_ptr, int comp_type,
+                              png_charp chunkdata, png_size_t chunklength,
+                              png_size_t prefix_size, png_size_t *newlength)
+{
+   static char msg[] = "Error decoding compressed text";
+   png_charp text = NULL;
+   png_size_t text_size;
+
+   if (comp_type == PNG_COMPRESSION_TYPE_BASE)
+   {
+      int ret = Z_OK;
+      png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
+      png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
+      png_ptr->zstream.next_out = png_ptr->zbuf;
+      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+      text_size = 0;
+      text = NULL;
+
+      while (png_ptr->zstream.avail_in)
+      {
+         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+         if (ret != Z_OK && ret != Z_STREAM_END)
+         {
+            if (png_ptr->zstream.msg != NULL)
+               png_warning(png_ptr, png_ptr->zstream.msg);
+            else
+               png_warning(png_ptr, msg);
+            inflateReset(&png_ptr->zstream);
+            png_ptr->zstream.avail_in = 0;
+
+            if (text ==  NULL)
+            {
+               text_size = prefix_size + sizeof(msg) + 1;
+               text = (png_charp)png_malloc(png_ptr, text_size);
+               png_memcpy(text, chunkdata, prefix_size);
+            }
+
+            text[text_size - 1] = 0x00;
+
+            /* Copy what we can of the error message into the text chunk */
+            text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
+            text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
+            png_memcpy(text + prefix_size, msg, text_size + 1);
+            break;
+         }
+         if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
+         {
+            if (text == NULL)
+            {
+               text_size = prefix_size +
+                   png_ptr->zbuf_size - png_ptr->zstream.avail_out;
+               text = (png_charp)png_malloc(png_ptr, text_size + 1);
+               png_memcpy(text + prefix_size, png_ptr->zbuf,
+                    text_size - prefix_size);
+               png_memcpy(text, chunkdata, prefix_size);
+               *(text + text_size) = 0x00;
+            }
+            else
+            {
+               png_charp tmp;
+
+               tmp = text;
+               text = (png_charp)png_malloc(png_ptr, (png_uint_32)(text_size +
+                  png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
+               png_memcpy(text, tmp, text_size);
+               png_free(png_ptr, tmp);
+               png_memcpy(text + text_size, png_ptr->zbuf,
+                  (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
+               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
+               *(text + text_size) = 0x00;
+            }
+            if (ret == Z_STREAM_END)
+               break;
+            else
+            {
+               png_ptr->zstream.next_out = png_ptr->zbuf;
+               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+            }
+         }
+      }
+      if (ret != Z_STREAM_END)
+      {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+         char umsg[50];
+
+         if (ret == Z_BUF_ERROR)
+            sprintf(umsg,"Buffer error in compressed datastream in %s chunk",
+                png_ptr->chunk_name);
+         else if (ret == Z_DATA_ERROR)
+            sprintf(umsg,"Data error in compressed datastream in %s chunk",
+                png_ptr->chunk_name);
+         else
+            sprintf(umsg,"Incomplete compressed datastream in %s chunk",
+                png_ptr->chunk_name);
+         png_warning(png_ptr, umsg);
+#else
+         png_warning(png_ptr,
+            "Incomplete compressed datastream in chunk other than IDAT");
+#endif
+         text_size=prefix_size;
+         if (text ==  NULL)
+         {
+            text = (png_charp)png_malloc(png_ptr, text_size+1);
+            png_memcpy(text, chunkdata, prefix_size);
+         }
+         *(text + text_size) = 0x00;
+      }
+
+      inflateReset(&png_ptr->zstream);
+      png_ptr->zstream.avail_in = 0;
+
+      png_free(png_ptr, chunkdata);
+      chunkdata = text;
+      *newlength=text_size;
+   }
+   else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
+   {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+      char umsg[50];
+
+      sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
+      png_warning(png_ptr, umsg);
+#else
+      png_warning(png_ptr, "Unknown zTXt compression type");
+#endif
+
+      *(chunkdata + prefix_size) = 0x00;
+      *newlength=prefix_size;
+   }
+
+   return chunkdata;
+}
+#endif
+
+/* read and check the IDHR chunk */
+void /* PRIVATE */
+png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte buf[13];
+   png_uint_32 width, height;
+   int bit_depth, color_type, compression_type, filter_type;
+   int interlace_type;
+
+   png_debug(1, "in png_handle_IHDR\n");
+
+   if (png_ptr->mode & PNG_HAVE_IHDR)
+      png_error(png_ptr, "Out of place IHDR");
+
+   /* check the length */
+   if (length != 13)
+      png_error(png_ptr, "Invalid IHDR chunk");
+
+   png_ptr->mode |= PNG_HAVE_IHDR;
+
+   png_crc_read(png_ptr, buf, 13);
+   png_crc_finish(png_ptr, 0);
+
+   width = png_get_uint_32(buf);
+   height = png_get_uint_32(buf + 4);
+   bit_depth = buf[8];
+   color_type = buf[9];
+   compression_type = buf[10];
+   filter_type = buf[11];
+   interlace_type = buf[12];
+
+
+   /* set internal variables */
+   png_ptr->width = width;
+   png_ptr->height = height;
+   png_ptr->bit_depth = (png_byte)bit_depth;
+   png_ptr->interlaced = (png_byte)interlace_type;
+   png_ptr->color_type = (png_byte)color_type;
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   png_ptr->filter_type = (png_byte)filter_type;
+#endif
+
+   /* find number of channels */
+   switch (png_ptr->color_type)
+   {
+      case PNG_COLOR_TYPE_GRAY:
+      case PNG_COLOR_TYPE_PALETTE:
+         png_ptr->channels = 1;
+         break;
+      case PNG_COLOR_TYPE_RGB:
+         png_ptr->channels = 3;
+         break;
+      case PNG_COLOR_TYPE_GRAY_ALPHA:
+         png_ptr->channels = 2;
+         break;
+      case PNG_COLOR_TYPE_RGB_ALPHA:
+         png_ptr->channels = 4;
+         break;
+   }
+
+   /* set up other useful info */
+   png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
+   png_ptr->channels);
+   png_ptr->rowbytes = ((png_ptr->width *
+      (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
+   png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
+   png_debug1(3,"channels = %d\n", png_ptr->channels);
+   png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
+   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
+      color_type, interlace_type, compression_type, filter_type);
+}
+
+/* read and check the palette */
+void /* PRIVATE */
+png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_color palette[PNG_MAX_PALETTE_LENGTH];
+   int num, i;
+#ifndef PNG_NO_POINTER_INDEXING
+   png_colorp pal_ptr;
+#endif
+
+   png_debug(1, "in png_handle_PLTE\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before PLTE");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid PLTE after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (png_ptr->mode & PNG_HAVE_PLTE)
+      png_error(png_ptr, "Duplicate PLTE chunk");
+
+   png_ptr->mode |= PNG_HAVE_PLTE;
+
+   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+   {
+      png_warning(png_ptr,
+        "Ignoring PLTE chunk in grayscale PNG");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
+   if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+   {
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+#endif
+
+   if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
+   {
+      if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+      {
+         png_warning(png_ptr, "Invalid palette chunk");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+      else
+      {
+         png_error(png_ptr, "Invalid palette chunk");
+      }
+   }
+
+   num = (int)length / 3;
+
+#ifndef PNG_NO_POINTER_INDEXING
+   for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
+   {
+      png_byte buf[3];
+
+      png_crc_read(png_ptr, buf, 3);
+      pal_ptr->red = buf[0];
+      pal_ptr->green = buf[1];
+      pal_ptr->blue = buf[2];
+   }
+#else
+   for (i = 0; i < num; i++)
+   {
+      png_byte buf[3];
+
+      png_crc_read(png_ptr, buf, 3);
+      /* don't depend upon png_color being any order */
+      palette[i].red = buf[0];
+      palette[i].green = buf[1];
+      palette[i].blue = buf[2];
+   }
+#endif
+
+   /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
+      whatever the normal CRC configuration tells us.  However, if we
+      have an RGB image, the PLTE can be considered ancillary, so
+      we will act as though it is. */
+#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+#endif
+   {
+      png_crc_finish(png_ptr, 0);
+   }
+#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
+   else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
+   {
+      /* If we don't want to use the data from an ancillary chunk,
+         we have two options: an error abort, or a warning and we
+         ignore the data in this chunk (which should be OK, since
+         it's considered ancillary for a RGB or RGBA image). */
+      if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
+      {
+         if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
+         {
+            png_chunk_error(png_ptr, "CRC error");
+         }
+         else
+         {
+            png_chunk_warning(png_ptr, "CRC error");
+            return;
+         }
+      }
+      /* Otherwise, we (optionally) emit a warning and use the chunk. */
+      else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
+      {
+         png_chunk_warning(png_ptr, "CRC error");
+      }
+   }
+#endif
+
+   png_set_PLTE(png_ptr, info_ptr, palette, num);
+
+#if defined(PNG_READ_tRNS_SUPPORTED)
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+      {
+         if (png_ptr->num_trans > (png_uint_16)num)
+         {
+            png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
+            png_ptr->num_trans = (png_uint_16)num;
+         }
+         if (info_ptr->num_trans > (png_uint_16)num)
+         {
+            png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
+            info_ptr->num_trans = (png_uint_16)num;
+         }
+      }
+   }
+#endif
+
+}
+
+void /* PRIVATE */
+png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_debug(1, "in png_handle_IEND\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
+   {
+      png_error(png_ptr, "No image in file");
+
+      info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
+   }
+
+   png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
+
+   if (length != 0)
+   {
+      png_warning(png_ptr, "Incorrect IEND chunk length");
+   }
+   png_crc_finish(png_ptr, length);
+}
+
+#if defined(PNG_READ_gAMA_SUPPORTED)
+void /* PRIVATE */
+png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_fixed_point igamma;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float file_gamma;
+#endif
+   png_byte buf[4];
+
+   png_debug(1, "in png_handle_gAMA\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before gAMA");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid gAMA after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (png_ptr->mode & PNG_HAVE_PLTE)
+      /* Should be an error, but we can cope with it */
+      png_warning(png_ptr, "Out of place gAMA chunk");
+
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      && !(info_ptr->valid & PNG_INFO_sRGB)
+#endif
+      )
+   {
+      png_warning(png_ptr, "Duplicate gAMA chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (length != 4)
+   {
+      png_warning(png_ptr, "Incorrect gAMA chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 4);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   igamma = (png_fixed_point)png_get_uint_32(buf);
+   /* check for zero gamma */
+   if (igamma == 0)
+      {
+         png_warning(png_ptr,
+           "Ignoring gAMA chunk with gamma=0");
+         return;
+      }
+
+#if defined(PNG_READ_sRGB_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sRGB)
+      if(igamma < 45000L || igamma > 46000L)
+      {
+         png_warning(png_ptr,
+           "Ignoring incorrect gAMA value when sRGB is also present");
+#ifndef PNG_NO_CONSOLE_IO
+         fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
+#endif
+         return;
+      }
+#endif /* PNG_READ_sRGB_SUPPORTED */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   file_gamma = (float)igamma / (float)100000.0;
+#  ifdef PNG_READ_GAMMA_SUPPORTED
+     png_ptr->gamma = file_gamma;
+#  endif
+     png_set_gAMA(png_ptr, info_ptr, file_gamma);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
+#endif
+}
+#endif
+
+#if defined(PNG_READ_sBIT_SUPPORTED)
+void /* PRIVATE */
+png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_size_t truelen;
+   png_byte buf[4];
+
+   png_debug(1, "in png_handle_sBIT\n");
+
+   buf[0] = buf[1] = buf[2] = buf[3] = 0;
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before sBIT");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid sBIT after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (png_ptr->mode & PNG_HAVE_PLTE)
+   {
+      /* Should be an error, but we can cope with it */
+      png_warning(png_ptr, "Out of place sBIT chunk");
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
+   {
+      png_warning(png_ptr, "Duplicate sBIT chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      truelen = 3;
+   else
+      truelen = (png_size_t)png_ptr->channels;
+
+   if (length != truelen)
+   {
+      png_warning(png_ptr, "Incorrect sBIT chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, truelen);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+   {
+      png_ptr->sig_bit.red = buf[0];
+      png_ptr->sig_bit.green = buf[1];
+      png_ptr->sig_bit.blue = buf[2];
+      png_ptr->sig_bit.alpha = buf[3];
+   }
+   else
+   {
+      png_ptr->sig_bit.gray = buf[0];
+      png_ptr->sig_bit.red = buf[0];
+      png_ptr->sig_bit.green = buf[0];
+      png_ptr->sig_bit.blue = buf[0];
+      png_ptr->sig_bit.alpha = buf[1];
+   }
+   png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
+}
+#endif
+
+#if defined(PNG_READ_cHRM_SUPPORTED)
+void /* PRIVATE */
+png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte buf[4];
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
+#endif
+   png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
+      int_y_green, int_x_blue, int_y_blue;
+
+   png_debug(1, "in png_handle_cHRM\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before cHRM");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid cHRM after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (png_ptr->mode & PNG_HAVE_PLTE)
+      /* Should be an error, but we can cope with it */
+      png_warning(png_ptr, "Missing PLTE before cHRM");
+
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
+#if defined(PNG_READ_sRGB_SUPPORTED)
+      && !(info_ptr->valid & PNG_INFO_sRGB)
+#endif
+      )
+   {
+      png_warning(png_ptr, "Duplicate cHRM chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (length != 32)
+   {
+      png_warning(png_ptr, "Incorrect cHRM chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 4);
+   int_x_white = (png_fixed_point)png_get_uint_32(buf);
+
+   png_crc_read(png_ptr, buf, 4);
+   int_y_white = (png_fixed_point)png_get_uint_32(buf);
+
+   if (int_x_white > 80000L || int_y_white > 80000L ||
+      int_x_white + int_y_white > 100000L)
+   {
+      png_warning(png_ptr, "Invalid cHRM white point");
+      png_crc_finish(png_ptr, 24);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 4);
+   int_x_red = (png_fixed_point)png_get_uint_32(buf);
+
+   png_crc_read(png_ptr, buf, 4);
+   int_y_red = (png_fixed_point)png_get_uint_32(buf);
+
+   if (int_x_red > 80000L || int_y_red > 80000L ||
+      int_x_red + int_y_red > 100000L)
+   {
+      png_warning(png_ptr, "Invalid cHRM red point");
+      png_crc_finish(png_ptr, 16);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 4);
+   int_x_green = (png_fixed_point)png_get_uint_32(buf);
+
+   png_crc_read(png_ptr, buf, 4);
+   int_y_green = (png_fixed_point)png_get_uint_32(buf);
+
+   if (int_x_green > 80000L || int_y_green > 80000L ||
+      int_x_green + int_y_green > 100000L)
+   {
+      png_warning(png_ptr, "Invalid cHRM green point");
+      png_crc_finish(png_ptr, 8);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 4);
+   int_x_blue = (png_fixed_point)png_get_uint_32(buf);
+
+   png_crc_read(png_ptr, buf, 4);
+   int_y_blue = (png_fixed_point)png_get_uint_32(buf);
+
+   if (int_x_blue > 80000L || int_y_blue > 80000L ||
+      int_x_blue + int_y_blue > 100000L)
+   {
+      png_warning(png_ptr, "Invalid cHRM blue point");
+      png_crc_finish(png_ptr, 0);
+      return;
+   }
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   white_x = (float)int_x_white / (float)100000.0;
+   white_y = (float)int_y_white / (float)100000.0;
+   red_x   = (float)int_x_red   / (float)100000.0;
+   red_y   = (float)int_y_red   / (float)100000.0;
+   green_x = (float)int_x_green / (float)100000.0;
+   green_y = (float)int_y_green / (float)100000.0;
+   blue_x  = (float)int_x_blue  / (float)100000.0;
+   blue_y  = (float)int_y_blue  / (float)100000.0;
+#endif
+
+#if defined(PNG_READ_sRGB_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sRGB)
+      {
+      if (abs(int_x_white - 31270L) > 1000 ||
+          abs(int_y_white - 32900L) > 1000 ||
+          abs(int_x_red   - 64000L) > 1000 ||
+          abs(int_y_red   - 33000L) > 1000 ||
+          abs(int_x_green - 30000L) > 1000 ||
+          abs(int_y_green - 60000L) > 1000 ||
+          abs(int_x_blue  - 15000L) > 1000 ||
+          abs(int_y_blue  -  6000L) > 1000)
+         {
+
+            png_warning(png_ptr,
+              "Ignoring incorrect cHRM value when sRGB is also present");
+#ifndef PNG_NO_CONSOLE_IO
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+            fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
+               white_x, white_y, red_x, red_y);
+            fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
+               green_x, green_y, blue_x, blue_y);
+#else
+            fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
+               int_x_white, int_y_white, int_x_red, int_y_red);
+            fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
+               int_x_green, int_y_green, int_x_blue, int_y_blue);
+#endif
+#endif /* PNG_NO_CONSOLE_IO */
+         }
+         png_crc_finish(png_ptr, 0);
+         return;
+      }
+#endif /* PNG_READ_sRGB_SUPPORTED */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   png_set_cHRM(png_ptr, info_ptr,
+      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_set_cHRM_fixed(png_ptr, info_ptr,
+      int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
+      int_y_green, int_x_blue, int_y_blue);
+#endif
+   if (png_crc_finish(png_ptr, 0))
+      return;
+}
+#endif
+
+#if defined(PNG_READ_sRGB_SUPPORTED)
+void /* PRIVATE */
+png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   int intent;
+   png_byte buf[1];
+
+   png_debug(1, "in png_handle_sRGB\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before sRGB");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid sRGB after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (png_ptr->mode & PNG_HAVE_PLTE)
+      /* Should be an error, but we can cope with it */
+      png_warning(png_ptr, "Out of place sRGB chunk");
+
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
+   {
+      png_warning(png_ptr, "Duplicate sRGB chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (length != 1)
+   {
+      png_warning(png_ptr, "Incorrect sRGB chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 1);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   intent = buf[0];
+   /* check for bad intent */
+   if (intent >= PNG_sRGB_INTENT_LAST)
+   {
+      png_warning(png_ptr, "Unknown sRGB intent");
+      return;
+   }
+
+#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
+   if ((info_ptr->valid & PNG_INFO_gAMA))
+   {
+   int igamma;
+#ifdef PNG_FIXED_POINT_SUPPORTED
+      igamma=(int)info_ptr->int_gamma;
+#else
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+      igamma=(int)(info_ptr->gamma * 100000.);
+#  endif
+#endif
+#if 0 && defined(PNG_cHRM_SUPPORTED) && !defined(PNG_FIXED_POINT_SUPPORTED)
+/* We need to define these here because they aren't in png.h */
+   png_fixed_point int_x_white;
+   png_fixed_point int_y_white;
+   png_fixed_point int_x_red;
+   png_fixed_point int_y_red;
+   png_fixed_point int_x_green;
+   png_fixed_point int_y_green;
+   png_fixed_point int_x_blue;
+   png_fixed_point int_y_blue;
+#endif
+      if(igamma < 45000L || igamma > 46000L)
+      {
+         png_warning(png_ptr,
+           "Ignoring incorrect gAMA value when sRGB is also present");
+#ifndef PNG_NO_CONSOLE_IO
+#  ifdef PNG_FIXED_POINT_SUPPORTED
+         fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
+#  else
+#    ifdef PNG_FLOATING_POINT_SUPPORTED
+         fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
+#    endif
+#  endif
+#endif
+      }
+   }
+#endif /* PNG_READ_gAMA_SUPPORTED */
+
+#ifdef PNG_READ_cHRM_SUPPORTED
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   if (info_ptr->valid & PNG_INFO_cHRM)
+      if (abs(info_ptr->int_x_white - 31270L) > 1000 ||
+          abs(info_ptr->int_y_white - 32900L) > 1000 ||
+          abs(info_ptr->int_x_red   - 64000L) > 1000 ||
+          abs(info_ptr->int_y_red   - 33000L) > 1000 ||
+          abs(info_ptr->int_x_green - 30000L) > 1000 ||
+          abs(info_ptr->int_y_green - 60000L) > 1000 ||
+          abs(info_ptr->int_x_blue  - 15000L) > 1000 ||
+          abs(info_ptr->int_y_blue  -  6000L) > 1000)
+         {
+            png_warning(png_ptr,
+              "Ignoring incorrect cHRM value when sRGB is also present");
+         }
+#endif /* PNG_FIXED_POINT_SUPPORTED */
+#endif /* PNG_READ_cHRM_SUPPORTED */
+
+   png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
+}
+#endif /* PNG_READ_sRGB_SUPPORTED */
+
+#if defined(PNG_READ_iCCP_SUPPORTED)
+void /* PRIVATE */
+png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+/* Note: this does not properly handle chunks that are > 64K under DOS */
+{
+   png_charp chunkdata;
+   png_byte compression_type;
+   png_charp profile;
+   png_uint_32 skip = 0;
+   png_uint_32 profile_size = 0;
+   png_uint_32 profile_length = 0;
+   png_size_t slength, prefix_length, data_length;
+
+   png_debug(1, "in png_handle_iCCP\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before iCCP");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid iCCP after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (png_ptr->mode & PNG_HAVE_PLTE)
+      /* Should be an error, but we can cope with it */
+      png_warning(png_ptr, "Out of place iCCP chunk");
+
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
+   {
+      png_warning(png_ptr, "Duplicate iCCP chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+#ifdef PNG_MAX_MALLOC_64K
+   if (length > (png_uint_32)65535L)
+   {
+      png_warning(png_ptr, "iCCP chunk too large to fit in memory");
+      skip = length - (png_uint_32)65535L;
+      length = (png_uint_32)65535L;
+   }
+#endif
+
+   chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+
+   if (png_crc_finish(png_ptr, skip))
+   {
+      png_free(png_ptr, chunkdata);
+      return;
+   }
+
+   chunkdata[slength] = 0x00;
+
+   for (profile = chunkdata; *profile; profile++)
+      /* empty loop to find end of name */ ;
+
+   ++profile;
+
+   /* there should be at least one zero (the compression type byte)
+      following the separator, and we should be on it  */
+   if ( profile >= chunkdata + slength)
+   {
+      png_free(png_ptr, chunkdata);
+      png_warning(png_ptr, "Malformed iCCP chunk");
+      return;
+   }
+
+   /* compression_type should always be zero */
+   compression_type = *profile++;
+   if (compression_type)
+   {
+      png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
+      compression_type=0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
+                                 wrote nonzero) */
+   }
+
+   prefix_length = profile - chunkdata;
+   chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
+                                    slength, prefix_length, &data_length);
+
+   profile_length = data_length - prefix_length;
+
+   if ( profile_length < 4)
+   {
+      png_free(png_ptr, chunkdata);
+      png_warning(png_ptr, "Profile size field missing from iCCP chunk");
+      return;
+   }
+
+   /* Check the profile_size recorded in the first 32 bits of the ICC profile */
+   profile_size = ((*(chunkdata+prefix_length))<<24) |
+                  ((*(chunkdata+prefix_length+1))<<16) |
+                  ((*(chunkdata+prefix_length+2))<< 8) |
+                  ((*(chunkdata+prefix_length+3))    );
+
+   if(profile_size < profile_length)
+      profile_length = profile_size;
+
+   if(profile_size > profile_length)
+   {
+      png_free(png_ptr, chunkdata);
+      png_warning(png_ptr, "Ignoring truncated iCCP profile.\n");
+      return;
+   }
+
+   png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
+                chunkdata + prefix_length, profile_length);
+   png_free(png_ptr, chunkdata);
+}
+#endif /* PNG_READ_iCCP_SUPPORTED */
+
+#if defined(PNG_READ_sPLT_SUPPORTED)
+void /* PRIVATE */
+png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+/* Note: this does not properly handle chunks that are > 64K under DOS */
+{
+   png_bytep chunkdata;
+   png_bytep entry_start;
+   png_sPLT_t new_palette;
+#ifdef PNG_NO_POINTER_INDEXING
+   png_sPLT_entryp pp;
+#endif
+   int data_length, entry_size, i;
+   png_uint_32 skip = 0;
+   png_size_t slength;
+
+   png_debug(1, "in png_handle_sPLT\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before sPLT");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid sPLT after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+#ifdef PNG_MAX_MALLOC_64K
+   if (length > (png_uint_32)65535L)
+   {
+      png_warning(png_ptr, "sPLT chunk too large to fit in memory");
+      skip = length - (png_uint_32)65535L;
+      length = (png_uint_32)65535L;
+   }
+#endif
+
+   chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+
+   if (png_crc_finish(png_ptr, skip))
+   {
+      png_free(png_ptr, chunkdata);
+      return;
+   }
+
+   chunkdata[slength] = 0x00;
+
+   for (entry_start = chunkdata; *entry_start; entry_start++)
+      /* empty loop to find end of name */ ;
+   ++entry_start;
+
+   /* a sample depth should follow the separator, and we should be on it  */
+   if (entry_start > chunkdata + slength)
+   {
+      png_free(png_ptr, chunkdata);
+      png_warning(png_ptr, "malformed sPLT chunk");
+      return;
+   }
+
+   new_palette.depth = *entry_start++;
+   entry_size = (new_palette.depth == 8 ? 6 : 10);
+   data_length = (slength - (entry_start - chunkdata));
+
+   /* integrity-check the data length */
+   if (data_length % entry_size)
+   {
+      png_free(png_ptr, chunkdata);
+      png_warning(png_ptr, "sPLT chunk has bad length");
+      return;
+   }
+
+   new_palette.nentries = data_length / entry_size;
+   new_palette.entries = (png_sPLT_entryp)png_malloc(
+       png_ptr, new_palette.nentries * sizeof(png_sPLT_entry));
+
+#ifndef PNG_NO_POINTER_INDEXING
+   for (i = 0; i < new_palette.nentries; i++)
+   {
+      png_sPLT_entryp pp = new_palette.entries + i;
+
+      if (new_palette.depth == 8)
+      {
+          pp->red = *entry_start++;
+          pp->green = *entry_start++;
+          pp->blue = *entry_start++;
+          pp->alpha = *entry_start++;
+      }
+      else
+      {
+          pp->red   = png_get_uint_16(entry_start); entry_start += 2;
+          pp->green = png_get_uint_16(entry_start); entry_start += 2;
+          pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
+          pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
+      }
+      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
+   }
+#else
+   pp = new_palette.entries;
+   for (i = 0; i < new_palette.nentries; i++)
+   {
+
+      if (new_palette.depth == 8)
+      {
+          pp[i].red   = *entry_start++;
+          pp[i].green = *entry_start++;
+          pp[i].blue  = *entry_start++;
+          pp[i].alpha = *entry_start++;
+      }
+      else
+      {
+          pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
+          pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
+          pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
+          pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
+      }
+      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
+   }
+#endif
+
+   /* discard all chunk data except the name and stash that */
+   new_palette.name = (png_charp)chunkdata;
+
+   png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
+
+   png_free(png_ptr, chunkdata);
+   png_free(png_ptr, new_palette.entries);
+}
+#endif /* PNG_READ_sPLT_SUPPORTED */
+
+#if defined(PNG_READ_tRNS_SUPPORTED)
+void /* PRIVATE */
+png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte    readbuf[PNG_MAX_PALETTE_LENGTH];
+
+   png_debug(1, "in png_handle_tRNS\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before tRNS");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid tRNS after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+   {
+      png_warning(png_ptr, "Duplicate tRNS chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (!(png_ptr->mode & PNG_HAVE_PLTE))
+      {
+         /* Should be an error, but we can cope with it */
+         png_warning(png_ptr, "Missing PLTE before tRNS");
+      }
+      else if (length > (png_uint_32)png_ptr->num_palette)
+      {
+         png_warning(png_ptr, "Incorrect tRNS chunk length");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+      if (length == 0)
+      {
+         png_warning(png_ptr, "Zero length tRNS chunk");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+
+      png_crc_read(png_ptr, readbuf, (png_size_t)length);
+      png_ptr->num_trans = (png_uint_16)length;
+   }
+   else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+   {
+      png_byte buf[6];
+
+      if (length != 6)
+      {
+         png_warning(png_ptr, "Incorrect tRNS chunk length");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+
+      png_crc_read(png_ptr, buf, (png_size_t)length);
+      png_ptr->num_trans = 1;
+      png_ptr->trans_values.red = png_get_uint_16(buf);
+      png_ptr->trans_values.green = png_get_uint_16(buf + 2);
+      png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
+   }
+   else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+   {
+      png_byte buf[6];
+
+      if (length != 2)
+      {
+         png_warning(png_ptr, "Incorrect tRNS chunk length");
+         png_crc_finish(png_ptr, length);
+         return;
+      }
+
+      png_crc_read(png_ptr, buf, 2);
+      png_ptr->num_trans = 1;
+      png_ptr->trans_values.gray = png_get_uint_16(buf);
+   }
+   else
+   {
+      png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
+      &(png_ptr->trans_values));
+}
+#endif
+
+#if defined(PNG_READ_bKGD_SUPPORTED)
+void /* PRIVATE */
+png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_size_t truelen;
+   png_byte buf[6];
+
+   png_debug(1, "in png_handle_bKGD\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before bKGD");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid bKGD after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+            !(png_ptr->mode & PNG_HAVE_PLTE))
+   {
+      png_warning(png_ptr, "Missing PLTE before bKGD");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
+   {
+      png_warning(png_ptr, "Duplicate bKGD chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      truelen = 1;
+   else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+      truelen = 6;
+   else
+      truelen = 2;
+
+   if (length != truelen)
+   {
+      png_warning(png_ptr, "Incorrect bKGD chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, truelen);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   /* We convert the index value into RGB components so that we can allow
+    * arbitrary RGB values for background when we have transparency, and
+    * so it is easy to determine the RGB values of the background color
+    * from the info_ptr struct. */
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      png_ptr->background.index = buf[0];
+      if(info_ptr->num_palette)
+      {
+          if(buf[0] > info_ptr->num_palette)
+          {
+             png_warning(png_ptr, "Incorrect bKGD chunk index value");
+             return;
+          }
+          png_ptr->background.red =
+             (png_uint_16)png_ptr->palette[buf[0]].red;
+          png_ptr->background.green =
+             (png_uint_16)png_ptr->palette[buf[0]].green;
+          png_ptr->background.blue =
+             (png_uint_16)png_ptr->palette[buf[0]].blue;
+      }
+   }
+   else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
+   {
+      png_ptr->background.red =
+      png_ptr->background.green =
+      png_ptr->background.blue =
+      png_ptr->background.gray = png_get_uint_16(buf);
+   }
+   else
+   {
+      png_ptr->background.red = png_get_uint_16(buf);
+      png_ptr->background.green = png_get_uint_16(buf + 2);
+      png_ptr->background.blue = png_get_uint_16(buf + 4);
+   }
+
+   png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
+}
+#endif
+
+#if defined(PNG_READ_hIST_SUPPORTED)
+void /* PRIVATE */
+png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   int num, i;
+   png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
+
+   png_debug(1, "in png_handle_hIST\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before hIST");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid hIST after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (!(png_ptr->mode & PNG_HAVE_PLTE))
+   {
+      png_warning(png_ptr, "Missing PLTE before hIST");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
+   {
+      png_warning(png_ptr, "Duplicate hIST chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   num = (int)length / 2 ;
+   if (num != png_ptr->num_palette)
+   {
+      png_warning(png_ptr, "Incorrect hIST chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   for (i = 0; i < num; i++)
+   {
+      png_byte buf[2];
+
+      png_crc_read(png_ptr, buf, 2);
+      readbuf[i] = png_get_uint_16(buf);
+   }
+
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   png_set_hIST(png_ptr, info_ptr, readbuf);
+}
+#endif
+
+#if defined(PNG_READ_pHYs_SUPPORTED)
+void /* PRIVATE */
+png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte buf[9];
+   png_uint_32 res_x, res_y;
+   int unit_type;
+
+   png_debug(1, "in png_handle_pHYs\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before pHYs");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid pHYs after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+   {
+      png_warning(png_ptr, "Duplicate pHYs chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (length != 9)
+   {
+      png_warning(png_ptr, "Incorrect pHYs chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 9);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   res_x = png_get_uint_32(buf);
+   res_y = png_get_uint_32(buf + 4);
+   unit_type = buf[8];
+   png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
+}
+#endif
+
+#if defined(PNG_READ_oFFs_SUPPORTED)
+void /* PRIVATE */
+png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte buf[9];
+   png_int_32 offset_x, offset_y;
+   int unit_type;
+
+   png_debug(1, "in png_handle_oFFs\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before oFFs");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid oFFs after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+   {
+      png_warning(png_ptr, "Duplicate oFFs chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (length != 9)
+   {
+      png_warning(png_ptr, "Incorrect oFFs chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 9);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   offset_x = png_get_int_32(buf);
+   offset_y = png_get_int_32(buf + 4);
+   unit_type = buf[8];
+   png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
+}
+#endif
+
+#if defined(PNG_READ_pCAL_SUPPORTED)
+/* read the pCAL chunk (described in the PNG Extensions document) */
+void /* PRIVATE */
+png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_charp purpose;
+   png_int_32 X0, X1;
+   png_byte type, nparams;
+   png_charp buf, units, endptr;
+   png_charpp params;
+   png_size_t slength;
+   int i;
+
+   png_debug(1, "in png_handle_pCAL\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before pCAL");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid pCAL after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
+   {
+      png_warning(png_ptr, "Duplicate pCAL chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
+      length + 1);
+   purpose = (png_charp)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)purpose, slength);
+
+   if (png_crc_finish(png_ptr, 0))
+   {
+      png_free(png_ptr, purpose);
+      return;
+   }
+
+   purpose[slength] = 0x00; /* null terminate the last string */
+
+   png_debug(3, "Finding end of pCAL purpose string\n");
+   for (buf = purpose; *buf; buf++)
+      /* empty loop */ ;
+
+   endptr = purpose + slength;
+
+   /* We need to have at least 12 bytes after the purpose string
+      in order to get the parameter information. */
+   if (endptr <= buf + 12)
+   {
+      png_warning(png_ptr, "Invalid pCAL data");
+      png_free(png_ptr, purpose);
+      return;
+   }
+
+   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
+   X0 = png_get_int_32((png_bytep)buf+1);
+   X1 = png_get_int_32((png_bytep)buf+5);
+   type = buf[9];
+   nparams = buf[10];
+   units = buf + 11;
+
+   png_debug(3, "Checking pCAL equation type and number of parameters\n");
+   /* Check that we have the right number of parameters for known
+      equation types. */
+   if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
+       (type == PNG_EQUATION_BASE_E && nparams != 3) ||
+       (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
+       (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
+   {
+      png_warning(png_ptr, "Invalid pCAL parameters for equation type");
+      png_free(png_ptr, purpose);
+      return;
+   }
+   else if (type >= PNG_EQUATION_LAST)
+   {
+      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+   }
+
+   for (buf = units; *buf; buf++)
+      /* Empty loop to move past the units string. */ ;
+
+   png_debug(3, "Allocating pCAL parameters array\n");
+   params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams
+      *sizeof(png_charp))) ;
+
+   /* Get pointers to the start of each parameter string. */
+   for (i = 0; i < (int)nparams; i++)
+   {
+      buf++; /* Skip the null string terminator from previous parameter. */
+
+      png_debug1(3, "Reading pCAL parameter %d\n", i);
+      for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
+         /* Empty loop to move past each parameter string */ ;
+
+      /* Make sure we haven't run out of data yet */
+      if (buf > endptr)
+      {
+         png_warning(png_ptr, "Invalid pCAL data");
+         png_free(png_ptr, purpose);
+         png_free(png_ptr, params);
+         return;
+      }
+   }
+
+   png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
+      units, params);
+
+   png_free(png_ptr, purpose);
+   png_free(png_ptr, params);
+}
+#endif
+
+#if defined(PNG_READ_sCAL_SUPPORTED)
+/* read the sCAL chunk */
+void /* PRIVATE */
+png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_charp buffer, ep;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   double width, height;
+   png_charp vp;
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_charp swidth, sheight;
+#endif
+#endif
+   png_size_t slength;
+
+   png_debug(1, "in png_handle_sCAL\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before sCAL");
+   else if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+      png_warning(png_ptr, "Invalid sCAL after IDAT");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
+   {
+      png_warning(png_ptr, "Duplicate sCAL chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
+      length + 1);
+   buffer = (png_charp)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)buffer, slength);
+
+   if (png_crc_finish(png_ptr, 0))
+   {
+      png_free(png_ptr, buffer);
+      return;
+   }
+
+   buffer[slength] = 0x00; /* null terminate the last string */
+
+   ep = buffer + 1;        /* skip unit byte */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   width = strtod(ep, &vp);
+   if (*vp)
+   {
+       png_warning(png_ptr, "malformed width string in sCAL chunk");
+       return;
+   }
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   swidth = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1);
+   png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
+#endif
+#endif
+
+   for (ep = buffer; *ep; ep++)
+      /* empty loop */ ;
+   ep++;
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   height = strtod(ep, &vp);
+   if (*vp)
+   {
+       png_warning(png_ptr, "malformed height string in sCAL chunk");
+       return;
+   }
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   sheight = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1);
+   png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
+#endif
+#endif
+
+   if (buffer + slength < ep
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+      || width <= 0. || height <= 0.
+#endif
+      )
+   {
+      png_warning(png_ptr, "Invalid sCAL data");
+      png_free(png_ptr, buffer);
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+      png_free(png_ptr, swidth);
+      png_free(png_ptr, sheight);
+#endif
+      return;
+   }
+
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
+#endif
+#endif
+
+   png_free(png_ptr, buffer);
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+   png_free(png_ptr, swidth);
+   png_free(png_ptr, sheight);
+#endif
+}
+#endif
+
+#if defined(PNG_READ_tIME_SUPPORTED)
+void /* PRIVATE */
+png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_byte buf[7];
+   png_time mod_time;
+
+   png_debug(1, "in png_handle_tIME\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Out of place tIME chunk");
+   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
+   {
+      png_warning(png_ptr, "Duplicate tIME chunk");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   if (png_ptr->mode & PNG_HAVE_IDAT)
+      png_ptr->mode |= PNG_AFTER_IDAT;
+
+   if (length != 7)
+   {
+      png_warning(png_ptr, "Incorrect tIME chunk length");
+      png_crc_finish(png_ptr, length);
+      return;
+   }
+
+   png_crc_read(png_ptr, buf, 7);
+   if (png_crc_finish(png_ptr, 0))
+      return;
+
+   mod_time.second = buf[6];
+   mod_time.minute = buf[5];
+   mod_time.hour = buf[4];
+   mod_time.day = buf[3];
+   mod_time.month = buf[2];
+   mod_time.year = png_get_uint_16(buf);
+
+   png_set_tIME(png_ptr, info_ptr, &mod_time);
+}
+#endif
+
+#if defined(PNG_READ_tEXt_SUPPORTED)
+/* Note: this does not properly handle chunks that are > 64K under DOS */
+void /* PRIVATE */
+png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_textp text_ptr;
+   png_charp key;
+   png_charp text;
+   png_uint_32 skip = 0;
+   png_size_t slength;
+
+   png_debug(1, "in png_handle_tEXt\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before tEXt");
+
+   if (png_ptr->mode & PNG_HAVE_IDAT)
+      png_ptr->mode |= PNG_AFTER_IDAT;
+
+#ifdef PNG_MAX_MALLOC_64K
+   if (length > (png_uint_32)65535L)
+   {
+      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
+      skip = length - (png_uint_32)65535L;
+      length = (png_uint_32)65535L;
+   }
+#endif
+
+   key = (png_charp)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)key, slength);
+
+   if (png_crc_finish(png_ptr, skip))
+   {
+      png_free(png_ptr, key);
+      return;
+   }
+
+   key[slength] = 0x00;
+
+   for (text = key; *text; text++)
+      /* empty loop to find end of key */ ;
+
+   if (text != key + slength)
+      text++;
+
+   text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
+   text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
+   text_ptr->key = key;
+#ifdef PNG_iTXt_SUPPORTED
+   text_ptr->lang = NULL;
+   text_ptr->lang_key = NULL;
+   text_ptr->itxt_length = 0;
+#endif
+   text_ptr->text = text;
+   text_ptr->text_length = png_strlen(text);
+
+   png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+   png_free(png_ptr, key);
+   png_free(png_ptr, text_ptr);
+}
+#endif
+
+#if defined(PNG_READ_zTXt_SUPPORTED)
+/* note: this does not correctly handle chunks that are > 64K under DOS */
+void /* PRIVATE */
+png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_textp text_ptr;
+   png_charp chunkdata;
+   png_charp text;
+   int comp_type;
+   png_size_t slength, prefix_len, data_len;
+
+   png_debug(1, "in png_handle_zTXt\n");
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before zTXt");
+
+   if (png_ptr->mode & PNG_HAVE_IDAT)
+      png_ptr->mode |= PNG_AFTER_IDAT;
+
+#ifdef PNG_MAX_MALLOC_64K
+   /* We will no doubt have problems with chunks even half this size, but
+      there is no hard and fast rule to tell us where to stop. */
+   if (length > (png_uint_32)65535L)
+   {
+     png_warning(png_ptr,"zTXt chunk too large to fit in memory");
+     png_crc_finish(png_ptr, length);
+     return;
+   }
+#endif
+
+   chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+     slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   if (png_crc_finish(png_ptr, 0))
+   {
+      png_free(png_ptr, chunkdata);
+      return;
+   }
+
+   chunkdata[slength] = 0x00;
+
+   for (text = chunkdata; *text; text++)
+      /* empty loop */ ;
+
+   /* zTXt must have some text after the chunkdataword */
+   if (text == chunkdata + slength)
+   {
+      comp_type = PNG_TEXT_COMPRESSION_NONE;
+      png_warning(png_ptr, "Zero length zTXt chunk");
+   }
+   else
+   {
+       comp_type = *(++text);
+       if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
+       {
+          png_warning(png_ptr, "Unknown compression type in zTXt chunk");
+          comp_type = PNG_TEXT_COMPRESSION_zTXt;
+       }
+       text++;        /* skip the compression_method byte */
+   }
+   prefix_len = text - chunkdata;
+
+   chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
+                                    (png_size_t)length, prefix_len, &data_len);
+
+   text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
+   text_ptr->compression = comp_type;
+   text_ptr->key = chunkdata;
+#ifdef PNG_iTXt_SUPPORTED
+   text_ptr->lang = NULL;
+   text_ptr->lang_key = NULL;
+   text_ptr->itxt_length = 0;
+#endif
+   text_ptr->text = chunkdata + prefix_len;
+   text_ptr->text_length = data_len;
+
+   png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+   png_free(png_ptr, text_ptr);
+   png_free(png_ptr, chunkdata);
+}
+#endif
+
+#if defined(PNG_READ_iTXt_SUPPORTED)
+/* note: this does not correctly handle chunks that are > 64K under DOS */
+void /* PRIVATE */
+png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_textp text_ptr;
+   png_charp chunkdata;
+   png_charp key, lang, text, lang_key;
+   int comp_flag;
+   int comp_type = 0;
+   png_size_t slength, prefix_len, data_len;
+
+   png_debug(1, "in png_handle_iTXt\n");
+
+   if (!(png_ptr->mode & PNG_HAVE_IHDR))
+      png_error(png_ptr, "Missing IHDR before iTXt");
+
+   if (png_ptr->mode & PNG_HAVE_IDAT)
+      png_ptr->mode |= PNG_AFTER_IDAT;
+
+#ifdef PNG_MAX_MALLOC_64K
+   /* We will no doubt have problems with chunks even half this size, but
+      there is no hard and fast rule to tell us where to stop. */
+   if (length > (png_uint_32)65535L)
+   {
+     png_warning(png_ptr,"iTXt chunk too large to fit in memory");
+     png_crc_finish(png_ptr, length);
+     return;
+   }
+#endif
+
+   chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+   slength = (png_size_t)length;
+   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
+   if (png_crc_finish(png_ptr, 0))
+   {
+      png_free(png_ptr, chunkdata);
+      return;
+   }
+
+   chunkdata[slength] = 0x00;
+
+   for (lang = chunkdata; *lang; lang++)
+      /* empty loop */ ;
+   lang++;        /* skip NUL separator */
+
+   /* iTXt must have a language tag (possibly empty), two compression bytes,
+      translated keyword (possibly empty), and possibly some text after the
+      keyword */
+
+   if (lang >= chunkdata + slength)
+   {
+      comp_flag = PNG_TEXT_COMPRESSION_NONE;
+      png_warning(png_ptr, "Zero length iTXt chunk");
+   }
+   else
+   {
+       comp_flag = *lang++;
+       comp_type = *lang++;
+   }
+
+   for (lang_key = lang; *lang_key; lang_key++)
+      /* empty loop */ ;
+   lang_key++;        /* skip NUL separator */
+
+   for (text = lang_key; *text; text++)
+      /* empty loop */ ;
+   text++;        /* skip NUL separator */
+
+   prefix_len = text - chunkdata;
+
+   key=chunkdata;
+   if (comp_flag)
+       chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
+          (size_t)length, prefix_len, &data_len);
+   else
+       data_len=png_strlen(chunkdata + prefix_len);
+   text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
+   text_ptr->compression = (int)comp_flag + 1;
+   text_ptr->lang_key = chunkdata+(lang_key-key);
+   text_ptr->lang = chunkdata+(lang-key);
+   text_ptr->itxt_length = data_len;
+   text_ptr->text_length = 0;
+   text_ptr->key = chunkdata;
+   text_ptr->text = chunkdata + prefix_len;
+
+   png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+   png_free(png_ptr, text_ptr);
+   png_free(png_ptr, chunkdata);
+}
+#endif
+
+/* This function is called when we haven't found a handler for a
+   chunk.  If there isn't a problem with the chunk itself (ie bad
+   chunk name, CRC, or a critical chunk), the chunk is silently ignored
+   -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
+   case it will be saved away to be written out later. */
+void /* PRIVATE */
+png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+   png_uint_32 skip = 0;
+
+   png_debug(1, "in png_handle_unknown\n");
+
+   if (png_ptr->mode & PNG_HAVE_IDAT)
+   {
+#ifdef PNG_USE_LOCAL_ARRAYS
+      PNG_IDAT;
+#endif
+      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))  /* not an IDAT */
+         png_ptr->mode |= PNG_AFTER_IDAT;
+   }
+
+   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+
+   if (!(png_ptr->chunk_name[0] & 0x20))
+   {
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+      if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+           HANDLE_CHUNK_ALWAYS
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+           && png_ptr->read_user_chunk_fn == NULL
+#endif
+        )
+#endif
+          png_chunk_error(png_ptr, "unknown critical chunk");
+   }
+
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+   if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
+   {
+       png_unknown_chunk chunk;
+
+#ifdef PNG_MAX_MALLOC_64K
+       if (length > (png_uint_32)65535L)
+       {
+           png_warning(png_ptr, "unknown chunk too large to fit in memory");
+           skip = length - (png_uint_32)65535L;
+           length = (png_uint_32)65535L;
+       }
+#endif
+       png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
+       chunk.data = (png_bytep)png_malloc(png_ptr, length);
+       chunk.size = (png_size_t)length;
+       png_crc_read(png_ptr, (png_bytep)chunk.data, length);
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+       if(png_ptr->read_user_chunk_fn != NULL)
+       {
+          /* callback to user unknown chunk handler */
+          if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
+          {
+             if (!(png_ptr->chunk_name[0] & 0x20))
+                if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+                     HANDLE_CHUNK_ALWAYS)
+                   png_chunk_error(png_ptr, "unknown critical chunk");
+             png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
+          }
+       }
+       else
+#endif
+          png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
+       png_free(png_ptr, chunk.data);
+   }
+   else
+#endif
+      skip = length;
+
+   png_crc_finish(png_ptr, skip);
+
+#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+   info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
+#endif
+}
+
+/* This function is called to verify that a chunk name is valid.
+   This function can't have the "critical chunk check" incorporated
+   into it, since in the future we will need to be able to call user
+   functions to handle unknown critical chunks after we check that
+   the chunk name itself is valid. */
+
+#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
+
+void /* PRIVATE */
+png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
+{
+   png_debug(1, "in png_check_chunk_name\n");
+   if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
+       isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
+   {
+      png_chunk_error(png_ptr, "invalid chunk type");
+   }
+}
+
+/* Combines the row recently read in with the existing pixels in the
+   row.  This routine takes care of alpha and transparency if requested.
+   This routine also handles the two methods of progressive display
+   of interlaced images, depending on the mask value.
+   The mask value describes which pixels are to be combined with
+   the row.  The pattern always repeats every 8 pixels, so just 8
+   bits are needed.  A one indicates the pixel is to be combined,
+   a zero indicates the pixel is to be skipped.  This is in addition
+   to any alpha or transparency value associated with the pixel.  If
+   you want all pixels to be combined, pass 0xff (255) in mask.  */
+#ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
+void /* PRIVATE */
+png_combine_row(png_structp png_ptr, png_bytep row, int mask)
+{
+   png_debug(1,"in png_combine_row\n");
+   if (mask == 0xff)
+   {
+      png_memcpy(row, png_ptr->row_buf + 1,
+         (png_size_t)((png_ptr->width *
+         png_ptr->row_info.pixel_depth + 7) >> 3));
+   }
+   else
+   {
+      switch (png_ptr->row_info.pixel_depth)
+      {
+         case 1:
+         {
+            png_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
+            int s_inc, s_start, s_end;
+            int m = 0x80;
+            int shift;
+            png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+                s_start = 0;
+                s_end = 7;
+                s_inc = 1;
+            }
+            else
+#endif
+            {
+                s_start = 7;
+                s_end = 0;
+                s_inc = -1;
+            }
+
+            shift = s_start;
+
+            for (i = 0; i < row_width; i++)
+            {
+               if (m & mask)
+               {
+                  int value;
+
+                  value = (*sp >> shift) & 0x01;
+                  *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+         case 2:
+         {
+            png_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
+            int s_start, s_end, s_inc;
+            int m = 0x80;
+            int shift;
+            png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
+            int value;
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+               s_start = 0;
+               s_end = 6;
+               s_inc = 2;
+            }
+            else
+#endif
+            {
+               s_start = 6;
+               s_end = 0;
+               s_inc = -2;
+            }
+
+            shift = s_start;
+
+            for (i = 0; i < row_width; i++)
+            {
+               if (m & mask)
+               {
+                  value = (*sp >> shift) & 0x03;
+                  *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+         case 4:
+         {
+            png_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
+            int s_start, s_end, s_inc;
+            int m = 0x80;
+            int shift;
+            png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
+            int value;
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+               s_start = 0;
+               s_end = 4;
+               s_inc = 4;
+            }
+            else
+#endif
+            {
+               s_start = 4;
+               s_end = 0;
+               s_inc = -4;
+            }
+            shift = s_start;
+
+            for (i = 0; i < row_width; i++)
+            {
+               if (m & mask)
+               {
+                  value = (*sp >> shift) & 0xf;
+                  *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+         default:
+         {
+            png_bytep sp = png_ptr->row_buf + 1;
+            png_bytep dp = row;
+            png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+            png_uint_32 i;
+            png_uint_32 row_width = png_ptr->width;
+            png_byte m = 0x80;
+
+
+            for (i = 0; i < row_width; i++)
+            {
+               if (m & mask)
+               {
+                  png_memcpy(dp, sp, pixel_bytes);
+               }
+
+               sp += pixel_bytes;
+               dp += pixel_bytes;
+
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+      }
+   }
+}
+#endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+#ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE   /* else in pngvcrd.c, pnggccrd.c */
+/* OLD pre-1.0.9 interface:
+void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
+   png_uint_32 transformations)
+ */
+void /* PRIVATE */
+png_do_read_interlace(png_structp png_ptr)
+{
+   png_row_infop row_info = &(png_ptr->row_info);
+   png_bytep row = png_ptr->row_buf + 1;
+   int pass = png_ptr->pass;
+   png_uint_32 transformations = png_ptr->transformations;
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+   /* offset to next interlace block */
+   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+#endif
+
+   png_debug(1,"in png_do_read_interlace (stock C version)\n");
+   if (row != NULL && row_info != NULL)
+   {
+      png_uint_32 final_width;
+
+      final_width = row_info->width * png_pass_inc[pass];
+
+      switch (row_info->pixel_depth)
+      {
+         case 1:
+         {
+            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
+            png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            int jstop = png_pass_inc[pass];
+            png_byte v;
+            png_uint_32 i;
+            int j;
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+                sshift = (int)((row_info->width + 7) & 0x07);
+                dshift = (int)((final_width + 7) & 0x07);
+                s_start = 7;
+                s_end = 0;
+                s_inc = -1;
+            }
+            else
+#endif
+            {
+                sshift = 7 - (int)((row_info->width + 7) & 0x07);
+                dshift = 7 - (int)((final_width + 7) & 0x07);
+                s_start = 0;
+                s_end = 7;
+                s_inc = 1;
+            }
+
+            for (i = 0; i < row_info->width; i++)
+            {
+               v = (png_byte)((*sp >> sshift) & 0x01);
+               for (j = 0; j < jstop; j++)
+               {
+                  *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+         case 2:
+         {
+            png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
+            png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            int jstop = png_pass_inc[pass];
+            png_uint_32 i;
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (int)(((row_info->width + 3) & 0x03) << 1);
+               dshift = (int)(((final_width + 3) & 0x03) << 1);
+               s_start = 6;
+               s_end = 0;
+               s_inc = -2;
+            }
+            else
+#endif
+            {
+               sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
+               dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
+               s_start = 0;
+               s_end = 6;
+               s_inc = 2;
+            }
+
+            for (i = 0; i < row_info->width; i++)
+            {
+               png_byte v;
+               int j;
+
+               v = (png_byte)((*sp >> sshift) & 0x03);
+               for (j = 0; j < jstop; j++)
+               {
+                  *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+         case 4:
+         {
+            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
+            png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_uint_32 i;
+            int jstop = png_pass_inc[pass];
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (int)(((row_info->width + 1) & 0x01) << 2);
+               dshift = (int)(((final_width + 1) & 0x01) << 2);
+               s_start = 4;
+               s_end = 0;
+               s_inc = -4;
+            }
+            else
+#endif
+            {
+               sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
+               dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
+               s_start = 0;
+               s_end = 4;
+               s_inc = 4;
+            }
+
+            for (i = 0; i < row_info->width; i++)
+            {
+               png_byte v = (png_byte)((*sp >> sshift) & 0xf);
+               int j;
+
+               for (j = 0; j < jstop; j++)
+               {
+                  *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+         default:
+         {
+            png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
+            png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
+            png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
+
+            int jstop = png_pass_inc[pass];
+            png_uint_32 i;
+
+            for (i = 0; i < row_info->width; i++)
+            {
+               png_byte v[8];
+               int j;
+
+               png_memcpy(v, sp, pixel_bytes);
+               for (j = 0; j < jstop; j++)
+               {
+                  png_memcpy(dp, v, pixel_bytes);
+                  dp -= pixel_bytes;
+               }
+               sp -= pixel_bytes;
+            }
+            break;
+         }
+      }
+      row_info->width = final_width;
+      row_info->rowbytes = ((final_width *
+         (png_uint_32)row_info->pixel_depth + 7) >> 3);
+   }
+#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
+   transformations = transformations; /* silence compiler warning */
+#endif
+}
+#endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+
+#ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
+void /* PRIVATE */
+png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
+   png_bytep prev_row, int filter)
+{
+   png_debug(1, "in png_read_filter_row\n");
+   png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
+   switch (filter)
+   {
+      case PNG_FILTER_VALUE_NONE:
+         break;
+      case PNG_FILTER_VALUE_SUB:
+      {
+         png_uint_32 i;
+         png_uint_32 istop = row_info->rowbytes;
+         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+         png_bytep rp = row + bpp;
+         png_bytep lp = row;
+
+         for (i = bpp; i < istop; i++)
+         {
+            *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
+            rp++;
+         }
+         break;
+      }
+      case PNG_FILTER_VALUE_UP:
+      {
+         png_uint_32 i;
+         png_uint_32 istop = row_info->rowbytes;
+         png_bytep rp = row;
+         png_bytep pp = prev_row;
+
+         for (i = 0; i < istop; i++)
+         {
+            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+            rp++;
+         }
+         break;
+      }
+      case PNG_FILTER_VALUE_AVG:
+      {
+         png_uint_32 i;
+         png_bytep rp = row;
+         png_bytep pp = prev_row;
+         png_bytep lp = row;
+         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+         png_uint_32 istop = row_info->rowbytes - bpp;
+
+         for (i = 0; i < bpp; i++)
+         {
+            *rp = (png_byte)(((int)(*rp) +
+               ((int)(*pp++) / 2 )) & 0xff);
+            rp++;
+         }
+
+         for (i = 0; i < istop; i++)
+         {
+            *rp = (png_byte)(((int)(*rp) +
+               (int)(*pp++ + *lp++) / 2 ) & 0xff);
+            rp++;
+         }
+         break;
+      }
+      case PNG_FILTER_VALUE_PAETH:
+      {
+         png_uint_32 i;
+         png_bytep rp = row;
+         png_bytep pp = prev_row;
+         png_bytep lp = row;
+         png_bytep cp = prev_row;
+         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+         png_uint_32 istop=row_info->rowbytes - bpp;
+
+         for (i = 0; i < bpp; i++)
+         {
+            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+            rp++;
+         }
+
+         for (i = 0; i < istop; i++)   /* use leftover rp,pp */
+         {
+            int a, b, c, pa, pb, pc, p;
+
+            a = *lp++;
+            b = *pp++;
+            c = *cp++;
+
+            p = b - c;
+            pc = a - c;
+
+#ifdef PNG_USE_ABS
+            pa = abs(p);
+            pb = abs(pc);
+            pc = abs(p + pc);
+#else
+            pa = p < 0 ? -p : p;
+            pb = pc < 0 ? -pc : pc;
+            pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+            /*
+               if (pa <= pb && pa <= pc)
+                  p = a;
+               else if (pb <= pc)
+                  p = b;
+               else
+                  p = c;
+             */
+
+            p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+
+            *rp = (png_byte)(((int)(*rp) + p) & 0xff);
+            rp++;
+         }
+         break;
+      }
+      default:
+         png_warning(png_ptr, "Ignoring bad adaptive filter type");
+         *row=0;
+         break;
+   }
+}
+#endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
+
+void /* PRIVATE */
+png_read_finish_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+   /* start of interlace block in the y direction */
+   const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+   /* offset to next interlace block in the y direction */
+   const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+   png_debug(1, "in png_read_finish_row\n");
+   png_ptr->row_number++;
+   if (png_ptr->row_number < png_ptr->num_rows)
+      return;
+
+   if (png_ptr->interlaced)
+   {
+      png_ptr->row_number = 0;
+      png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+      do
+      {
+         png_ptr->pass++;
+         if (png_ptr->pass >= 7)
+            break;
+         png_ptr->iwidth = (png_ptr->width +
+            png_pass_inc[png_ptr->pass] - 1 -
+            png_pass_start[png_ptr->pass]) /
+            png_pass_inc[png_ptr->pass];
+            png_ptr->irowbytes = ((png_ptr->iwidth *
+               (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
+
+         if (!(png_ptr->transformations & PNG_INTERLACE))
+         {
+            png_ptr->num_rows = (png_ptr->height +
+               png_pass_yinc[png_ptr->pass] - 1 -
+               png_pass_ystart[png_ptr->pass]) /
+               png_pass_yinc[png_ptr->pass];
+            if (!(png_ptr->num_rows))
+               continue;
+         }
+         else  /* if (png_ptr->transformations & PNG_INTERLACE) */
+            break;
+      } while (png_ptr->iwidth == 0);
+
+      if (png_ptr->pass < 7)
+         return;
+   }
+
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+   {
+#ifdef PNG_USE_LOCAL_ARRAYS
+      PNG_IDAT;
+#endif
+      char extra;
+      int ret;
+
+      png_ptr->zstream.next_out = (Byte *)&extra;
+      png_ptr->zstream.avail_out = (uInt)1;
+      for(;;)
+      {
+         if (!(png_ptr->zstream.avail_in))
+         {
+            while (!png_ptr->idat_size)
+            {
+               png_byte chunk_length[4];
+
+               png_crc_finish(png_ptr, 0);
+
+               png_read_data(png_ptr, chunk_length, 4);
+               png_ptr->idat_size = png_get_uint_32(chunk_length);
+
+               png_reset_crc(png_ptr);
+               png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+               if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
+                  png_error(png_ptr, "Not enough image data");
+
+            }
+            png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
+            png_ptr->zstream.next_in = png_ptr->zbuf;
+            if (png_ptr->zbuf_size > png_ptr->idat_size)
+               png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
+            png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
+            png_ptr->idat_size -= png_ptr->zstream.avail_in;
+         }
+         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+         if (ret == Z_STREAM_END)
+         {
+            if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
+               png_ptr->idat_size)
+               png_error(png_ptr, "Extra compressed data");
+            png_ptr->mode |= PNG_AFTER_IDAT;
+            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+            break;
+         }
+         if (ret != Z_OK)
+            png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
+                      "Decompression Error");
+
+         if (!(png_ptr->zstream.avail_out))
+            png_error(png_ptr, "Extra compressed data");
+
+      }
+      png_ptr->zstream.avail_out = 0;
+   }
+
+   if (png_ptr->idat_size || png_ptr->zstream.avail_in)
+      png_error(png_ptr, "Extra compression data");
+
+   inflateReset(&png_ptr->zstream);
+
+   png_ptr->mode |= PNG_AFTER_IDAT;
+}
+
+void /* PRIVATE */
+png_read_start_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+   /* start of interlace block in the y direction */
+   const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+   /* offset to next interlace block in the y direction */
+   const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+   int max_pixel_depth;
+   png_uint_32 row_bytes;
+
+   png_debug(1, "in png_read_start_row\n");
+   png_ptr->zstream.avail_in = 0;
+   png_init_read_transformations(png_ptr);
+   if (png_ptr->interlaced)
+   {
+      if (!(png_ptr->transformations & PNG_INTERLACE))
+         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
+            png_pass_ystart[0]) / png_pass_yinc[0];
+      else
+         png_ptr->num_rows = png_ptr->height;
+
+      png_ptr->iwidth = (png_ptr->width +
+         png_pass_inc[png_ptr->pass] - 1 -
+         png_pass_start[png_ptr->pass]) /
+         png_pass_inc[png_ptr->pass];
+
+         row_bytes = ((png_ptr->iwidth *
+            (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
+         png_ptr->irowbytes = (png_size_t)row_bytes;
+         if((png_uint_32)png_ptr->irowbytes != row_bytes)
+            png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
+   }
+   else
+   {
+      png_ptr->num_rows = png_ptr->height;
+      png_ptr->iwidth = png_ptr->width;
+      png_ptr->irowbytes = png_ptr->rowbytes + 1;
+   }
+   max_pixel_depth = png_ptr->pixel_depth;
+
+#if defined(PNG_READ_PACK_SUPPORTED)
+   if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
+      max_pixel_depth = 8;
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+   if (png_ptr->transformations & PNG_EXPAND)
+   {
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         if (png_ptr->num_trans)
+            max_pixel_depth = 32;
+         else
+            max_pixel_depth = 24;
+      }
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+      {
+         if (max_pixel_depth < 8)
+            max_pixel_depth = 8;
+         if (png_ptr->num_trans)
+            max_pixel_depth *= 2;
+      }
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+      {
+         if (png_ptr->num_trans)
+         {
+            max_pixel_depth *= 4;
+            max_pixel_depth /= 3;
+         }
+      }
+   }
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED)
+   if (png_ptr->transformations & (PNG_FILLER))
+   {
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+         max_pixel_depth = 32;
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+      {
+         if (max_pixel_depth <= 8)
+            max_pixel_depth = 16;
+         else
+            max_pixel_depth = 32;
+      }
+      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+      {
+         if (max_pixel_depth <= 32)
+            max_pixel_depth = 32;
+         else
+            max_pixel_depth = 64;
+      }
+   }
+#endif
+
+#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+   {
+      if (
+#if defined(PNG_READ_EXPAND_SUPPORTED)
+        (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
+#endif
+#if defined(PNG_READ_FILLER_SUPPORTED)
+        (png_ptr->transformations & (PNG_FILLER)) ||
+#endif
+        png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         if (max_pixel_depth <= 16)
+            max_pixel_depth = 32;
+         else
+            max_pixel_depth = 64;
+      }
+      else
+      {
+         if (max_pixel_depth <= 8)
+           {
+             if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+               max_pixel_depth = 32;
+             else
+               max_pixel_depth = 24;
+           }
+         else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+            max_pixel_depth = 64;
+         else
+            max_pixel_depth = 48;
+      }
+   }
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
+defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+   if(png_ptr->transformations & PNG_USER_TRANSFORM)
+     {
+       int user_pixel_depth=png_ptr->user_transform_depth*
+         png_ptr->user_transform_channels;
+       if(user_pixel_depth > max_pixel_depth)
+         max_pixel_depth=user_pixel_depth;
+     }
+#endif
+
+   /* align the width on the next larger 8 pixels.  Mainly used
+      for interlacing */
+   row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
+   /* calculate the maximum bytes needed, adding a byte and a pixel
+      for safety's sake */
+   row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
+      1 + ((max_pixel_depth + 7) >> 3);
+#ifdef PNG_MAX_MALLOC_64K
+   if (row_bytes > (png_uint_32)65536L)
+      png_error(png_ptr, "This image requires a row greater than 64KB");
+#endif
+   png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
+   png_ptr->row_buf = png_ptr->big_row_buf+32;
+#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
+   png_ptr->row_buf_size = row_bytes;
+#endif
+
+#ifdef PNG_MAX_MALLOC_64K
+   if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
+      png_error(png_ptr, "This image requires a row greater than 64KB");
+#endif
+   png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
+      png_ptr->rowbytes + 1));
+
+   png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+
+   png_debug1(3, "width = %lu,\n", png_ptr->width);
+   png_debug1(3, "height = %lu,\n", png_ptr->height);
+   png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
+   png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
+   png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
+   png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
+
+   png_ptr->flags |= PNG_FLAG_ROW_INIT;
+}
diff --git a/libraries/libpng-1.2.0/pngset.c b/libraries/libpng-1.2.0/pngset.c
new file mode 100644 (file)
index 0000000..8845d38
--- /dev/null
@@ -0,0 +1,1029 @@
+
+/* pngset.c - storage of image information into info struct
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * The functions here are used during reads to store data from the file
+ * into the info struct, and during writes to store application data
+ * into the info struct for writing into the file.  This abstracts the
+ * info struct and allows us to change the structure in the future.
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(PNG_bKGD_SUPPORTED)
+void PNGAPI
+png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)
+{
+   png_debug1(1, "in %s storage function\n", "bKGD");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   png_memcpy(&(info_ptr->background), background, sizeof(png_color_16));
+   info_ptr->valid |= PNG_INFO_bKGD;
+}
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
+   double white_x, double white_y, double red_x, double red_y,
+   double green_x, double green_y, double blue_x, double blue_y)
+{
+   png_debug1(1, "in %s storage function\n", "cHRM");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->x_white = (float)white_x;
+   info_ptr->y_white = (float)white_y;
+   info_ptr->x_red   = (float)red_x;
+   info_ptr->y_red   = (float)red_y;
+   info_ptr->x_green = (float)green_x;
+   info_ptr->y_green = (float)green_y;
+   info_ptr->x_blue  = (float)blue_x;
+   info_ptr->y_blue  = (float)blue_y;
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5);
+   info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5);
+   info_ptr->int_x_red   = (png_fixed_point)(red_x*100000.+0.5);
+   info_ptr->int_y_red   = (png_fixed_point)(red_y*100000.+0.5);
+   info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5);
+   info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5);
+   info_ptr->int_x_blue  = (png_fixed_point)(blue_x*100000.+0.5);
+   info_ptr->int_y_blue  = (png_fixed_point)(blue_y*100000.+0.5);
+#endif
+   info_ptr->valid |= PNG_INFO_cHRM;
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void PNGAPI
+png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
+   png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
+   png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
+   png_fixed_point blue_x, png_fixed_point blue_y)
+{
+   png_debug1(1, "in %s storage function\n", "cHRM");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->int_x_white = white_x;
+   info_ptr->int_y_white = white_y;
+   info_ptr->int_x_red   = red_x;
+   info_ptr->int_y_red   = red_y;
+   info_ptr->int_x_green = green_x;
+   info_ptr->int_y_green = green_y;
+   info_ptr->int_x_blue  = blue_x;
+   info_ptr->int_y_blue  = blue_y;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   info_ptr->x_white = (float)(white_x/100000.);
+   info_ptr->y_white = (float)(white_y/100000.);
+   info_ptr->x_red   = (float)(red_x/100000.);
+   info_ptr->y_red   = (float)(red_y/100000.);
+   info_ptr->x_green = (float)(green_x/100000.);
+   info_ptr->y_green = (float)(green_y/100000.);
+   info_ptr->x_blue  = (float)(blue_x/100000.);
+   info_ptr->y_blue  = (float)(blue_y/100000.);
+#endif
+   info_ptr->valid |= PNG_INFO_cHRM;
+}
+#endif
+#endif
+
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
+{
+   png_debug1(1, "in %s storage function\n", "gAMA");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->gamma = (float)file_gamma;
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   info_ptr->int_gamma = (int)(file_gamma*100000.+.5);
+#endif
+   info_ptr->valid |= PNG_INFO_gAMA;
+   if(file_gamma == 0.0)
+      png_warning(png_ptr, "Setting gamma=0");
+}
+#endif
+void PNGAPI
+png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
+   int_gamma)
+{
+   png_debug1(1, "in %s storage function\n", "gAMA");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   info_ptr->gamma = (float)(int_gamma/100000.);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   info_ptr->int_gamma = int_gamma;
+#endif
+   info_ptr->valid |= PNG_INFO_gAMA;
+   if(int_gamma == 0)
+      png_warning(png_ptr, "Setting gamma=0");
+}
+#endif
+
+#if defined(PNG_hIST_SUPPORTED)
+void PNGAPI
+png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist)
+{
+   int i;
+
+   png_debug1(1, "in %s storage function\n", "hIST");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+   if (info_ptr->num_palette == 0)
+   {
+       png_warning(png_ptr,
+          "Palette size 0, hIST allocation skipped.");
+       return;
+   }
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
+#endif
+   png_ptr->hist = (png_uint_16p)png_malloc(png_ptr,
+      (png_uint_32)(info_ptr->num_palette * sizeof (png_uint_16)));
+
+   for (i = 0; i < info_ptr->num_palette; i++)
+       png_ptr->hist[i] = hist[i];
+   info_ptr->hist = png_ptr->hist;
+   info_ptr->valid |= PNG_INFO_hIST;
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   info_ptr->free_me |= PNG_FREE_HIST;
+#else
+   png_ptr->flags |= PNG_FLAG_FREE_HIST;
+#endif
+}
+#endif
+
+void PNGAPI
+png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 width, png_uint_32 height, int bit_depth,
+   int color_type, int interlace_type, int compression_type,
+   int filter_type)
+{
+   int rowbytes_per_pixel;
+   png_debug1(1, "in %s storage function\n", "IHDR");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   /* check for width and height valid values */
+   if (width == 0 || height == 0)
+      png_error(png_ptr, "Image width or height is zero in IHDR");
+   if (width > PNG_MAX_UINT || height > PNG_MAX_UINT)
+      png_error(png_ptr, "Invalid image size in IHDR");
+
+   /* check other values */
+   if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
+      bit_depth != 8 && bit_depth != 16)
+      png_error(png_ptr, "Invalid bit depth in IHDR");
+
+   if (color_type < 0 || color_type == 1 ||
+      color_type == 5 || color_type > 6)
+      png_error(png_ptr, "Invalid color type in IHDR");
+
+   if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
+       ((color_type == PNG_COLOR_TYPE_RGB ||
+         color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
+         color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
+      png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");
+
+   if (interlace_type >= PNG_INTERLACE_LAST)
+      png_error(png_ptr, "Unknown interlace method in IHDR");
+
+   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+      png_error(png_ptr, "Unknown compression method in IHDR");
+
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   /* Accept filter_method 64 (intrapixel differencing) only if
+    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+    * 2. Libpng did not read a PNG signature (this filter_method is only
+    *    used in PNG datastreams that are embedded in MNG datastreams) and
+    * 3. The application called png_permit_mng_features with a mask that
+    *    included PNG_FLAG_MNG_FILTER_64 and
+    * 4. The filter_method is 64 and
+    * 5. The color_type is RGB or RGBA
+    */
+   if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
+      png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n");
+   if(filter_type != PNG_FILTER_TYPE_BASE)
+   {
+     if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+        (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
+        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
+        (color_type == PNG_COLOR_TYPE_RGB || 
+         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
+        png_error(png_ptr, "Unknown filter method in IHDR");
+     if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
+        png_warning(png_ptr, "Invalid filter method in IHDR");
+   }
+#else
+   if(filter_type != PNG_FILTER_TYPE_BASE)
+      png_error(png_ptr, "Unknown filter method in IHDR");
+#endif
+
+   info_ptr->width = width;
+   info_ptr->height = height;
+   info_ptr->bit_depth = (png_byte)bit_depth;
+   info_ptr->color_type =(png_byte) color_type;
+   info_ptr->compression_type = (png_byte)compression_type;
+   info_ptr->filter_type = (png_byte)filter_type;
+   info_ptr->interlace_type = (png_byte)interlace_type;
+   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      info_ptr->channels = 1;
+   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+      info_ptr->channels = 3;
+   else
+      info_ptr->channels = 1;
+   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+      info_ptr->channels++;
+   info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
+
+   /* check for overflow */
+   rowbytes_per_pixel = (info_ptr->pixel_depth + 7) >> 3;
+   if (( width > PNG_MAX_UINT/rowbytes_per_pixel))
+   {
+      png_warning(png_ptr,
+         "Width too large to process image data; rowbytes will overflow.");
+      info_ptr->rowbytes = (png_size_t)0;
+   }
+   else
+      info_ptr->rowbytes = (info_ptr->width * info_ptr->pixel_depth + 7) >> 3;
+}
+
+#if defined(PNG_oFFs_SUPPORTED)
+void PNGAPI
+png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
+   png_int_32 offset_x, png_int_32 offset_y, int unit_type)
+{
+   png_debug1(1, "in %s storage function\n", "oFFs");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->x_offset = offset_x;
+   info_ptr->y_offset = offset_y;
+   info_ptr->offset_unit_type = (png_byte)unit_type;
+   info_ptr->valid |= PNG_INFO_oFFs;
+}
+#endif
+
+#if defined(PNG_pCAL_SUPPORTED)
+void PNGAPI
+png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
+   png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
+   png_charp units, png_charpp params)
+{
+   png_uint_32 length;
+   int i;
+
+   png_debug1(1, "in %s storage function\n", "pCAL");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   length = png_strlen(purpose) + 1;
+   png_debug1(3, "allocating purpose for info (%lu bytes)\n", length);
+   info_ptr->pcal_purpose = (png_charp)png_malloc(png_ptr, length);
+   png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length);
+
+   png_debug(3, "storing X0, X1, type, and nparams in info\n");
+   info_ptr->pcal_X0 = X0;
+   info_ptr->pcal_X1 = X1;
+   info_ptr->pcal_type = (png_byte)type;
+   info_ptr->pcal_nparams = (png_byte)nparams;
+
+   length = png_strlen(units) + 1;
+   png_debug1(3, "allocating units for info (%lu bytes)\n", length);
+   info_ptr->pcal_units = (png_charp)png_malloc(png_ptr, length);
+   png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
+
+   info_ptr->pcal_params = (png_charpp)png_malloc(png_ptr,
+      (png_uint_32)((nparams + 1) * sizeof(png_charp)));
+
+   info_ptr->pcal_params[nparams] = NULL;
+
+   for (i = 0; i < nparams; i++)
+   {
+      length = png_strlen(params[i]) + 1;
+      png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length);
+      info_ptr->pcal_params[i] = (png_charp)png_malloc(png_ptr, length);
+      png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length);
+   }
+
+   info_ptr->valid |= PNG_INFO_pCAL;
+#ifdef PNG_FREE_ME_SUPPORTED
+   info_ptr->free_me |= PNG_FREE_PCAL;
+#endif
+}
+#endif
+
+#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_sCAL(png_structp png_ptr, png_infop info_ptr,
+             int unit, double width, double height)
+{
+   png_debug1(1, "in %s storage function\n", "sCAL");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->scal_unit = (png_byte)unit;
+   info_ptr->scal_pixel_width = width;
+   info_ptr->scal_pixel_height = height;
+
+   info_ptr->valid |= PNG_INFO_sCAL;
+}
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void PNGAPI
+png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
+             int unit, png_charp swidth, png_charp sheight)
+{
+   png_uint_32 length;
+
+   png_debug1(1, "in %s storage function\n", "sCAL");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->scal_unit = (png_byte)unit;
+
+   length = png_strlen(swidth) + 1;
+   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
+   info_ptr->scal_s_width = (png_charp)png_malloc(png_ptr, length);
+   png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length);
+
+   length = png_strlen(sheight) + 1;
+   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
+   info_ptr->scal_s_height = (png_charp)png_malloc(png_ptr, length);
+   png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length);
+
+   info_ptr->valid |= PNG_INFO_sCAL;
+#ifdef PNG_FREE_ME_SUPPORTED
+   info_ptr->free_me |= PNG_FREE_SCAL;
+#endif
+}
+#endif
+#endif
+#endif
+
+#if defined(PNG_pHYs_SUPPORTED)
+void PNGAPI
+png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
+   png_uint_32 res_x, png_uint_32 res_y, int unit_type)
+{
+   png_debug1(1, "in %s storage function\n", "pHYs");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->x_pixels_per_unit = res_x;
+   info_ptr->y_pixels_per_unit = res_y;
+   info_ptr->phys_unit_type = (png_byte)unit_type;
+   info_ptr->valid |= PNG_INFO_pHYs;
+}
+#endif
+
+void PNGAPI
+png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
+   png_colorp palette, int num_palette)
+{
+
+   png_debug1(1, "in %s storage function\n", "PLTE");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   /*
+    * It may not actually be necessary to set png_ptr->palette here;
+    * we do it for backward compatibility with the way the png_handle_tRNS
+    * function used to do the allocation.
+    */
+#ifdef PNG_FREE_ME_SUPPORTED
+   png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
+#endif
+   png_ptr->palette = (png_colorp)png_zalloc(png_ptr, (uInt)num_palette,
+      sizeof (png_color));
+   png_memcpy(png_ptr->palette, palette, num_palette * sizeof (png_color));
+   info_ptr->palette = png_ptr->palette;
+   info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
+
+#ifdef PNG_FREE_ME_SUPPORTED
+   info_ptr->free_me |= PNG_FREE_PLTE;
+#else
+   png_ptr->flags |= PNG_FLAG_FREE_PLTE;
+#endif
+
+   info_ptr->valid |= PNG_INFO_PLTE;
+}
+
+#if defined(PNG_sBIT_SUPPORTED)
+void PNGAPI
+png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
+   png_color_8p sig_bit)
+{
+   png_debug1(1, "in %s storage function\n", "sBIT");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   png_memcpy(&(info_ptr->sig_bit), sig_bit, sizeof (png_color_8));
+   info_ptr->valid |= PNG_INFO_sBIT;
+}
+#endif
+
+#if defined(PNG_sRGB_SUPPORTED)
+void PNGAPI
+png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent)
+{
+   png_debug1(1, "in %s storage function\n", "sRGB");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->srgb_intent = (png_byte)intent;
+   info_ptr->valid |= PNG_INFO_sRGB;
+}
+
+void PNGAPI
+png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
+   int intent)
+{
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float file_gamma;
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_fixed_point int_file_gamma;
+#endif
+#endif
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
+      int_green_y, int_blue_x, int_blue_y;
+#endif
+#endif
+   png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   png_set_sRGB(png_ptr, info_ptr, intent);
+
+#if defined(PNG_gAMA_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   file_gamma = (float).45455;
+   png_set_gAMA(png_ptr, info_ptr, file_gamma);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   int_file_gamma = 45455L;
+   png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma);
+#endif
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED)
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   int_white_x = 31270L;
+   int_white_y = 32900L;
+   int_red_x   = 64000L;
+   int_red_y   = 33000L;
+   int_green_x = 30000L;
+   int_green_y = 60000L;
+   int_blue_x  = 15000L;
+   int_blue_y  =  6000L;
+
+   png_set_cHRM_fixed(png_ptr, info_ptr,
+      int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y,
+      int_blue_x, int_blue_y);
+#endif
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   white_x = (float).3127;
+   white_y = (float).3290;
+   red_x   = (float).64;
+   red_y   = (float).33;
+   green_x = (float).30;
+   green_y = (float).60;
+   blue_x  = (float).15;
+   blue_y  = (float).06;
+
+   png_set_cHRM(png_ptr, info_ptr,
+      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
+#endif
+#endif
+}
+#endif
+
+
+#if defined(PNG_iCCP_SUPPORTED)
+void PNGAPI
+png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
+             png_charp name, int compression_type,
+             png_charp profile, png_uint_32 proflen)
+{
+   png_charp new_iccp_name;
+   png_charp new_iccp_profile;
+
+   png_debug1(1, "in %s storage function\n", "iCCP");
+   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
+      return;
+
+   new_iccp_name = (png_charp)png_malloc(png_ptr, png_strlen(name)+1);
+   png_strcpy(new_iccp_name, name);
+   new_iccp_profile = (png_charp)png_malloc(png_ptr, proflen);
+   png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);
+
+   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
+
+   info_ptr->iccp_proflen = proflen;
+   info_ptr->iccp_name = new_iccp_name;
+   info_ptr->iccp_profile = new_iccp_profile;
+   /* Compression is always zero but is here so the API and info structure
+    * does not have to change if we introduce multiple compression types */
+   info_ptr->iccp_compression = (png_byte)compression_type;
+#ifdef PNG_FREE_ME_SUPPORTED
+   info_ptr->free_me |= PNG_FREE_ICCP;
+#endif
+   info_ptr->valid |= PNG_INFO_iCCP;
+}
+#endif
+
+#if defined(PNG_TEXT_SUPPORTED)
+void PNGAPI
+png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
+   int num_text)
+{
+   int i;
+
+   png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ?
+      "text" : (png_const_charp)png_ptr->chunk_name));
+
+   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
+      return;
+
+   /* Make sure we have enough space in the "text" array in info_struct
+    * to hold all of the incoming text_ptr objects.
+    */
+   if (info_ptr->num_text + num_text > info_ptr->max_text)
+   {
+      if (info_ptr->text != NULL)
+      {
+         png_textp old_text;
+         int old_max;
+
+         old_max = info_ptr->max_text;
+         info_ptr->max_text = info_ptr->num_text + num_text + 8;
+         old_text = info_ptr->text;
+         info_ptr->text = (png_textp)png_malloc(png_ptr,
+            (png_uint_32)(info_ptr->max_text * sizeof (png_text)));
+         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
+            sizeof(png_text)));
+         png_free(png_ptr, old_text);
+      }
+      else
+      {
+         info_ptr->max_text = num_text + 8;
+         info_ptr->num_text = 0;
+         info_ptr->text = (png_textp)png_malloc(png_ptr,
+            (png_uint_32)(info_ptr->max_text * sizeof (png_text)));
+#ifdef PNG_FREE_ME_SUPPORTED
+         info_ptr->free_me |= PNG_FREE_TEXT;
+#endif
+      }
+      png_debug1(3, "allocated %d entries for info_ptr->text\n",
+         info_ptr->max_text);
+   }
+   for (i = 0; i < num_text; i++)
+   {
+      png_size_t text_length,key_len;
+      png_size_t lang_len,lang_key_len;
+      png_textp textp = &(info_ptr->text[info_ptr->num_text]);
+
+      if (text_ptr[i].key == NULL)
+          continue;
+
+      key_len = png_strlen(text_ptr[i].key);
+
+      if(text_ptr[i].compression <= 0)
+      {
+        lang_len = 0;
+        lang_key_len = 0;
+      }
+      else
+#ifdef PNG_iTXt_SUPPORTED
+      {
+        /* set iTXt data */
+        if (text_ptr[i].key != NULL)
+          lang_len = png_strlen(text_ptr[i].lang);
+        else
+          lang_len = 0;
+        if (text_ptr[i].lang_key != NULL)
+          lang_key_len = png_strlen(text_ptr[i].lang_key);
+        else
+          lang_key_len = 0;
+      }
+#else
+      {
+        png_warning(png_ptr, "iTXt chunk not supported.");
+        continue;
+      }
+#endif
+
+      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
+      {
+         text_length = 0;
+#ifdef PNG_iTXt_SUPPORTED
+         if(text_ptr[i].compression > 0)
+            textp->compression = PNG_ITXT_COMPRESSION_NONE;
+         else
+#endif
+            textp->compression = PNG_TEXT_COMPRESSION_NONE;
+      }
+      else
+      {
+         text_length = png_strlen(text_ptr[i].text);
+         textp->compression = text_ptr[i].compression;
+      }
+
+      textp->key = (png_charp)png_malloc(png_ptr,
+         (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4));
+      png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n",
+         (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4),
+         (int)textp->key);
+
+      png_memcpy(textp->key, text_ptr[i].key,
+         (png_size_t)(key_len));
+      *(textp->key+key_len) = '\0';
+#ifdef PNG_iTXt_SUPPORTED
+      if (text_ptr[i].compression > 0)
+      {
+         textp->lang=textp->key + key_len + 1;
+         png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
+         *(textp->lang+lang_len) = '\0';
+         textp->lang_key=textp->lang + lang_len + 1;
+         png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
+         *(textp->lang_key+lang_key_len) = '\0';
+         textp->text=textp->lang_key + lang_key_len + 1;
+      }
+      else
+#endif
+      {
+#ifdef PNG_iTXt_SUPPORTED
+         textp->lang=(png_charp)NULL;
+         textp->lang_key=(png_charp)NULL;
+#endif
+         textp->text=textp->key + key_len + 1;
+      }
+      if(text_length)
+         png_memcpy(textp->text, text_ptr[i].text,
+            (png_size_t)(text_length));
+      *(textp->text+text_length) = '\0';
+
+#ifdef PNG_iTXt_SUPPORTED
+      if(textp->compression > 0)
+      {
+         textp->text_length = 0;
+         textp->itxt_length = text_length;
+      }
+      else
+#endif
+      {
+         textp->text_length = text_length;
+#ifdef PNG_iTXt_SUPPORTED
+         textp->itxt_length = 0;
+#endif
+      }
+      info_ptr->text[info_ptr->num_text]= *textp;
+      info_ptr->num_text++;
+      png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text);
+   }
+}
+#endif
+
+#if defined(PNG_tIME_SUPPORTED)
+void PNGAPI
+png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
+{
+   png_debug1(1, "in %s storage function\n", "tIME");
+   if (png_ptr == NULL || info_ptr == NULL ||
+       (png_ptr->mode & PNG_WROTE_tIME))
+      return;
+
+   png_memcpy(&(info_ptr->mod_time), mod_time, sizeof (png_time));
+   info_ptr->valid |= PNG_INFO_tIME;
+}
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED)
+void PNGAPI
+png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
+   png_bytep trans, int num_trans, png_color_16p trans_values)
+{
+   png_debug1(1, "in %s storage function\n", "tRNS");
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   if (trans != NULL)
+   {
+       /*
+       * It may not actually be necessary to set png_ptr->trans here;
+       * we do it for backward compatibility with the way the png_handle_tRNS
+       * function used to do the allocation.
+       */
+#ifdef PNG_FREE_ME_SUPPORTED
+       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
+#endif
+       png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
+           (png_uint_32)num_trans);
+       png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans);
+#ifdef PNG_FREE_ME_SUPPORTED
+       info_ptr->free_me |= PNG_FREE_TRNS;
+#else
+       png_ptr->flags |= PNG_FLAG_FREE_TRNS;
+#endif
+   }
+
+   if (trans_values != NULL)
+   {
+      png_memcpy(&(info_ptr->trans_values), trans_values,
+         sizeof(png_color_16));
+      if (num_trans == 0)
+        num_trans = 1;
+   }
+   info_ptr->num_trans = (png_uint_16)num_trans;
+   info_ptr->valid |= PNG_INFO_tRNS;
+}
+#endif
+
+#if defined(PNG_sPLT_SUPPORTED)
+void PNGAPI
+png_set_sPLT(png_structp png_ptr,
+             png_infop info_ptr, png_sPLT_tp entries, int nentries)
+{
+    png_sPLT_tp np;
+    int i;
+
+    np = (png_sPLT_tp)png_malloc(png_ptr,
+        (info_ptr->splt_palettes_num + nentries) * sizeof(png_sPLT_t));
+
+    png_memcpy(np, info_ptr->splt_palettes,
+           info_ptr->splt_palettes_num * sizeof(png_sPLT_t));
+    png_free(png_ptr, info_ptr->splt_palettes);
+    info_ptr->splt_palettes=NULL;
+
+    for (i = 0; i < nentries; i++)
+    {
+        png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
+        png_sPLT_tp from = entries + i;
+
+        to->name = (png_charp)png_malloc(png_ptr,
+            png_strlen(from->name) + 1);
+        png_strcpy(to->name, from->name);
+        to->entries = (png_sPLT_entryp)png_malloc(png_ptr,
+            from->nentries * sizeof(png_sPLT_t));
+        png_memcpy(to->entries, from->entries,
+            from->nentries * sizeof(png_sPLT_t));
+        to->nentries = from->nentries;
+        to->depth = from->depth;
+    }
+
+    info_ptr->splt_palettes = np;
+    info_ptr->splt_palettes_num += nentries;
+    info_ptr->valid |= PNG_INFO_sPLT;
+#ifdef PNG_FREE_ME_SUPPORTED
+    info_ptr->free_me |= PNG_FREE_SPLT;
+#endif
+}
+#endif /* PNG_sPLT_SUPPORTED */
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+void PNGAPI
+png_set_unknown_chunks(png_structp png_ptr,
+   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
+{
+    png_unknown_chunkp np;
+    int i;
+
+    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
+        return;
+
+    np = (png_unknown_chunkp)png_malloc(png_ptr,
+        (info_ptr->unknown_chunks_num + num_unknowns) *
+        sizeof(png_unknown_chunk));
+
+    png_memcpy(np, info_ptr->unknown_chunks,
+           info_ptr->unknown_chunks_num * sizeof(png_unknown_chunk));
+    png_free(png_ptr, info_ptr->unknown_chunks);
+    info_ptr->unknown_chunks=NULL;
+
+    for (i = 0; i < num_unknowns; i++)
+    {
+        png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
+        png_unknown_chunkp from = unknowns + i;
+
+        png_strcpy((png_charp)to->name, (png_charp)from->name);
+        to->data = (png_bytep)png_malloc(png_ptr, from->size);
+        png_memcpy(to->data, from->data, from->size);
+        to->size = from->size;
+
+        /* note our location in the read or write sequence */
+        to->location = (png_byte)(png_ptr->mode & 0xff);
+    }
+
+    info_ptr->unknown_chunks = np;
+    info_ptr->unknown_chunks_num += num_unknowns;
+#ifdef PNG_FREE_ME_SUPPORTED
+    info_ptr->free_me |= PNG_FREE_UNKN;
+#endif
+}
+void PNGAPI
+png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
+   int chunk, int location)
+{
+   if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
+         (int)info_ptr->unknown_chunks_num)
+      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
+}
+#endif
+
+#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
+    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+void PNGAPI
+png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
+{
+   /* This function is deprecated in favor of png_permit_mng_features()
+      and will be removed from libpng-2.0.0 */
+   png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n");
+   if (png_ptr == NULL)
+      return;
+   png_ptr->mng_features_permitted = (png_byte)
+     ((png_ptr->mng_features_permitted & (~(PNG_FLAG_MNG_EMPTY_PLTE))) |
+     ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE)));
+}
+#endif
+
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+png_uint_32 PNGAPI
+png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
+{
+   png_debug(1, "in png_permit_mng_features\n");
+   if (png_ptr == NULL)
+      return (png_uint_32)0;
+   png_ptr->mng_features_permitted =
+     (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
+   return (png_uint_32)png_ptr->mng_features_permitted;
+}
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+void PNGAPI
+png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep
+   chunk_list, int num_chunks)
+{
+    png_bytep new_list, p;
+    int i, old_num_chunks;
+    if (num_chunks == 0)
+    {
+      if(keep == HANDLE_CHUNK_ALWAYS || keep == HANDLE_CHUNK_IF_SAFE)
+        png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+      else
+        png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+
+      if(keep == HANDLE_CHUNK_ALWAYS)
+        png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+      else
+        png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+      return;
+    }
+    if (chunk_list == NULL)
+      return;
+    old_num_chunks=png_ptr->num_chunk_list;
+    new_list=(png_bytep)png_malloc(png_ptr,
+       (png_uint_32)(5*(num_chunks+old_num_chunks)));
+    if(png_ptr->chunk_list != NULL)
+    {
+       png_memcpy(new_list, png_ptr->chunk_list,
+          (png_size_t)(5*old_num_chunks));
+       png_free(png_ptr, png_ptr->chunk_list);
+       png_ptr->chunk_list=NULL;
+    }
+    png_memcpy(new_list+5*old_num_chunks, chunk_list,
+       (png_size_t)(5*num_chunks));
+    for (p=new_list+5*old_num_chunks+4, i=0; i<num_chunks; i++, p+=5)
+       *p=(png_byte)keep;
+    png_ptr->num_chunk_list=old_num_chunks+num_chunks;
+    png_ptr->chunk_list=new_list;
+#ifdef PNG_FREE_ME_SUPPORTED
+    png_ptr->free_me |= PNG_FREE_LIST;
+#endif
+}
+#endif
+
+#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
+void PNGAPI
+png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
+   png_user_chunk_ptr read_user_chunk_fn)
+{
+   png_debug(1, "in png_set_read_user_chunk_fn\n");
+   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
+   png_ptr->user_chunk_ptr = user_chunk_ptr;
+}
+#endif
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+void PNGAPI
+png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
+{
+   png_debug1(1, "in %s storage function\n", "rows");
+
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
+      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
+   info_ptr->row_pointers = row_pointers;
+   if(row_pointers)
+      info_ptr->valid |= PNG_INFO_IDAT;
+}
+#endif
+
+void PNGAPI
+png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size)
+{
+    if(png_ptr->zbuf)
+       png_free(png_ptr, png_ptr->zbuf);
+    png_ptr->zbuf_size = (png_size_t)size;
+    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
+    png_ptr->zstream.next_out = png_ptr->zbuf;
+    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+}
+
+void PNGAPI
+png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
+{
+   if (png_ptr && info_ptr)
+      info_ptr->valid &= ~(mask);
+}
+
+
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+/* this function was added to libpng 1.2.0 and should always exist by default */
+void PNGAPI
+png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags)
+{
+    png_uint_32 settable_asm_flags;
+    png_uint_32 settable_mmx_flags;
+
+    settable_mmx_flags =
+#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW
+                         PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  |
+#endif
+#ifdef PNG_HAVE_ASSEMBLER_READ_INTERLACE
+                         PNG_ASM_FLAG_MMX_READ_INTERLACE    |
+#endif
+#ifdef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
+                         PNG_ASM_FLAG_MMX_READ_FILTER_SUB   |
+                         PNG_ASM_FLAG_MMX_READ_FILTER_UP    |
+                         PNG_ASM_FLAG_MMX_READ_FILTER_AVG   |
+                         PNG_ASM_FLAG_MMX_READ_FILTER_PAETH |
+#endif
+                         0;
+
+    /* could be some non-MMX ones in the future, but not currently: */
+    settable_asm_flags = settable_mmx_flags;
+
+    if (!(png_ptr->asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_COMPILED) ||
+        !(png_ptr->asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU))
+    {
+        /* clear all MMX flags if MMX isn't supported */
+        settable_asm_flags &= ~settable_mmx_flags;
+        png_ptr->asm_flags &= ~settable_mmx_flags;
+    }
+
+    /* we're replacing the settable bits with those passed in by the user,
+     * so first zero them out of the master copy, then logical-OR in the
+     * allowed subset that was requested */
+
+    png_ptr->asm_flags &= ~settable_asm_flags;                 /* zero them */
+    png_ptr->asm_flags |= (asm_flags & settable_asm_flags);    /* set them */
+}
+#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
+
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+/* this function was added to libpng 1.2.0 */
+void PNGAPI
+png_set_mmx_thresholds (png_structp png_ptr,
+                        png_byte mmx_bitdepth_threshold,
+                        png_uint_32 mmx_rowbytes_threshold)
+{
+    png_ptr->mmx_bitdepth_threshold = mmx_bitdepth_threshold;
+    png_ptr->mmx_rowbytes_threshold = mmx_rowbytes_threshold;
+}
+#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
diff --git a/libraries/libpng-1.2.0/pngtest.c b/libraries/libpng-1.2.0/pngtest.c
new file mode 100644 (file)
index 0000000..5ed1b33
--- /dev/null
@@ -0,0 +1,1513 @@
+
+/* pngtest.c - a simple test program to test libpng
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This program reads in a PNG image, writes it out again, and then
+ * compares the two files.  If the files are identical, this shows that
+ * the basic chunk handling, filtering, and (de)compression code is working
+ * properly.  It does not currently test all of the transforms, although
+ * it probably should.
+ *
+ * The program will report "FAIL" in certain legitimate cases:
+ * 1) when the compression level or filter selection method is changed.
+ * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192.
+ * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks
+ *    exist in the input file.
+ * 4) others not listed here...
+ * In these cases, it is best to check with another tool such as "pngcheck"
+ * to see what the differences between the two files are.
+ *
+ * If a filename is given on the command-line, then this file is used
+ * for the input, rather than the default "pngtest.png".  This allows
+ * testing a wide variety of files easily.  You can also test a number
+ * of files at once by typing "pngtest -m file1.png file2.png ..."
+ */
+
+#if defined(_WIN32_WCE)
+#  if _WIN32_WCE < 211
+     __error__ (f|w)printf functions are not supported on old WindowsCE.;
+#  endif
+#  include <windows.h>
+#  include <stdlib.h>
+#  define READFILE(file, data, length, check) \
+     if (ReadFile(file, data, length, &check,NULL)) check = 0
+#  define WRITEFILE(file, data, length, check)) \
+     if (WriteFile(file, data, length, &check, NULL)) check = 0
+#  define FCLOSE(file) CloseHandle(file)
+#else
+#  include <stdio.h>
+#  include <stdlib.h>
+#  include <assert.h>
+#  define READFILE(file, data, length, check) \
+     check=(png_size_t)fread(data,(png_size_t)1,length,file)
+#  define WRITEFILE(file, data, length, check) \
+     check=(png_size_t)fwrite(data,(png_size_t)1, length, file)
+#  define FCLOSE(file) fclose(file)
+#endif
+
+#if defined(PNG_NO_STDIO)
+#  if defined(_WIN32_WCE)
+     typedef HANDLE                png_FILE_p;
+#  else
+     typedef FILE                * png_FILE_p;
+#  endif
+#endif
+
+/* Makes pngtest verbose so we can find problems (needs to be before png.h) */
+#ifndef PNG_DEBUG
+#  define PNG_DEBUG 0
+#endif
+
+#if !PNG_DEBUG
+#  define SINGLE_ROWBUF_ALLOC  /* makes buffer overruns easier to nail */
+#endif
+
+/* Turn on CPU timing
+#define PNGTEST_TIMING
+*/
+
+#ifdef PNG_NO_FLOATING_POINT_SUPPORTED
+#undef PNGTEST_TIMING
+#endif
+
+#ifdef PNGTEST_TIMING
+static float t_start, t_stop, t_decode, t_encode, t_misc;
+#include <time.h>
+#endif
+
+#include "png.h"
+
+/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
+#ifndef png_jmpbuf
+#  define png_jmpbuf(png_ptr) png_ptr->jmpbuf
+#endif
+
+#ifdef PNGTEST_TIMING
+static float t_start, t_stop, t_decode, t_encode, t_misc;
+#if !defined(PNG_tIME_SUPPORTED)
+#include <time.h>
+#endif
+#endif
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+static int tIME_chunk_present=0;
+static char tIME_string[30] = "no tIME chunk present in file";
+#endif
+
+static int verbose = 0;
+
+int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname));
+
+#ifdef __TURBOC__
+#include <mem.h>
+#endif
+
+/* defined so I can write to a file on gui/windowing platforms */
+/*  #define STDERR stderr  */
+#define STDERR stdout   /* for DOS */
+
+/* example of using row callbacks to make a simple progress meter */
+static int status_pass=1;
+static int status_dots_requested=0;
+static int status_dots=1;
+
+void
+read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
+void
+read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
+{
+    if(png_ptr == NULL || row_number > PNG_MAX_UINT) return;
+    if(status_pass != pass)
+    {
+       fprintf(stdout,"\n Pass %d: ",pass);
+       status_pass = pass;
+       status_dots = 31;
+    }
+    status_dots--;
+    if(status_dots == 0)
+    {
+       fprintf(stdout, "\n         ");
+       status_dots=30;
+    }
+    fprintf(stdout, "r");
+}
+
+void
+write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
+void
+write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
+{
+    if(png_ptr == NULL || row_number > PNG_MAX_UINT || pass > 7) return;
+    fprintf(stdout, "w");
+}
+
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+/* Example of using user transform callback (we don't transform anything,
+   but merely examine the row filters.  We set this to 256 rather than
+   5 in case illegal filter values are present.) */
+static png_uint_32 filters_used[256];
+void
+count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data);
+void
+count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data)
+{
+    if(png_ptr != NULL && row_info != NULL)
+      ++filters_used[*(data-1)];
+}
+#endif
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+/* example of using user transform callback (we don't transform anything,
+   but merely count the zero samples) */
+
+static png_uint_32 zero_samples;
+
+void
+count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data);
+void
+count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
+{
+   png_bytep dp = data;
+   if(png_ptr == NULL)return;
+
+   /* contents of row_info:
+    *  png_uint_32 width      width of row
+    *  png_uint_32 rowbytes   number of bytes in row
+    *  png_byte color_type    color type of pixels
+    *  png_byte bit_depth     bit depth of samples
+    *  png_byte channels      number of channels (1-4)
+    *  png_byte pixel_depth   bits per pixel (depth*channels)
+    */
+
+
+    /* counts the number of zero samples (or zero pixels if color_type is 3 */
+
+    if(row_info->color_type == 0 || row_info->color_type == 3)
+    {
+       int pos=0;
+       png_uint_32 n, nstop;
+       for (n=0, nstop=row_info->width; n<nstop; n++)
+       {
+          if(row_info->bit_depth == 1)
+          {
+             if(((*dp << pos++ ) & 0x80) == 0) zero_samples++;
+             if(pos == 8)
+             {
+                pos = 0;
+                dp++;
+             }
+          }
+          if(row_info->bit_depth == 2)
+          {
+             if(((*dp << (pos+=2)) & 0xc0) == 0) zero_samples++;
+             if(pos == 8)
+             {
+                pos = 0;
+                dp++;
+             }
+          }
+          if(row_info->bit_depth == 4)
+          {
+             if(((*dp << (pos+=4)) & 0xf0) == 0) zero_samples++;
+             if(pos == 8)
+             {
+                pos = 0;
+                dp++;
+             }
+          }
+          if(row_info->bit_depth == 8)
+             if(*dp++ == 0) zero_samples++;
+          if(row_info->bit_depth == 16)
+          {
+             if((*dp | *(dp+1)) == 0) zero_samples++;
+             dp+=2;
+          }
+       }
+    }
+    else /* other color types */
+    {
+       png_uint_32 n, nstop;
+       int channel;
+       int color_channels = row_info->channels;
+       if(row_info->color_type > 3)color_channels--;
+
+       for (n=0, nstop=row_info->width; n<nstop; n++)
+       {
+          for (channel = 0; channel < color_channels; channel++)
+          {
+             if(row_info->bit_depth == 8)
+                if(*dp++ == 0) zero_samples++;
+             if(row_info->bit_depth == 16)
+             {
+                if((*dp | *(dp+1)) == 0) zero_samples++;
+                dp+=2;
+             }
+          }
+          if(row_info->color_type > 3)
+          {
+             dp++;
+             if(row_info->bit_depth == 16)dp++;
+          }
+       }
+    }
+}
+#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */
+
+static int wrote_question = 0;
+
+#if defined(PNG_NO_STDIO)
+/* START of code to validate stdio-free compilation */
+/* These copies of the default read/write functions come from pngrio.c and */
+/* pngwio.c.  They allow "don't include stdio" testing of the library. */
+/* This is the function that does the actual reading of data.  If you are
+   not reading from a standard C stream, you should create a replacement
+   read_data function and use it at run time with png_set_read_fn(), rather
+   than changing the library. */
+
+#ifndef USE_FAR_KEYWORD
+static void
+pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_size_t check;
+
+   /* fread() returns 0 on error, so it is OK to store this in a png_size_t
+    * instead of an int, which is what fread() actually returns.
+    */
+   READFILE((png_FILE_p)png_ptr->io_ptr, data, length, check);
+
+   if (check != length)
+   {
+      png_error(png_ptr, "Read Error!");
+   }
+}
+#else
+/* this is the model-independent version. Since the standard I/O library
+   can't handle far buffers in the medium and small models, we have to copy
+   the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void
+pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   int check;
+   png_byte *n_data;
+   png_FILE_p io_ptr;
+
+   /* Check if data really is near. If so, use usual code. */
+   n_data = (png_byte *)CVT_PTR_NOCHECK(data);
+   io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+   if ((png_bytep)n_data == data)
+   {
+      READFILE(io_ptr, n_data, length, check);
+   }
+   else
+   {
+      png_byte buf[NEAR_BUF_SIZE];
+      png_size_t read, remaining, err;
+      check = 0;
+      remaining = length;
+      do
+      {
+         read = MIN(NEAR_BUF_SIZE, remaining);
+         READFILE(io_ptr, buf, 1, err);
+         png_memcpy(data, buf, read); /* copy far buffer to near buffer */
+         if(err != read)
+            break;
+         else
+            check += err;
+         data += read;
+         remaining -= read;
+      }
+      while (remaining != 0);
+   }
+   if (check != length)
+   {
+      png_error(png_ptr, "read Error");
+   }
+}
+#endif /* USE_FAR_KEYWORD */
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+static void
+pngtest_flush(png_structp png_ptr)
+{
+#if !defined(_WIN32_WCE)
+   png_FILE_p io_ptr;
+   io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
+   if (io_ptr != NULL)
+      fflush(io_ptr);
+#endif
+}
+#endif
+
+/* This is the function that does the actual writing of data.  If you are
+   not writing to a standard C stream, you should create a replacement
+   write_data function and use it at run time with png_set_write_fn(), rather
+   than changing the library. */
+#ifndef USE_FAR_KEYWORD
+static void
+pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_uint_32 check;
+
+   WRITEFILE((png_FILE_p)png_ptr->io_ptr,  data, length, check);
+   if (check != length)
+   {
+      png_error(png_ptr, "Write Error");
+   }
+}
+#else
+/* this is the model-independent version. Since the standard I/O library
+   can't handle far buffers in the medium and small models, we have to copy
+   the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void
+pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_uint_32 check;
+   png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
+   png_FILE_p io_ptr;
+
+   /* Check if data really is near. If so, use usual code. */
+   near_data = (png_byte *)CVT_PTR_NOCHECK(data);
+   io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+   if ((png_bytep)near_data == data)
+   {
+      WRITEFILE(io_ptr, near_data, length, check);
+   }
+   else
+   {
+      png_byte buf[NEAR_BUF_SIZE];
+      png_size_t written, remaining, err;
+      check = 0;
+      remaining = length;
+      do
+      {
+         written = MIN(NEAR_BUF_SIZE, remaining);
+         png_memcpy(buf, data, written); /* copy far buffer to near buffer */
+         WRITEFILE(io_ptr, buf, written, err);
+         if (err != written)
+            break;
+         else
+            check += err;
+         data += written;
+         remaining -= written;
+      }
+      while (remaining != 0);
+   }
+   if (check != length)
+   {
+      png_error(png_ptr, "Write Error");
+   }
+}
+
+#endif /* USE_FAR_KEYWORD */
+
+/* This function is called when there is a warning, but the library thinks
+ * it can continue anyway.  Replacement functions don't have to do anything
+ * here if you don't want to.  In the default configuration, png_ptr is
+ * not used, but it is passed in case it may be useful.
+ */
+static void
+pngtest_warning(png_structp png_ptr, png_const_charp message)
+{
+   PNG_CONST char *name = "UNKNOWN (ERROR!)";
+   if (png_ptr != NULL && png_ptr->error_ptr != NULL)
+      name = png_ptr->error_ptr;
+   fprintf(STDERR, "%s: libpng warning: %s\n", name, message);
+}
+
+/* This is the default error handling function.  Note that replacements for
+ * this function MUST NOT RETURN, or the program will likely crash.  This
+ * function is used by default, or if the program supplies NULL for the
+ * error function pointer in png_set_error_fn().
+ */
+static void
+pngtest_error(png_structp png_ptr, png_const_charp message)
+{
+   pngtest_warning(png_ptr, message);
+   /* We can return because png_error calls the default handler, which is
+    * actually OK in this case. */
+}
+#endif /* PNG_NO_STDIO */
+/* END of code to validate stdio-free compilation */
+
+/* START of code to validate memory allocation and deallocation */
+#ifdef PNG_USER_MEM_SUPPORTED
+
+/* Allocate memory.  For reasonable files, size should never exceed
+   64K.  However, zlib may allocate more then 64K if you don't tell
+   it not to.  See zconf.h and png.h for more information.  zlib does
+   need to allocate exactly 64K, so whatever you call here must
+   have the ability to do that.
+
+   This piece of code can be compiled to validate max 64K allocations
+   by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */
+typedef struct memory_information
+{
+   png_uint_32               size;
+   png_voidp                 pointer;
+   struct memory_information FAR *next;
+} memory_information;
+typedef memory_information FAR *memory_infop;
+
+static memory_infop pinformation = NULL;
+static int current_allocation = 0;
+static int maximum_allocation = 0;
+static int total_allocation = 0;
+static int num_allocations = 0;
+
+png_voidp png_debug_malloc PNGARG((png_structp png_ptr, png_uint_32 size));
+void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr));
+
+png_voidp
+png_debug_malloc(png_structp png_ptr, png_uint_32 size)
+{
+
+   /* png_malloc has already tested for NULL; png_create_struct calls
+      png_debug_malloc directly, with png_ptr == NULL which is OK */
+
+   if (size == 0)
+      return (png_voidp)(NULL);
+
+   /* This calls the library allocator twice, once to get the requested
+      buffer and once to get a new free list entry. */
+   {
+      memory_infop pinfo = (memory_infop)png_malloc_default(png_ptr,
+         (png_uint_32)sizeof *pinfo);
+      pinfo->size = size;
+      current_allocation += size;
+      total_allocation += size;
+      num_allocations ++;
+      if (current_allocation > maximum_allocation)
+         maximum_allocation = current_allocation;
+      pinfo->pointer = (png_voidp)png_malloc_default(png_ptr, size);
+      pinfo->next = pinformation;
+      pinformation = pinfo;
+      /* Make sure the caller isn't assuming zeroed memory. */
+      png_memset(pinfo->pointer, 0xdd, pinfo->size);
+#if PNG_DEBUG
+      if(verbose)
+         printf("png_malloc %lu bytes at %x\n",size,pinfo->pointer);
+#endif
+      assert(pinfo->size != 12345678);
+      return (png_voidp)(pinfo->pointer);
+   }
+}
+
+/* Free a pointer.  It is removed from the list at the same time. */
+void
+png_debug_free(png_structp png_ptr, png_voidp ptr)
+{
+   if (png_ptr == NULL)
+      fprintf(STDERR, "NULL pointer to png_debug_free.\n");
+   if (ptr == 0)
+   {
+#if 0 /* This happens all the time. */
+      fprintf(STDERR, "WARNING: freeing NULL pointer\n");
+#endif
+      return;
+   }
+
+   /* Unlink the element from the list. */
+   {
+      memory_infop FAR *ppinfo = &pinformation;
+      for (;;)
+      {
+         memory_infop pinfo = *ppinfo;
+         if (pinfo->pointer == ptr)
+         {
+            *ppinfo = pinfo->next;
+            current_allocation -= pinfo->size;
+            if (current_allocation < 0)
+               fprintf(STDERR, "Duplicate free of memory\n");
+            /* We must free the list element too, but first kill
+               the memory that is to be freed. */
+            png_memset(ptr, 0x55, pinfo->size);
+            png_free_default(png_ptr, pinfo);
+            pinfo=NULL;
+            break;
+         }
+         if (pinfo->next == NULL)
+         {
+            fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr);
+            break;
+         }
+         ppinfo = &pinfo->next;
+      }
+   }
+
+   /* Finally free the data. */
+#if PNG_DEBUG
+   if(verbose)
+      printf("Freeing %x\n",ptr);
+#endif
+   png_free_default(png_ptr, ptr);
+   ptr=NULL;
+}
+#endif /* PNG_USER_MEM_SUPPORTED */
+/* END of code to test memory allocation/deallocation */
+
+/* Test one file */
+int
+test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
+{
+   static png_FILE_p fpin;
+   static png_FILE_p fpout;  /* "static" prevents setjmp corruption */
+   png_structp read_ptr;
+   png_infop read_info_ptr, end_info_ptr;
+#ifdef PNG_WRITE_SUPPORTED
+   png_structp write_ptr;
+   png_infop write_info_ptr;
+   png_infop write_end_info_ptr;
+#else
+   png_structp write_ptr = NULL;
+   png_infop write_info_ptr = NULL;
+   png_infop write_end_info_ptr = NULL;
+#endif
+   png_bytep row_buf;
+   png_uint_32 y;
+   png_uint_32 width, height;
+   int num_pass, pass;
+   int bit_depth, color_type;
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+   jmp_buf jmpbuf;
+#endif
+#endif
+
+#if defined(_WIN32_WCE)
+   TCHAR path[MAX_PATH];
+#endif
+   char inbuf[256], outbuf[256];
+
+   row_buf = (png_bytep)NULL;
+
+#if defined(_WIN32_WCE)
+   MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
+   if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+   if ((fpin = fopen(inname, "rb")) == NULL)
+#endif
+   {
+      fprintf(STDERR, "Could not find input file %s\n", inname);
+      return (1);
+   }
+
+#if defined(_WIN32_WCE)
+   MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
+   if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+   if ((fpout = fopen(outname, "wb")) == NULL)
+#endif
+   {
+      fprintf(STDERR, "Could not open output file %s\n", outname);
+      FCLOSE(fpin);
+      return (1);
+   }
+
+   png_debug(0, "Allocating read and write structures\n");
+#ifdef PNG_USER_MEM_SUPPORTED
+   read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+      (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL,
+      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
+#else
+   read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+      (png_error_ptr)NULL, (png_error_ptr)NULL);
+#endif
+#if defined(PNG_NO_STDIO)
+   png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error,
+       pngtest_warning);
+#endif
+#ifdef PNG_WRITE_SUPPORTED
+#ifdef PNG_USER_MEM_SUPPORTED
+   write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+      (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL,
+      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
+#else
+   write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
+      (png_error_ptr)NULL, (png_error_ptr)NULL);
+#endif
+#if defined(PNG_NO_STDIO)
+   png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error,
+       pngtest_warning);
+#endif
+#endif
+   png_debug(0, "Allocating read_info, write_info and end_info structures\n");
+   read_info_ptr = png_create_info_struct(read_ptr);
+   end_info_ptr = png_create_info_struct(read_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+   write_info_ptr = png_create_info_struct(write_ptr);
+   write_end_info_ptr = png_create_info_struct(write_ptr);
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+   png_debug(0, "Setting jmpbuf for read struct\n");
+#ifdef USE_FAR_KEYWORD
+   if (setjmp(jmpbuf))
+#else
+   if (setjmp(png_jmpbuf(read_ptr)))
+#endif
+   {
+      fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
+      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
+      png_destroy_write_struct(&write_ptr, &write_info_ptr);
+#endif
+      FCLOSE(fpin);
+      FCLOSE(fpout);
+      return (1);
+   }
+#ifdef USE_FAR_KEYWORD
+   png_memcpy(png_jmpbuf(read_ptr),jmpbuf,sizeof(jmp_buf));
+#endif
+
+#ifdef PNG_WRITE_SUPPORTED
+   png_debug(0, "Setting jmpbuf for write struct\n");
+#ifdef USE_FAR_KEYWORD
+   if (setjmp(jmpbuf))
+#else
+   if (setjmp(png_jmpbuf(write_ptr)))
+#endif
+   {
+      fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
+      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
+      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+      png_destroy_write_struct(&write_ptr, &write_info_ptr);
+#endif
+      FCLOSE(fpin);
+      FCLOSE(fpout);
+      return (1);
+   }
+#ifdef USE_FAR_KEYWORD
+   png_memcpy(png_jmpbuf(write_ptr),jmpbuf,sizeof(jmp_buf));
+#endif
+#endif
+#endif
+
+   png_debug(0, "Initializing input and output streams\n");
+#if !defined(PNG_NO_STDIO)
+   png_init_io(read_ptr, fpin);
+#  ifdef PNG_WRITE_SUPPORTED
+   png_init_io(write_ptr, fpout);
+#  endif
+#else
+   png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
+#  ifdef PNG_WRITE_SUPPORTED
+   png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,
+#    if defined(PNG_WRITE_FLUSH_SUPPORTED)
+      pngtest_flush);
+#    else
+      NULL);
+#    endif
+#  endif
+#endif
+   if(status_dots_requested == 1)
+   {
+#ifdef PNG_WRITE_SUPPORTED
+      png_set_write_status_fn(write_ptr, write_row_callback);
+#endif
+      png_set_read_status_fn(read_ptr, read_row_callback);
+   }
+   else
+   {
+#ifdef PNG_WRITE_SUPPORTED
+      png_set_write_status_fn(write_ptr, NULL);
+#endif
+      png_set_read_status_fn(read_ptr, NULL);
+   }
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+   {
+     int i;
+     for(i=0; i<256; i++)
+        filters_used[i]=0;
+     png_set_read_user_transform_fn(read_ptr, count_filters);
+   }
+#endif
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+   zero_samples=0;
+   png_set_write_user_transform_fn(write_ptr, count_zero_samples);
+#endif
+
+#define HANDLE_CHUNK_IF_SAFE      2
+#define HANDLE_CHUNK_ALWAYS       3
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+   png_set_keep_unknown_chunks(read_ptr, HANDLE_CHUNK_ALWAYS, NULL, 0);
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   png_set_keep_unknown_chunks(write_ptr, HANDLE_CHUNK_IF_SAFE, NULL, 0);
+#endif
+
+   png_debug(0, "Reading info struct\n");
+   png_read_info(read_ptr, read_info_ptr);
+
+   png_debug(0, "Transferring info struct\n");
+   {
+      int interlace_type, compression_type, filter_type;
+
+      if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
+          &color_type, &interlace_type, &compression_type, &filter_type))
+      {
+         png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+            color_type, interlace_type, compression_type, filter_type);
+#else
+            color_type, PNG_INTERLACE_NONE, compression_type, filter_type);
+#endif
+      }
+   }
+#if defined(PNG_FIXED_POINT_SUPPORTED)
+#if defined(PNG_cHRM_SUPPORTED)
+   {
+      png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
+         blue_y;
+      if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
+         &red_y, &green_x, &green_y, &blue_x, &blue_y))
+      {
+         png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,
+            red_y, green_x, green_y, blue_x, blue_y);
+      }
+   }
+#endif
+#if defined(PNG_gAMA_SUPPORTED)
+   {
+      png_fixed_point gamma;
+
+      if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma))
+      {
+         png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
+      }
+   }
+#endif
+#else /* Use floating point versions */
+#if defined(PNG_FLOATING_POINT_SUPPORTED)
+#if defined(PNG_cHRM_SUPPORTED)
+   {
+      double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
+         blue_y;
+      if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
+         &red_y, &green_x, &green_y, &blue_x, &blue_y))
+      {
+         png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
+            red_y, green_x, green_y, blue_x, blue_y);
+      }
+   }
+#endif
+#if defined(PNG_gAMA_SUPPORTED)
+   {
+      double gamma;
+
+      if (png_get_gAMA(read_ptr, read_info_ptr, &gamma))
+      {
+         png_set_gAMA(write_ptr, write_info_ptr, gamma);
+      }
+   }
+#endif
+#endif /* floating point */
+#endif /* fixed point */
+#if defined(PNG_iCCP_SUPPORTED)
+   {
+      png_charp name;
+      png_charp profile;
+      png_uint_32 proflen;
+      int compression_type;
+
+      if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
+                      &profile, &proflen))
+      {
+         png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
+                      profile, proflen);
+      }
+   }
+#endif
+#if defined(PNG_sRGB_SUPPORTED)
+   {
+      int intent;
+
+      if (png_get_sRGB(read_ptr, read_info_ptr, &intent))
+      {
+         png_set_sRGB(write_ptr, write_info_ptr, intent);
+      }
+   }
+#endif
+   {
+      png_colorp palette;
+      int num_palette;
+
+      if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette))
+      {
+         png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
+      }
+   }
+#if defined(PNG_bKGD_SUPPORTED)
+   {
+      png_color_16p background;
+
+      if (png_get_bKGD(read_ptr, read_info_ptr, &background))
+      {
+         png_set_bKGD(write_ptr, write_info_ptr, background);
+      }
+   }
+#endif
+#if defined(PNG_hIST_SUPPORTED)
+   {
+      png_uint_16p hist;
+
+      if (png_get_hIST(read_ptr, read_info_ptr, &hist))
+      {
+         png_set_hIST(write_ptr, write_info_ptr, hist);
+      }
+   }
+#endif
+#if defined(PNG_oFFs_SUPPORTED)
+   {
+      png_int_32 offset_x, offset_y;
+      int unit_type;
+
+      if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type))
+      {
+         png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
+      }
+   }
+#endif
+#if defined(PNG_pCAL_SUPPORTED)
+   {
+      png_charp purpose, units;
+      png_charpp params;
+      png_int_32 X0, X1;
+      int type, nparams;
+
+      if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
+         &nparams, &units, &params))
+      {
+         png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
+            nparams, units, params);
+      }
+   }
+#endif
+#if defined(PNG_pHYs_SUPPORTED)
+   {
+      png_uint_32 res_x, res_y;
+      int unit_type;
+
+      if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type))
+      {
+         png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
+      }
+   }
+#endif
+#if defined(PNG_sBIT_SUPPORTED)
+   {
+      png_color_8p sig_bit;
+
+      if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit))
+      {
+         png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
+      }
+   }
+#endif
+#if defined(PNG_sCAL_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+   {
+      int unit;
+      double scal_width, scal_height;
+
+      if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
+         &scal_height))
+      {
+         png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
+      }
+   }
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+   {
+      int unit;
+      png_charp scal_width, scal_height;
+
+      if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
+          &scal_height))
+      {
+         png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height);
+      }
+   }
+#endif
+#endif
+#endif
+#if defined(PNG_TEXT_SUPPORTED)
+   {
+      png_textp text_ptr;
+      int num_text;
+
+      if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
+      {
+         png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text);
+         png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
+      }
+   }
+#endif
+#if defined(PNG_tIME_SUPPORTED)
+   {
+      png_timep mod_time;
+
+      if (png_get_tIME(read_ptr, read_info_ptr, &mod_time))
+      {
+         png_set_tIME(write_ptr, write_info_ptr, mod_time);
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+         /* we have to use png_strcpy instead of "=" because the string
+            pointed to by png_convert_to_rfc1123() gets free'ed before
+            we use it */
+         png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
+         tIME_chunk_present++;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+      }
+   }
+#endif
+#if defined(PNG_tRNS_SUPPORTED)
+   {
+      png_bytep trans;
+      int num_trans;
+      png_color_16p trans_values;
+
+      if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans,
+         &trans_values))
+      {
+         png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans,
+            trans_values);
+      }
+   }
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   {
+      png_unknown_chunkp unknowns;
+      int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr,
+         &unknowns);
+      if (num_unknowns)
+      {
+         png_size_t i;
+         png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
+           num_unknowns);
+         /* copy the locations from the read_info_ptr.  The automatically
+            generated locations in write_info_ptr are wrong because we
+            haven't written anything yet */
+         for (i = 0; i < (png_size_t)num_unknowns; i++)
+           png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
+             unknowns[i].location);
+      }
+   }
+#endif
+
+#ifdef PNG_WRITE_SUPPORTED
+   png_debug(0, "\nWriting info struct\n");
+
+/* If we wanted, we could write info in two steps:
+   png_write_info_before_PLTE(write_ptr, write_info_ptr);
+ */
+   png_write_info(write_ptr, write_info_ptr);
+#endif
+
+#ifdef SINGLE_ROWBUF_ALLOC
+   png_debug(0, "\nAllocating row buffer...");
+   row_buf = (png_bytep)png_malloc(read_ptr,
+      png_get_rowbytes(read_ptr, read_info_ptr));
+   png_debug1(0, "0x%08lx\n\n", (unsigned long)row_buf);
+#endif /* SINGLE_ROWBUF_ALLOC */
+   png_debug(0, "Writing row data\n");
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
+  defined(PNG_WRITE_INTERLACING_SUPPORTED)
+   num_pass = png_set_interlace_handling(read_ptr);
+#  ifdef PNG_WRITE_SUPPORTED
+   png_set_interlace_handling(write_ptr);
+#  endif
+#else
+   num_pass=1;
+#endif
+
+#ifdef PNGTEST_TIMING
+   t_stop = (float)clock();
+   t_misc += (t_stop - t_start);
+   t_start = t_stop;
+#endif
+   for (pass = 0; pass < num_pass; pass++)
+   {
+      png_debug1(0, "Writing row data for pass %d\n",pass);
+      for (y = 0; y < height; y++)
+      {
+#ifndef SINGLE_ROWBUF_ALLOC
+         png_debug2(0, "\nAllocating row buffer (pass %d, y = %ld)...", pass,y);
+         row_buf = (png_bytep)png_malloc(read_ptr,
+            png_get_rowbytes(read_ptr, read_info_ptr));
+         png_debug2(0, "0x%08lx (%ld bytes)\n", (unsigned long)row_buf,
+            png_get_rowbytes(read_ptr, read_info_ptr));
+#endif /* !SINGLE_ROWBUF_ALLOC */
+         png_read_rows(read_ptr, (png_bytepp)&row_buf, (png_bytepp)NULL, 1);
+
+#ifdef PNG_WRITE_SUPPORTED
+#ifdef PNGTEST_TIMING
+         t_stop = (float)clock();
+         t_decode += (t_stop - t_start);
+         t_start = t_stop;
+#endif
+         png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
+#ifdef PNGTEST_TIMING
+         t_stop = (float)clock();
+         t_encode += (t_stop - t_start);
+         t_start = t_stop;
+#endif
+#endif /* PNG_WRITE_SUPPORTED */
+
+#ifndef SINGLE_ROWBUF_ALLOC
+         png_debug2(0, "Freeing row buffer (pass %d, y = %ld)\n\n", pass, y);
+         png_free(read_ptr, row_buf);
+#endif /* !SINGLE_ROWBUF_ALLOC */
+      }
+   }
+
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+   png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);
+#endif
+
+   png_debug(0, "Reading and writing end_info data\n");
+
+   png_read_end(read_ptr, end_info_ptr);
+#if defined(PNG_TEXT_SUPPORTED)
+   {
+      png_textp text_ptr;
+      int num_text;
+
+      if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)
+      {
+         png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text);
+         png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);
+      }
+   }
+#endif
+#if defined(PNG_tIME_SUPPORTED)
+   {
+      png_timep mod_time;
+
+      if (png_get_tIME(read_ptr, end_info_ptr, &mod_time))
+      {
+         png_set_tIME(write_ptr, write_end_info_ptr, mod_time);
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+         /* we have to use png_strcpy instead of "=" because the string
+            pointed to by png_convert_to_rfc1123() gets free'ed before
+            we use it */
+         png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
+         tIME_chunk_present++;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+      }
+   }
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   {
+      png_unknown_chunkp unknowns;
+      int num_unknowns;
+      num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr,
+         &unknowns);
+      if (num_unknowns)
+      {
+         png_size_t i;
+         png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
+           num_unknowns);
+         /* copy the locations from the read_info_ptr.  The automatically
+            generated locations in write_end_info_ptr are wrong because we
+            haven't written the end_info yet */
+         for (i = 0; i < (png_size_t)num_unknowns; i++)
+           png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
+             unknowns[i].location);
+      }
+   }
+#endif
+#ifdef PNG_WRITE_SUPPORTED
+   png_write_end(write_ptr, write_end_info_ptr);
+#endif
+
+#ifdef PNG_EASY_ACCESS_SUPPORTED
+   if(verbose)
+   {
+      png_uint_32 iwidth, iheight;
+      iwidth = png_get_image_width(write_ptr, write_info_ptr);
+      iheight = png_get_image_height(write_ptr, write_info_ptr);
+      fprintf(STDERR, "Image width = %lu, height = %lu\n",
+         iwidth, iheight);
+   }
+#endif
+
+   png_debug(0, "Destroying data structs\n");
+#ifdef SINGLE_ROWBUF_ALLOC
+   png_debug(1, "destroying row_buf for read_ptr\n");
+   png_free(read_ptr, row_buf);
+   row_buf=NULL;
+#endif /* SINGLE_ROWBUF_ALLOC */
+   png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr\n");
+   png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+   png_debug(1, "destroying write_end_info_ptr\n");
+   png_destroy_info_struct(write_ptr, &write_end_info_ptr);
+   png_debug(1, "destroying write_ptr, write_info_ptr\n");
+   png_destroy_write_struct(&write_ptr, &write_info_ptr);
+#endif
+   png_debug(0, "Destruction complete.\n");
+
+   FCLOSE(fpin);
+   FCLOSE(fpout);
+
+   png_debug(0, "Opening files for comparison\n");
+#if defined(_WIN32_WCE)
+   MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
+   if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+   if ((fpin = fopen(inname, "rb")) == NULL)
+#endif
+   {
+      fprintf(STDERR, "Could not find file %s\n", inname);
+      return (1);
+   }
+
+#if defined(_WIN32_WCE)
+   MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
+   if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+   if ((fpout = fopen(outname, "rb")) == NULL)
+#endif
+   {
+      fprintf(STDERR, "Could not find file %s\n", outname);
+      FCLOSE(fpin);
+      return (1);
+   }
+
+   for(;;)
+   {
+      png_size_t num_in, num_out;
+
+      READFILE(fpin, inbuf, 1, num_in);
+      READFILE(fpout, outbuf, 1, num_out);
+
+      if (num_in != num_out)
+      {
+         fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
+                 inname, outname);
+         if(wrote_question == 0)
+         {
+            fprintf(STDERR,
+         "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
+              inname,PNG_ZBUF_SIZE);
+            fprintf(STDERR,
+              "\n   filtering heuristic (libpng default), compression");
+            fprintf(STDERR,
+              " level (zlib default),\n   and zlib version (%s)?\n\n",
+              ZLIB_VERSION);
+            wrote_question=1;
+         }
+         FCLOSE(fpin);
+         FCLOSE(fpout);
+         return (0);
+      }
+
+      if (!num_in)
+         break;
+
+      if (png_memcmp(inbuf, outbuf, num_in))
+      {
+         fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname);
+         if(wrote_question == 0)
+         {
+            fprintf(STDERR,
+         "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
+                 inname,PNG_ZBUF_SIZE);
+            fprintf(STDERR,
+              "\n   filtering heuristic (libpng default), compression");
+            fprintf(STDERR,
+              " level (zlib default),\n   and zlib version (%s)?\n\n",
+              ZLIB_VERSION);
+            wrote_question=1;
+         }
+         FCLOSE(fpin);
+         FCLOSE(fpout);
+         return (0);
+      }
+   }
+
+   FCLOSE(fpin);
+   FCLOSE(fpout);
+
+   return (0);
+}
+
+/* input and output filenames */
+#ifdef RISCOS
+static PNG_CONST char *inname = "pngtest/png";
+static PNG_CONST char *outname = "pngout/png";
+#else
+static PNG_CONST char *inname = "pngtest.png";
+static PNG_CONST char *outname = "pngout.png";
+#endif
+
+int
+main(int argc, char *argv[])
+{
+   int multiple = 0;
+   int ierror = 0;
+
+   fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
+   fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);
+   fprintf(STDERR,"%s",png_get_copyright(NULL));
+   /* Show the version of libpng used in building the library */
+   fprintf(STDERR," library (%lu):%s", png_access_version_number(),
+      png_get_header_version(NULL));
+   /* Show the version of libpng used in building the application */
+   fprintf(STDERR," pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
+      PNG_HEADER_VERSION_STRING);
+   fprintf(STDERR," sizeof(png_struct)=%ld, sizeof(png_info)=%ld\n",
+                    (long)sizeof(png_struct), (long)sizeof(png_info));
+
+   /* Do some consistency checking on the memory allocation settings, I'm
+      not sure this matters, but it is nice to know, the first of these
+      tests should be impossible because of the way the macros are set
+      in pngconf.h */
+#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
+      fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");
+#endif
+   /* I think the following can happen. */
+#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
+      fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");
+#endif
+
+   if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
+   {
+      fprintf(STDERR,
+         "Warning: versions are different between png.h and png.c\n");
+      fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
+      fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
+      ++ierror;
+   }
+
+   if (argc > 1)
+   {
+      if (strcmp(argv[1], "-m") == 0)
+      {
+         multiple = 1;
+         status_dots_requested = 0;
+      }
+      else if (strcmp(argv[1], "-mv") == 0 ||
+               strcmp(argv[1], "-vm") == 0 )
+      {
+         multiple = 1;
+         verbose = 1;
+         status_dots_requested = 1;
+      }
+      else if (strcmp(argv[1], "-v") == 0)
+      {
+         verbose = 1;
+         status_dots_requested = 1;
+         inname = argv[2];
+      }
+      else
+      {
+         inname = argv[1];
+         status_dots_requested = 0;
+      }
+   }
+
+   if (!multiple && argc == 3+verbose)
+     outname = argv[2+verbose];
+
+   if ((!multiple && argc > 3+verbose) || (multiple && argc < 2))
+   {
+     fprintf(STDERR,
+       "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
+        argv[0], argv[0]);
+     fprintf(STDERR,
+       "  reads/writes one PNG file (without -m) or multiple files (-m)\n");
+     fprintf(STDERR,
+       "  with -m %s is used as a temporary file\n", outname);
+     exit(1);
+   }
+
+   if (multiple)
+   {
+      int i;
+#ifdef PNG_USER_MEM_SUPPORTED
+      int allocation_now = current_allocation;
+#endif
+      for (i=2; i<argc; ++i)
+      {
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+         int k;
+#endif
+         int kerror;
+         fprintf(STDERR, "Testing %s:",argv[i]);
+         kerror = test_one_file(argv[i], outname);
+         if (kerror == 0)
+         {
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+            fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples);
+#else
+            fprintf(STDERR, " PASS\n");
+#endif
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+            for (k=0; k<256; k++)
+               if(filters_used[k])
+                  fprintf(STDERR, " Filter %d was used %lu times\n",
+                     k,filters_used[k]);
+#endif
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+         if(tIME_chunk_present != 0)
+            fprintf(STDERR, " tIME = %s\n",tIME_string);
+         tIME_chunk_present = 0;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+         }
+         else
+         {
+            fprintf(STDERR, " FAIL\n");
+            ierror += kerror;
+         }
+#ifdef PNG_USER_MEM_SUPPORTED
+         if (allocation_now != current_allocation)
+            fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
+               current_allocation-allocation_now);
+         if (current_allocation != 0)
+         {
+            memory_infop pinfo = pinformation;
+
+            fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
+               current_allocation);
+            while (pinfo != NULL)
+            {
+               fprintf(STDERR, " %lu bytes at %x\n", pinfo->size, 
+                 (unsigned int) pinfo->pointer);
+               pinfo = pinfo->next;
+            }
+         }
+#endif
+      }
+#ifdef PNG_USER_MEM_SUPPORTED
+         fprintf(STDERR, " Current memory allocation: %10d bytes\n",
+            current_allocation);
+         fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
+            maximum_allocation);
+         fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
+            total_allocation);
+         fprintf(STDERR, "     Number of allocations: %10d\n",
+            num_allocations);
+#endif
+   }
+   else
+   {
+      int i;
+      for (i=0; i<3; ++i)
+      {
+         int kerror;
+#ifdef PNG_USER_MEM_SUPPORTED
+         int allocation_now = current_allocation;
+#endif
+         if (i == 1) status_dots_requested = 1;
+         else if(verbose == 0)status_dots_requested = 0;
+         if (i == 0 || verbose == 1 || ierror != 0)
+            fprintf(STDERR, "Testing %s:",inname);
+         kerror = test_one_file(inname, outname);
+         if(kerror == 0)
+         {
+            if(verbose == 1 || i == 2)
+            {
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+                int k;
+#endif
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+                fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples);
+#else
+                fprintf(STDERR, " PASS\n");
+#endif
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+                for (k=0; k<256; k++)
+                   if(filters_used[k])
+                      fprintf(STDERR, " Filter %d was used %lu times\n",
+                         k,filters_used[k]);
+#endif
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+             if(tIME_chunk_present != 0)
+                fprintf(STDERR, " tIME = %s\n",tIME_string);
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+            }
+         }
+         else
+         {
+            if(verbose == 0 && i != 2)
+               fprintf(STDERR, "Testing %s:",inname);
+            fprintf(STDERR, " FAIL\n");
+            ierror += kerror;
+         }
+#ifdef PNG_USER_MEM_SUPPORTED
+         if (allocation_now != current_allocation)
+             fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
+               current_allocation-allocation_now);
+         if (current_allocation != 0)
+         {
+             memory_infop pinfo = pinformation;
+
+             fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
+                current_allocation);
+             while (pinfo != NULL)
+             {
+                fprintf(STDERR," %lu bytes at %x\n",
+                   pinfo->size, (unsigned int)pinfo->pointer);
+                pinfo = pinfo->next;
+             }
+          }
+#endif
+       }
+#ifdef PNG_USER_MEM_SUPPORTED
+       fprintf(STDERR, " Current memory allocation: %10d bytes\n",
+          current_allocation);
+       fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
+          maximum_allocation);
+       fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
+          total_allocation);
+       fprintf(STDERR, "     Number of allocations: %10d\n",
+            num_allocations);
+#endif
+   }
+
+#ifdef PNGTEST_TIMING
+   t_stop = (float)clock();
+   t_misc += (t_stop - t_start);
+   t_start = t_stop;
+   fprintf(STDERR," CPU time used = %.3f seconds",
+      (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
+   fprintf(STDERR," (decoding %.3f,\n",
+      t_decode/(float)CLOCKS_PER_SEC);
+   fprintf(STDERR,"        encoding %.3f ,",
+      t_encode/(float)CLOCKS_PER_SEC);
+   fprintf(STDERR," other %.3f seconds)\n\n",
+      t_misc/(float)CLOCKS_PER_SEC);
+#endif
+
+   if (ierror == 0)
+      fprintf(STDERR, "libpng passes test\n");
+   else
+      fprintf(STDERR, "libpng FAILS test\n");
+   return (int)(ierror != 0);
+}
+
+/* Generate a compiler error if there is an old png.h in the search path. */
+typedef version_1_2_0 your_png_h_is_not_version_1_2_0;
diff --git a/libraries/libpng-1.2.0/pngtest.png b/libraries/libpng-1.2.0/pngtest.png
new file mode 100644 (file)
index 0000000..3d6f1c3
Binary files /dev/null and b/libraries/libpng-1.2.0/pngtest.png differ
diff --git a/libraries/libpng-1.2.0/pngtrans.c b/libraries/libpng-1.2.0/pngtrans.c
new file mode 100644 (file)
index 0000000..6398dcf
--- /dev/null
@@ -0,0 +1,640 @@
+
+/* pngtrans.c - transforms the data in a row (used by both readers and writers)
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+/* turn on BGR-to-RGB mapping */
+void PNGAPI
+png_set_bgr(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_bgr\n");
+   png_ptr->transformations |= PNG_BGR;
+}
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+/* turn on 16 bit byte swapping */
+void PNGAPI
+png_set_swap(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_swap\n");
+   if (png_ptr->bit_depth == 16)
+      png_ptr->transformations |= PNG_SWAP_BYTES;
+}
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
+/* turn on pixel packing */
+void PNGAPI
+png_set_packing(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_packing\n");
+   if (png_ptr->bit_depth < 8)
+   {
+      png_ptr->transformations |= PNG_PACK;
+      png_ptr->usr_bit_depth = 8;
+   }
+}
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+/* turn on packed pixel swapping */
+void PNGAPI
+png_set_packswap(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_packswap\n");
+   if (png_ptr->bit_depth < 8)
+      png_ptr->transformations |= PNG_PACKSWAP;
+}
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
+void PNGAPI
+png_set_shift(png_structp png_ptr, png_color_8p true_bits)
+{
+   png_debug(1, "in png_set_shift\n");
+   png_ptr->transformations |= PNG_SHIFT;
+   png_ptr->shift = *true_bits;
+}
+#endif
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
+    defined(PNG_WRITE_INTERLACING_SUPPORTED)
+int PNGAPI
+png_set_interlace_handling(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_interlace handling\n");
+   if (png_ptr->interlaced)
+   {
+      png_ptr->transformations |= PNG_INTERLACE;
+      return (7);
+   }
+
+   return (1);
+}
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
+/* Add a filler byte on read, or remove a filler or alpha byte on write.
+ * The filler type has changed in v0.95 to allow future 2-byte fillers
+ * for 48-bit input data, as well as to avoid problems with some compilers
+ * that don't like bytes as parameters.
+ */
+void PNGAPI
+png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
+{
+   png_debug(1, "in png_set_filler\n");
+   png_ptr->transformations |= PNG_FILLER;
+   png_ptr->filler = (png_byte)filler;
+   if (filler_loc == PNG_FILLER_AFTER)
+      png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
+   else
+      png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
+
+   /* This should probably go in the "do_filler" routine.
+    * I attempted to do that in libpng-1.0.1a but that caused problems
+    * so I restored it in libpng-1.0.2a
+   */
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+   {
+      png_ptr->usr_channels = 4;
+   }
+
+   /* Also I added this in libpng-1.0.2a (what happens when we expand
+    * a less-than-8-bit grayscale to GA? */
+
+   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
+   {
+      png_ptr->usr_channels = 2;
+   }
+}
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
+    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+void PNGAPI
+png_set_swap_alpha(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_swap_alpha\n");
+   png_ptr->transformations |= PNG_SWAP_ALPHA;
+}
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
+    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+void PNGAPI
+png_set_invert_alpha(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_invert_alpha\n");
+   png_ptr->transformations |= PNG_INVERT_ALPHA;
+}
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
+void PNGAPI
+png_set_invert_mono(png_structp png_ptr)
+{
+   png_debug(1, "in png_set_invert_mono\n");
+   png_ptr->transformations |= PNG_INVERT_MONO;
+}
+
+/* invert monochrome grayscale data */
+void /* PRIVATE */
+png_do_invert(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_invert\n");
+  /* This test removed from libpng version 1.0.13 and 1.2.0:
+   *   if (row_info->bit_depth == 1 &&
+   */
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row == NULL || row_info == NULL)
+     return;
+#endif
+   if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
+   {
+      png_bytep rp = row;
+      png_uint_32 i;
+      png_uint_32 istop = row_info->rowbytes;
+
+      for (i = 0; i < istop; i++)
+      {
+         *rp = (png_byte)(~(*rp));
+         rp++;
+      }
+   }
+   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
+      row_info->bit_depth == 8)
+   {
+      png_bytep rp = row;
+      png_uint_32 i;
+      png_uint_32 istop = row_info->rowbytes;
+
+      for (i = 0; i < istop; i+=2)
+      {
+         *rp = (png_byte)(~(*rp));
+         rp+=2;
+      }
+   }
+   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
+      row_info->bit_depth == 16)
+   {
+      png_bytep rp = row;
+      png_uint_32 i;
+      png_uint_32 istop = row_info->rowbytes;
+
+      for (i = 0; i < istop; i+=4)
+      {
+         *rp = (png_byte)(~(*rp));
+         *(rp+1) = (png_byte)(~(*(rp+1)));
+         rp+=4;
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+/* swaps byte order on 16 bit depth images */
+void /* PRIVATE */
+png_do_swap(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_swap\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       row_info->bit_depth == 16)
+   {
+      png_bytep rp = row;
+      png_uint_32 i;
+      png_uint_32 istop= row_info->width * row_info->channels;
+
+      for (i = 0; i < istop; i++, rp += 2)
+      {
+         png_byte t = *rp;
+         *rp = *(rp + 1);
+         *(rp + 1) = t;
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+static png_byte onebppswaptable[256] = {
+   0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+   0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+   0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+   0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+   0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+   0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+   0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+   0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+   0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+   0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+   0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+   0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+   0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+   0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+   0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+   0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+   0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+   0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+   0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+   0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+   0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+   0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+   0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+   0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+   0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+   0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+   0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+   0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+   0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+   0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+   0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+   0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
+};
+
+static png_byte twobppswaptable[256] = {
+   0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
+   0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
+   0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
+   0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
+   0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
+   0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
+   0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
+   0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
+   0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
+   0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
+   0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
+   0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
+   0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
+   0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
+   0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
+   0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
+   0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
+   0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
+   0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
+   0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
+   0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
+   0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
+   0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
+   0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
+   0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
+   0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
+   0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
+   0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
+   0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
+   0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
+   0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
+   0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
+};
+
+static png_byte fourbppswaptable[256] = {
+   0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+   0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
+   0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
+   0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
+   0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
+   0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
+   0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
+   0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
+   0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
+   0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
+   0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
+   0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
+   0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
+   0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
+   0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
+   0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
+   0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
+   0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
+   0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
+   0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
+   0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
+   0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
+   0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
+   0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
+   0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
+   0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
+   0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
+   0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
+   0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
+   0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
+   0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
+   0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
+};
+
+/* swaps pixel packing order within bytes */
+void /* PRIVATE */
+png_do_packswap(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_packswap\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       row_info->bit_depth < 8)
+   {
+      png_bytep rp, end, table;
+
+      end = row + row_info->rowbytes;
+
+      if (row_info->bit_depth == 1)
+         table = onebppswaptable;
+      else if (row_info->bit_depth == 2)
+         table = twobppswaptable;
+      else if (row_info->bit_depth == 4)
+         table = fourbppswaptable;
+      else
+         return;
+
+      for (rp = row; rp < end; rp++)
+         *rp = table[*rp];
+   }
+}
+#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
+
+#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
+    defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+/* remove filler or alpha byte(s) */
+void /* PRIVATE */
+png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
+{
+   png_debug(1, "in png_do_strip_filler\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+/*
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB ||
+          row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+*/
+      png_bytep sp=row;
+      png_bytep dp=row;
+      png_uint_32 row_width=row_info->width;
+      png_uint_32 i;
+
+      if (row_info->channels == 4)
+      {
+         if (row_info->bit_depth == 8)
+         {
+            /* This converts from RGBX or RGBA to RGB */
+            if (flags & PNG_FLAG_FILLER_AFTER)
+            {
+               dp+=3; sp+=4;
+               for (i = 1; i < row_width; i++)
+               {
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  sp++;
+               }
+            }
+            /* This converts from XRGB or ARGB to RGB */
+            else
+            {
+               for (i = 0; i < row_width; i++)
+               {
+                  sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+               }
+            }
+            row_info->pixel_depth = 24;
+            row_info->rowbytes = row_width * 3;
+         }
+         else /* if (row_info->bit_depth == 16) */
+         {
+            if (flags & PNG_FLAG_FILLER_AFTER)
+            {
+               /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
+               sp += 8; dp += 6;
+               for (i = 1; i < row_width; i++)
+               {
+                  /* This could be (although png_memcpy is probably slower):
+                  png_memcpy(dp, sp, 6);
+                  sp += 8;
+                  dp += 6;
+                  */
+
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  sp += 2;
+               }
+            }
+            else
+            {
+               /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
+               for (i = 0; i < row_width; i++)
+               {
+                  /* This could be (although png_memcpy is probably slower):
+                  png_memcpy(dp, sp, 6);
+                  sp += 8;
+                  dp += 6;
+                  */
+
+                  sp+=2;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+               }
+            }
+            row_info->pixel_depth = 48;
+            row_info->rowbytes = row_width * 6;
+         }
+         row_info->channels = 3;
+         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
+      }
+/*
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY ||
+               row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+*/
+      else if (row_info->channels == 2)
+      {
+         if (row_info->bit_depth == 8)
+         {
+            /* This converts from GX or GA to G */
+            if (flags & PNG_FLAG_FILLER_AFTER)
+            {
+               for (i = 0; i < row_width; i++)
+               {
+                  *dp++ = *sp++;
+                  sp++;
+               }
+            }
+            /* This converts from XG or AG to G */
+            else
+            {
+               for (i = 0; i < row_width; i++)
+               {
+                  sp++;
+                  *dp++ = *sp++;
+               }
+            }
+            row_info->pixel_depth = 8;
+            row_info->rowbytes = row_width;
+         }
+         else /* if (row_info->bit_depth == 16) */
+         {
+            if (flags & PNG_FLAG_FILLER_AFTER)
+            {
+               /* This converts from GGXX or GGAA to GG */
+               sp += 4; dp += 2;
+               for (i = 1; i < row_width; i++)
+               {
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+                  sp += 2;
+               }
+            }
+            else
+            {
+               /* This converts from XXGG or AAGG to GG */
+               for (i = 0; i < row_width; i++)
+               {
+                  sp += 2;
+                  *dp++ = *sp++;
+                  *dp++ = *sp++;
+               }
+            }
+            row_info->pixel_depth = 16;
+            row_info->rowbytes = row_width * 2;
+         }
+         row_info->channels = 1;
+         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
+      }
+   }
+}
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+/* swaps red and blue bytes within a pixel */
+void /* PRIVATE */
+png_do_bgr(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_bgr\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       (row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      png_uint_32 row_width = row_info->width;
+      if (row_info->bit_depth == 8)
+      {
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+         {
+            png_bytep rp;
+            png_uint_32 i;
+
+            for (i = 0, rp = row; i < row_width; i++, rp += 3)
+            {
+               png_byte save = *rp;
+               *rp = *(rp + 2);
+               *(rp + 2) = save;
+            }
+         }
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+         {
+            png_bytep rp;
+            png_uint_32 i;
+
+            for (i = 0, rp = row; i < row_width; i++, rp += 4)
+            {
+               png_byte save = *rp;
+               *rp = *(rp + 2);
+               *(rp + 2) = save;
+            }
+         }
+      }
+      else if (row_info->bit_depth == 16)
+      {
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+         {
+            png_bytep rp;
+            png_uint_32 i;
+
+            for (i = 0, rp = row; i < row_width; i++, rp += 6)
+            {
+               png_byte save = *rp;
+               *rp = *(rp + 4);
+               *(rp + 4) = save;
+               save = *(rp + 1);
+               *(rp + 1) = *(rp + 5);
+               *(rp + 5) = save;
+            }
+         }
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+         {
+            png_bytep rp;
+            png_uint_32 i;
+
+            for (i = 0, rp = row; i < row_width; i++, rp += 8)
+            {
+               png_byte save = *rp;
+               *rp = *(rp + 4);
+               *(rp + 4) = save;
+               save = *(rp + 1);
+               *(rp + 1) = *(rp + 5);
+               *(rp + 5) = save;
+            }
+         }
+      }
+   }
+}
+#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+    defined(PNG_LEGACY_SUPPORTED)
+void PNGAPI
+png_set_user_transform_info(png_structp png_ptr, png_voidp
+   user_transform_ptr, int user_transform_depth, int user_transform_channels)
+{
+   png_debug(1, "in png_set_user_transform_info\n");
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+   png_ptr->user_transform_ptr = user_transform_ptr;
+   png_ptr->user_transform_depth = (png_byte)user_transform_depth;
+   png_ptr->user_transform_channels = (png_byte)user_transform_channels;
+#else
+   if(user_transform_ptr || user_transform_depth || user_transform_channels)
+      png_warning(png_ptr,
+        "This version of libpng does not support user transform info");
+#endif
+}
+#endif
+
+/* This function returns a pointer to the user_transform_ptr associated with
+ * the user transform functions.  The application should free any memory
+ * associated with this pointer before png_write_destroy and png_read_destroy
+ * are called.
+ */
+png_voidp PNGAPI
+png_get_user_transform_ptr(png_structp png_ptr)
+{
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+   return ((png_voidp)png_ptr->user_transform_ptr);
+#else
+   if(png_ptr)
+     return (NULL);
+   return (NULL);
+#endif
+}
diff --git a/libraries/libpng-1.2.0/pngvcrd.c b/libraries/libpng-1.2.0/pngvcrd.c
new file mode 100644 (file)
index 0000000..d92c546
--- /dev/null
@@ -0,0 +1,3842 @@
+/* pngvcrd.c - mixed C/assembler version of utilities to read a PNG file
+ *
+ * For Intel x86 CPU and Microsoft Visual C++ compiler
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * Copyright (c) 1998, Intel Corporation
+ *
+ * Contributed by Nirav Chhatrapati, Intel Corporation, 1998
+ * Interface to libpng contributed by Gilles Vollant, 1999
+ *
+ *
+ * In png_do_read_interlace() in libpng versions 1.0.3a through 1.0.4d,
+ * a sign error in the post-MMX cleanup code for each pixel_depth resulted
+ * in bad pixels at the beginning of some rows of some images, and also
+ * (due to out-of-range memory reads and writes) caused heap corruption
+ * when compiled with MSVC 6.0.  The error was fixed in version 1.0.4e.
+ *
+ * [png_read_filter_row_mmx_avg() bpp == 2 bugfix, GRR 20000916]
+ *
+ * [runtime MMX configuration, GRR 20010102]
+ *
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+
+#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD)
+
+static int mmx_supported=2;
+
+
+int PNGAPI
+png_mmx_support(void)
+{
+  int mmx_supported_local = 0;
+  _asm {
+    push ebx          //CPUID will trash these
+    push ecx
+    push edx
+    pushfd            //Save Eflag to stack
+    pop eax           //Get Eflag from stack into eax
+    mov ecx, eax      //Make another copy of Eflag in ecx
+    xor eax, 0x200000 //Toggle ID bit in Eflag [i.e. bit(21)]
+    push eax          //Save modified Eflag back to stack
+
+    popfd             //Restored modified value back to Eflag reg
+    pushfd            //Save Eflag to stack
+    pop eax           //Get Eflag from stack
+    xor eax, ecx      //Compare the new Eflag with the original Eflag
+    jz NOT_SUPPORTED  //If the same, CPUID instruction is not supported,
+                      //skip following instructions and jump to
+                      //NOT_SUPPORTED label
+
+    xor eax, eax      //Set eax to zero
+
+    _asm _emit 0x0f   //CPUID instruction  (two bytes opcode)
+    _asm _emit 0xa2
+
+    cmp eax, 1        //make sure eax return non-zero value
+    jl NOT_SUPPORTED  //If eax is zero, mmx not supported
+
+    xor eax, eax      //set eax to zero
+    inc eax           //Now increment eax to 1.  This instruction is
+                      //faster than the instruction "mov eax, 1"
+
+    _asm _emit 0x0f   //CPUID instruction
+    _asm _emit 0xa2
+
+    and edx, 0x00800000  //mask out all bits but mmx bit(24)
+    cmp edx, 0        // 0 = mmx not supported
+    jz  NOT_SUPPORTED // non-zero = Yes, mmx IS supported
+
+    mov  mmx_supported_local, 1  //set return value to 1
+
+NOT_SUPPORTED:
+    mov  eax, mmx_supported_local  //move return value to eax
+    pop edx          //CPUID trashed these
+    pop ecx
+    pop ebx
+  }
+
+  //mmx_supported_local=0; // test code for force don't support MMX
+  //printf("MMX : %u (1=MMX supported)\n",mmx_supported_local);
+
+  mmx_supported = mmx_supported_local;
+  return mmx_supported_local;
+}
+
+/* Combines the row recently read in with the previous row.
+   This routine takes care of alpha and transparency if requested.
+   This routine also handles the two methods of progressive display
+   of interlaced images, depending on the mask value.
+   The mask value describes which pixels are to be combined with
+   the row.  The pattern always repeats every 8 pixels, so just 8
+   bits are needed.  A one indicates the pixel is to be combined; a
+   zero indicates the pixel is to be skipped.  This is in addition
+   to any alpha or transparency value associated with the pixel.  If
+   you want all pixels to be combined, pass 0xff (255) in mask.  */
+
+/* Use this routine for x86 platform - uses faster MMX routine if machine
+   supports MMX */
+
+void /* PRIVATE */
+png_combine_row(png_structp png_ptr, png_bytep row, int mask)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+#endif
+
+   png_debug(1,"in png_combine_row_asm\n");
+
+   if (mmx_supported == 2) {
+       /* this should have happened in png_init_mmx_flags() already */
+       png_warning(png_ptr, "asm_flags may not have been initialized");
+       png_mmx_support();
+   }
+
+   if (mask == 0xff)
+   {
+      png_memcpy(row, png_ptr->row_buf + 1,
+       (png_size_t)((png_ptr->width * png_ptr->row_info.pixel_depth + 7) >> 3));
+   }
+   /* GRR:  add "else if (mask == 0)" case?
+    *       or does png_combine_row() not even get called in that case? */
+   else
+   {
+      switch (png_ptr->row_info.pixel_depth)
+      {
+         case 1:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int s_inc, s_start, s_end;
+            int m;
+            int shift;
+            png_uint_32 i;
+
+            sp = png_ptr->row_buf + 1;
+            dp = row;
+            m = 0x80;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+                s_start = 0;
+                s_end = 7;
+                s_inc = 1;
+            }
+            else
+#endif
+            {
+                s_start = 7;
+                s_end = 0;
+                s_inc = -1;
+            }
+
+            shift = s_start;
+
+            for (i = 0; i < png_ptr->width; i++)
+            {
+               if (m & mask)
+               {
+                  int value;
+
+                  value = (*sp >> shift) & 0x1;
+                  *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+
+         case 2:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int s_start, s_end, s_inc;
+            int m;
+            int shift;
+            png_uint_32 i;
+            int value;
+
+            sp = png_ptr->row_buf + 1;
+            dp = row;
+            m = 0x80;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+               s_start = 0;
+               s_end = 6;
+               s_inc = 2;
+            }
+            else
+#endif
+            {
+               s_start = 6;
+               s_end = 0;
+               s_inc = -2;
+            }
+
+            shift = s_start;
+
+            for (i = 0; i < png_ptr->width; i++)
+            {
+               if (m & mask)
+               {
+                  value = (*sp >> shift) & 0x3;
+                  *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+
+         case 4:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int s_start, s_end, s_inc;
+            int m;
+            int shift;
+            png_uint_32 i;
+            int value;
+
+            sp = png_ptr->row_buf + 1;
+            dp = row;
+            m = 0x80;
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (png_ptr->transformations & PNG_PACKSWAP)
+            {
+               s_start = 0;
+               s_end = 4;
+               s_inc = 4;
+            }
+            else
+#endif
+            {
+               s_start = 4;
+               s_end = 0;
+               s_inc = -4;
+            }
+            shift = s_start;
+
+            for (i = 0; i < png_ptr->width; i++)
+            {
+               if (m & mask)
+               {
+                  value = (*sp >> shift) & 0xf;
+                  *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+                  *dp |= (png_byte)(value << shift);
+               }
+
+               if (shift == s_end)
+               {
+                  shift = s_start;
+                  sp++;
+                  dp++;
+               }
+               else
+                  shift += s_inc;
+               if (m == 1)
+                  m = 0x80;
+               else
+                  m >>= 1;
+            }
+            break;
+         }
+
+         case 8:
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            png_uint_32 len;
+            int m;
+            int diff, unmask;
+
+            __int64 mask0=0x0102040810204080;
+
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
+                /* && mmx_supported */ )
+            {
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+               m = 0x80;
+               unmask = ~mask;
+               len  = png_ptr->width &~7;  //reduce to multiple of 8
+               diff = png_ptr->width & 7;  //amount lost
+
+               _asm
+               {
+                  movd       mm7, unmask   //load bit pattern
+                  psubb      mm6,mm6       //zero mm6
+                  punpcklbw  mm7,mm7
+                  punpcklwd  mm7,mm7
+                  punpckldq  mm7,mm7       //fill register with 8 masks
+
+                  movq       mm0,mask0
+
+                  pand       mm0,mm7       //nonzero if keep byte
+                  pcmpeqb    mm0,mm6       //zeros->1s, v versa
+
+                  mov        ecx,len       //load length of line (pixels)
+                  mov        esi,srcptr    //load source
+                  mov        ebx,dstptr    //load dest
+                  cmp        ecx,0         //lcr
+                  je         mainloop8end
+
+mainloop8:
+                  movq       mm4,[esi]
+                  pand       mm4,mm0
+                  movq       mm6,mm0
+                  pandn      mm6,[ebx]
+                  por        mm4,mm6
+                  movq       [ebx],mm4
+
+                  add        esi,8         //inc by 8 bytes processed
+                  add        ebx,8
+                  sub        ecx,8         //dec by 8 pixels processed
+
+                  ja         mainloop8
+mainloop8end:
+
+                  mov        ecx,diff
+                  cmp        ecx,0
+                  jz         end8
+
+                  mov        edx,mask
+                  sal        edx,24        //make low byte the high byte
+
+secondloop8:
+                  sal        edx,1         //move high bit to CF
+                  jnc        skip8         //if CF = 0
+                  mov        al,[esi]
+                  mov        [ebx],al
+skip8:
+                  inc        esi
+                  inc        ebx
+
+                  dec        ecx
+                  jnz        secondloop8
+end8:
+                  emms
+               }
+            }
+            else /* mmx not supported - use modified C routine */
+            {
+               register unsigned int incr1, initial_val, final_val;
+               png_size_t pixel_bytes;
+               png_uint_32 i;
+               register int disp = png_pass_inc[png_ptr->pass];
+               int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+
+               pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+               srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+                  pixel_bytes;
+               dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
+               initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+               final_val = png_ptr->width*pixel_bytes;
+               incr1 = (disp)*pixel_bytes;
+               for (i = initial_val; i < final_val; i += incr1)
+               {
+                  png_memcpy(dstptr, srcptr, pixel_bytes);
+                  srcptr += incr1;
+                  dstptr += incr1;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 8 bpp
+
+         case 16:
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            png_uint_32 len;
+            int unmask, diff;
+            __int64 mask1=0x0101020204040808,
+                    mask0=0x1010202040408080;
+
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
+                /* && mmx_supported */ )
+            {
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+
+               unmask = ~mask;
+               len     = (png_ptr->width)&~7;
+               diff = (png_ptr->width)&7;
+               _asm
+               {
+                  movd       mm7, unmask       //load bit pattern
+                  psubb      mm6,mm6           //zero mm6
+                  punpcklbw  mm7,mm7
+                  punpcklwd  mm7,mm7
+                  punpckldq  mm7,mm7           //fill register with 8 masks
+
+                  movq       mm0,mask0
+                  movq       mm1,mask1
+
+                  pand       mm0,mm7
+                  pand       mm1,mm7
+
+                  pcmpeqb    mm0,mm6
+                  pcmpeqb    mm1,mm6
+
+                  mov        ecx,len           //load length of line
+                  mov        esi,srcptr        //load source
+                  mov        ebx,dstptr        //load dest
+                  cmp        ecx,0             //lcr
+                  jz         mainloop16end
+
+mainloop16:
+                  movq       mm4,[esi]
+                  pand       mm4,mm0
+                  movq       mm6,mm0
+                  movq       mm7,[ebx]
+                  pandn      mm6,mm7
+                  por        mm4,mm6
+                  movq       [ebx],mm4
+
+                  movq       mm5,[esi+8]
+                  pand       mm5,mm1
+                  movq       mm7,mm1
+                  movq       mm6,[ebx+8]
+                  pandn      mm7,mm6
+                  por        mm5,mm7
+                  movq       [ebx+8],mm5
+
+                  add        esi,16            //inc by 16 bytes processed
+                  add        ebx,16
+                  sub        ecx,8             //dec by 8 pixels processed
+
+                  ja         mainloop16
+
+mainloop16end:
+                  mov        ecx,diff
+                  cmp        ecx,0
+                  jz         end16
+
+                  mov        edx,mask
+                  sal        edx,24            //make low byte the high byte
+secondloop16:
+                  sal        edx,1             //move high bit to CF
+                  jnc        skip16            //if CF = 0
+                  mov        ax,[esi]
+                  mov        [ebx],ax
+skip16:
+                  add        esi,2
+                  add        ebx,2
+
+                  dec        ecx
+                  jnz        secondloop16
+end16:
+                  emms
+               }
+            }
+            else /* mmx not supported - use modified C routine */
+            {
+               register unsigned int incr1, initial_val, final_val;
+               png_size_t pixel_bytes;
+               png_uint_32 i;
+               register int disp = png_pass_inc[png_ptr->pass];
+               int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+
+               pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+               srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+                  pixel_bytes;
+               dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
+               initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+               final_val = png_ptr->width*pixel_bytes;
+               incr1 = (disp)*pixel_bytes;
+               for (i = initial_val; i < final_val; i += incr1)
+               {
+                  png_memcpy(dstptr, srcptr, pixel_bytes);
+                  srcptr += incr1;
+                  dstptr += incr1;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 16 bpp
+
+         case 24:
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            png_uint_32 len;
+            int unmask, diff;
+
+            __int64 mask2=0x0101010202020404,  //24bpp
+                    mask1=0x0408080810101020,
+                    mask0=0x2020404040808080;
+
+            srcptr = png_ptr->row_buf + 1;
+            dstptr = row;
+
+            unmask = ~mask;
+            len     = (png_ptr->width)&~7;
+            diff = (png_ptr->width)&7;
+
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
+                /* && mmx_supported */ )
+            {
+               _asm
+               {
+                  movd       mm7, unmask       //load bit pattern
+                  psubb      mm6,mm6           //zero mm6
+                  punpcklbw  mm7,mm7
+                  punpcklwd  mm7,mm7
+                  punpckldq  mm7,mm7           //fill register with 8 masks
+
+                  movq       mm0,mask0
+                  movq       mm1,mask1
+                  movq       mm2,mask2
+
+                  pand       mm0,mm7
+                  pand       mm1,mm7
+                  pand       mm2,mm7
+
+                  pcmpeqb    mm0,mm6
+                  pcmpeqb    mm1,mm6
+                  pcmpeqb    mm2,mm6
+
+                  mov        ecx,len           //load length of line
+                  mov        esi,srcptr        //load source
+                  mov        ebx,dstptr        //load dest
+                  cmp        ecx,0
+                  jz         mainloop24end
+
+mainloop24:
+                  movq       mm4,[esi]
+                  pand       mm4,mm0
+                  movq       mm6,mm0
+                  movq       mm7,[ebx]
+                  pandn      mm6,mm7
+                  por        mm4,mm6
+                  movq       [ebx],mm4
+
+
+                  movq       mm5,[esi+8]
+                  pand       mm5,mm1
+                  movq       mm7,mm1
+                  movq       mm6,[ebx+8]
+                  pandn      mm7,mm6
+                  por        mm5,mm7
+                  movq       [ebx+8],mm5
+
+                  movq       mm6,[esi+16]
+                  pand       mm6,mm2
+                  movq       mm4,mm2
+                  movq       mm7,[ebx+16]
+                  pandn      mm4,mm7
+                  por        mm6,mm4
+                  movq       [ebx+16],mm6
+
+                  add        esi,24            //inc by 24 bytes processed
+                  add        ebx,24
+                  sub        ecx,8             //dec by 8 pixels processed
+
+                  ja         mainloop24
+
+mainloop24end:
+                  mov        ecx,diff
+                  cmp        ecx,0
+                  jz         end24
+
+                  mov        edx,mask
+                  sal        edx,24            //make low byte the high byte
+secondloop24:
+                  sal        edx,1             //move high bit to CF
+                  jnc        skip24            //if CF = 0
+                  mov        ax,[esi]
+                  mov        [ebx],ax
+                  xor        eax,eax
+                  mov        al,[esi+2]
+                  mov        [ebx+2],al
+skip24:
+                  add        esi,3
+                  add        ebx,3
+
+                  dec        ecx
+                  jnz        secondloop24
+
+end24:
+                  emms
+               }
+            }
+            else /* mmx not supported - use modified C routine */
+            {
+               register unsigned int incr1, initial_val, final_val;
+               png_size_t pixel_bytes;
+               png_uint_32 i;
+               register int disp = png_pass_inc[png_ptr->pass];
+               int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+
+               pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+               srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+                  pixel_bytes;
+               dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
+               initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+               final_val = png_ptr->width*pixel_bytes;
+               incr1 = (disp)*pixel_bytes;
+               for (i = initial_val; i < final_val; i += incr1)
+               {
+                  png_memcpy(dstptr, srcptr, pixel_bytes);
+                  srcptr += incr1;
+                  dstptr += incr1;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 24 bpp
+
+         case 32:
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            png_uint_32 len;
+            int unmask, diff;
+
+            __int64 mask3=0x0101010102020202,  //32bpp
+                    mask2=0x0404040408080808,
+                    mask1=0x1010101020202020,
+                    mask0=0x4040404080808080;
+
+            srcptr = png_ptr->row_buf + 1;
+            dstptr = row;
+
+            unmask = ~mask;
+            len     = (png_ptr->width)&~7;
+            diff = (png_ptr->width)&7;
+
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
+                /* && mmx_supported */ )
+            {
+               _asm
+               {
+                  movd       mm7, unmask       //load bit pattern
+                  psubb      mm6,mm6           //zero mm6
+                  punpcklbw  mm7,mm7
+                  punpcklwd  mm7,mm7
+                  punpckldq  mm7,mm7           //fill register with 8 masks
+
+                  movq       mm0,mask0
+                  movq       mm1,mask1
+                  movq       mm2,mask2
+                  movq       mm3,mask3
+
+                  pand       mm0,mm7
+                  pand       mm1,mm7
+                  pand       mm2,mm7
+                  pand       mm3,mm7
+
+                  pcmpeqb    mm0,mm6
+                  pcmpeqb    mm1,mm6
+                  pcmpeqb    mm2,mm6
+                  pcmpeqb    mm3,mm6
+
+                  mov        ecx,len           //load length of line
+                  mov        esi,srcptr        //load source
+                  mov        ebx,dstptr        //load dest
+
+                  cmp        ecx,0             //lcr
+                  jz         mainloop32end
+
+mainloop32:
+                  movq       mm4,[esi]
+                  pand       mm4,mm0
+                  movq       mm6,mm0
+                  movq       mm7,[ebx]
+                  pandn      mm6,mm7
+                  por        mm4,mm6
+                  movq       [ebx],mm4
+
+                  movq       mm5,[esi+8]
+                  pand       mm5,mm1
+                  movq       mm7,mm1
+                  movq       mm6,[ebx+8]
+                  pandn      mm7,mm6
+                  por        mm5,mm7
+                  movq       [ebx+8],mm5
+
+                  movq       mm6,[esi+16]
+                  pand       mm6,mm2
+                  movq       mm4,mm2
+                  movq       mm7,[ebx+16]
+                  pandn      mm4,mm7
+                  por        mm6,mm4
+                  movq       [ebx+16],mm6
+
+                  movq       mm7,[esi+24]
+                  pand       mm7,mm3
+                  movq       mm5,mm3
+                  movq       mm4,[ebx+24]
+                  pandn      mm5,mm4
+                  por        mm7,mm5
+                  movq       [ebx+24],mm7
+
+                  add        esi,32            //inc by 32 bytes processed
+                  add        ebx,32
+                  sub        ecx,8             //dec by 8 pixels processed
+
+                  ja         mainloop32
+
+mainloop32end:
+                  mov        ecx,diff
+                  cmp        ecx,0
+                  jz         end32
+
+                  mov        edx,mask
+                  sal        edx,24            //make low byte the high byte
+secondloop32:
+                  sal        edx,1             //move high bit to CF
+                  jnc        skip32            //if CF = 0
+                  mov        eax,[esi]
+                  mov        [ebx],eax
+skip32:
+                  add        esi,4
+                  add        ebx,4
+
+                  dec        ecx
+                  jnz        secondloop32
+
+end32:
+                  emms
+               }
+            }
+            else /* mmx _not supported - Use modified C routine */
+            {
+               register unsigned int incr1, initial_val, final_val;
+               png_size_t pixel_bytes;
+               png_uint_32 i;
+               register int disp = png_pass_inc[png_ptr->pass];
+               int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+
+               pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+               srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+                  pixel_bytes;
+               dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
+               initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+               final_val = png_ptr->width*pixel_bytes;
+               incr1 = (disp)*pixel_bytes;
+               for (i = initial_val; i < final_val; i += incr1)
+               {
+                  png_memcpy(dstptr, srcptr, pixel_bytes);
+                  srcptr += incr1;
+                  dstptr += incr1;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 32 bpp
+
+         case 48:
+         {
+            png_bytep srcptr;
+            png_bytep dstptr;
+            png_uint_32 len;
+            int unmask, diff;
+
+            __int64 mask5=0x0101010101010202,
+                    mask4=0x0202020204040404,
+                    mask3=0x0404080808080808,
+                    mask2=0x1010101010102020,
+                    mask1=0x2020202040404040,
+                    mask0=0x4040808080808080;
+
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)
+                /* && mmx_supported */ )
+            {
+               srcptr = png_ptr->row_buf + 1;
+               dstptr = row;
+
+               unmask = ~mask;
+               len     = (png_ptr->width)&~7;
+               diff = (png_ptr->width)&7;
+               _asm
+               {
+                  movd       mm7, unmask       //load bit pattern
+                  psubb      mm6,mm6           //zero mm6
+                  punpcklbw  mm7,mm7
+                  punpcklwd  mm7,mm7
+                  punpckldq  mm7,mm7           //fill register with 8 masks
+
+                  movq       mm0,mask0
+                  movq       mm1,mask1
+                  movq       mm2,mask2
+                  movq       mm3,mask3
+                  movq       mm4,mask4
+                  movq       mm5,mask5
+
+                  pand       mm0,mm7
+                  pand       mm1,mm7
+                  pand       mm2,mm7
+                  pand       mm3,mm7
+                  pand       mm4,mm7
+                  pand       mm5,mm7
+
+                  pcmpeqb    mm0,mm6
+                  pcmpeqb    mm1,mm6
+                  pcmpeqb    mm2,mm6
+                  pcmpeqb    mm3,mm6
+                  pcmpeqb    mm4,mm6
+                  pcmpeqb    mm5,mm6
+
+                  mov        ecx,len           //load length of line
+                  mov        esi,srcptr        //load source
+                  mov        ebx,dstptr        //load dest
+
+                  cmp        ecx,0
+                  jz         mainloop48end
+
+mainloop48:
+                  movq       mm7,[esi]
+                  pand       mm7,mm0
+                  movq       mm6,mm0
+                  pandn      mm6,[ebx]
+                  por        mm7,mm6
+                  movq       [ebx],mm7
+
+                  movq       mm6,[esi+8]
+                  pand       mm6,mm1
+                  movq       mm7,mm1
+                  pandn      mm7,[ebx+8]
+                  por        mm6,mm7
+                  movq       [ebx+8],mm6
+
+                  movq       mm6,[esi+16]
+                  pand       mm6,mm2
+                  movq       mm7,mm2
+                  pandn      mm7,[ebx+16]
+                  por        mm6,mm7
+                  movq       [ebx+16],mm6
+
+                  movq       mm7,[esi+24]
+                  pand       mm7,mm3
+                  movq       mm6,mm3
+                  pandn      mm6,[ebx+24]
+                  por        mm7,mm6
+                  movq       [ebx+24],mm7
+
+                  movq       mm6,[esi+32]
+                  pand       mm6,mm4
+                  movq       mm7,mm4
+                  pandn      mm7,[ebx+32]
+                  por        mm6,mm7
+                  movq       [ebx+32],mm6
+
+                  movq       mm7,[esi+40]
+                  pand       mm7,mm5
+                  movq       mm6,mm5
+                  pandn      mm6,[ebx+40]
+                  por        mm7,mm6
+                  movq       [ebx+40],mm7
+
+                  add        esi,48            //inc by 32 bytes processed
+                  add        ebx,48
+                  sub        ecx,8             //dec by 8 pixels processed
+
+                  ja         mainloop48
+mainloop48end:
+
+                  mov        ecx,diff
+                  cmp        ecx,0
+                  jz         end48
+
+                  mov        edx,mask
+                  sal        edx,24            //make low byte the high byte
+
+secondloop48:
+                  sal        edx,1             //move high bit to CF
+                  jnc        skip48            //if CF = 0
+                  mov        eax,[esi]
+                  mov        [ebx],eax
+skip48:
+                  add        esi,4
+                  add        ebx,4
+
+                  dec        ecx
+                  jnz        secondloop48
+
+end48:
+                  emms
+               }
+            }
+            else /* mmx _not supported - Use modified C routine */
+            {
+               register unsigned int incr1, initial_val, final_val;
+               png_size_t pixel_bytes;
+               png_uint_32 i;
+               register int disp = png_pass_inc[png_ptr->pass];
+               int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+
+               pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+               srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+                  pixel_bytes;
+               dstptr = row + offset_table[png_ptr->pass]*pixel_bytes;
+               initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+               final_val = png_ptr->width*pixel_bytes;
+               incr1 = (disp)*pixel_bytes;
+               for (i = initial_val; i < final_val; i += incr1)
+               {
+                  png_memcpy(dstptr, srcptr, pixel_bytes);
+                  srcptr += incr1;
+                  dstptr += incr1;
+               }
+            } /* end of else */
+
+            break;
+         }       // end 48 bpp
+
+         default:
+         {
+            png_bytep sptr;
+            png_bytep dp;
+            png_size_t pixel_bytes;
+            int offset_table[7] = {0, 4, 0, 2, 0, 1, 0};
+            unsigned int i;
+            register int disp = png_pass_inc[png_ptr->pass];  // get the offset
+            register unsigned int incr1, initial_val, final_val;
+
+            pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+            sptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]*
+               pixel_bytes;
+            dp = row + offset_table[png_ptr->pass]*pixel_bytes;
+            initial_val = offset_table[png_ptr->pass]*pixel_bytes;
+            final_val = png_ptr->width*pixel_bytes;
+            incr1 = (disp)*pixel_bytes;
+            for (i = initial_val; i < final_val; i += incr1)
+            {
+               png_memcpy(dp, sptr, pixel_bytes);
+               sptr += incr1;
+               dp += incr1;
+            }
+            break;
+         }
+      } /* end switch (png_ptr->row_info.pixel_depth) */
+   } /* end if (non-trivial mask) */
+
+} /* end png_combine_row() */
+
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED)
+
+void /* PRIVATE */
+png_do_read_interlace(png_structp png_ptr)
+{
+   png_row_infop row_info = &(png_ptr->row_info);
+   png_bytep row = png_ptr->row_buf + 1;
+   int pass = png_ptr->pass;
+   png_uint_32 transformations = png_ptr->transformations;
+#ifdef PNG_USE_LOCAL_ARRAYS
+   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+#endif
+
+   png_debug(1,"in png_do_read_interlace\n");
+
+   if (mmx_supported == 2) {
+       /* this should have happened in png_init_mmx_flags() already */
+       png_warning(png_ptr, "asm_flags may not have been initialized");
+       png_mmx_support();
+   }
+
+   if (row != NULL && row_info != NULL)
+   {
+      png_uint_32 final_width;
+
+      final_width = row_info->width * png_pass_inc[pass];
+
+      switch (row_info->pixel_depth)
+      {
+         case 1:
+         {
+            png_bytep sp, dp;
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_byte v;
+            png_uint_32 i;
+            int j;
+
+            sp = row + (png_size_t)((row_info->width - 1) >> 3);
+            dp = row + (png_size_t)((final_width - 1) >> 3);
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (int)((row_info->width + 7) & 7);
+               dshift = (int)((final_width + 7) & 7);
+               s_start = 7;
+               s_end = 0;
+               s_inc = -1;
+            }
+            else
+#endif
+            {
+               sshift = 7 - (int)((row_info->width + 7) & 7);
+               dshift = 7 - (int)((final_width + 7) & 7);
+               s_start = 0;
+               s_end = 7;
+               s_inc = 1;
+            }
+
+            for (i = row_info->width; i; i--)
+            {
+               v = (png_byte)((*sp >> sshift) & 0x1);
+               for (j = 0; j < png_pass_inc[pass]; j++)
+               {
+                  *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+
+         case 2:
+         {
+            png_bytep sp, dp;
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_uint_32 i;
+
+            sp = row + (png_size_t)((row_info->width - 1) >> 2);
+            dp = row + (png_size_t)((final_width - 1) >> 2);
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (png_size_t)(((row_info->width + 3) & 3) << 1);
+               dshift = (png_size_t)(((final_width + 3) & 3) << 1);
+               s_start = 6;
+               s_end = 0;
+               s_inc = -2;
+            }
+            else
+#endif
+            {
+               sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1);
+               dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1);
+               s_start = 0;
+               s_end = 6;
+               s_inc = 2;
+            }
+
+            for (i = row_info->width; i; i--)
+            {
+               png_byte v;
+               int j;
+
+               v = (png_byte)((*sp >> sshift) & 0x3);
+               for (j = 0; j < png_pass_inc[pass]; j++)
+               {
+                  *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+
+         case 4:
+         {
+            png_bytep sp, dp;
+            int sshift, dshift;
+            int s_start, s_end, s_inc;
+            png_uint_32 i;
+
+            sp = row + (png_size_t)((row_info->width - 1) >> 1);
+            dp = row + (png_size_t)((final_width - 1) >> 1);
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)
+            if (transformations & PNG_PACKSWAP)
+            {
+               sshift = (png_size_t)(((row_info->width + 1) & 1) << 2);
+               dshift = (png_size_t)(((final_width + 1) & 1) << 2);
+               s_start = 4;
+               s_end = 0;
+               s_inc = -4;
+            }
+            else
+#endif
+            {
+               sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2);
+               dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2);
+               s_start = 0;
+               s_end = 4;
+               s_inc = 4;
+            }
+
+            for (i = row_info->width; i; i--)
+            {
+               png_byte v;
+               int j;
+
+               v = (png_byte)((*sp >> sshift) & 0xf);
+               for (j = 0; j < png_pass_inc[pass]; j++)
+               {
+                  *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
+                  *dp |= (png_byte)(v << dshift);
+                  if (dshift == s_end)
+                  {
+                     dshift = s_start;
+                     dp--;
+                  }
+                  else
+                     dshift += s_inc;
+               }
+               if (sshift == s_end)
+               {
+                  sshift = s_start;
+                  sp--;
+               }
+               else
+                  sshift += s_inc;
+            }
+            break;
+         }
+
+         default:         // This is the place where the routine is modified
+         {
+            __int64 const4 = 0x0000000000FFFFFF;
+            // __int64 const5 = 0x000000FFFFFF0000;  // unused...
+            __int64 const6 = 0x00000000000000FF;
+            png_bytep sptr, dp;
+            png_uint_32 i;
+            png_size_t pixel_bytes;
+            int width = row_info->width;
+
+            pixel_bytes = (row_info->pixel_depth >> 3);
+
+            sptr = row + (width - 1) * pixel_bytes;
+            dp = row + (final_width - 1) * pixel_bytes;
+            // New code by Nirav Chhatrapati - Intel Corporation
+            // sign fix by GRR
+            // NOTE:  there is NO MMX code for 48-bit and 64-bit images
+
+            // use MMX routine if machine supports it
+            if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_INTERLACE)
+                /* && mmx_supported */ )
+            {
+               if (pixel_bytes == 3)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     _asm
+                     {
+                        mov esi, sptr
+                        mov edi, dp
+                        mov ecx, width
+                        sub edi, 21   // (png_pass_inc[pass] - 1)*pixel_bytes
+loop_pass0:
+                        movd mm0, [esi]     ; X X X X X v2 v1 v0
+                        pand mm0, const4    ; 0 0 0 0 0 v2 v1 v0
+                        movq mm1, mm0       ; 0 0 0 0 0 v2 v1 v0
+                        psllq mm0, 16       ; 0 0 0 v2 v1 v0 0 0
+                        movq mm2, mm0       ; 0 0 0 v2 v1 v0 0 0
+                        psllq mm0, 24       ; v2 v1 v0 0 0 0 0 0
+                        psrlq mm1, 8        ; 0 0 0 0 0 0 v2 v1
+                        por mm0, mm2        ; v2 v1 v0 v2 v1 v0 0 0
+                        por mm0, mm1        ; v2 v1 v0 v2 v1 v0 v2 v1
+                        movq mm3, mm0       ; v2 v1 v0 v2 v1 v0 v2 v1
+                        psllq mm0, 16       ; v0 v2 v1 v0 v2 v1 0 0
+                        movq mm4, mm3       ; v2 v1 v0 v2 v1 v0 v2 v1
+                        punpckhdq mm3, mm0  ; v0 v2 v1 v0 v2 v1 v0 v2
+                        movq [edi+16] , mm4
+                        psrlq mm0, 32       ; 0 0 0 0 v0 v2 v1 v0
+                        movq [edi+8] , mm3
+                        punpckldq mm0, mm4  ; v1 v0 v2 v1 v0 v2 v1 v0
+                        sub esi, 3
+                        movq [edi], mm0
+                        sub edi, 24
+                        //sub esi, 3
+                        dec ecx
+                        jnz loop_pass0
+                        EMMS
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     _asm
+                     {
+                        mov esi, sptr
+                        mov edi, dp
+                        mov ecx, width
+                        sub edi, 9   // (png_pass_inc[pass] - 1)*pixel_bytes
+loop_pass2:
+                        movd mm0, [esi]     ; X X X X X v2 v1 v0
+                        pand mm0, const4    ; 0 0 0 0 0 v2 v1 v0
+                        movq mm1, mm0       ; 0 0 0 0 0 v2 v1 v0
+                        psllq mm0, 16       ; 0 0 0 v2 v1 v0 0 0
+                        movq mm2, mm0       ; 0 0 0 v2 v1 v0 0 0
+                        psllq mm0, 24       ; v2 v1 v0 0 0 0 0 0
+                        psrlq mm1, 8        ; 0 0 0 0 0 0 v2 v1
+                        por mm0, mm2        ; v2 v1 v0 v2 v1 v0 0 0
+                        por mm0, mm1        ; v2 v1 v0 v2 v1 v0 v2 v1
+                        movq [edi+4], mm0   ; move to memory
+                        psrlq mm0, 16       ; 0 0 v2 v1 v0 v2 v1 v0
+                        movd [edi], mm0     ; move to memory
+                        sub esi, 3
+                        sub edi, 12
+                        dec ecx
+                        jnz loop_pass2
+                        EMMS
+                     }
+                  }
+                  else if (width) /* && ((pass == 4) || (pass == 5)) */
+                  {
+                     int width_mmx = ((width >> 1) << 1) - 8;
+                     if (width_mmx < 0)
+                         width_mmx = 0;
+                     width -= width_mmx;        // 8 or 9 pix, 24 or 27 bytes
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 3
+                           sub edi, 9
+loop_pass4:
+                           movq mm0, [esi]     ; X X v2 v1 v0 v5 v4 v3
+                           movq mm7, mm0       ; X X v2 v1 v0 v5 v4 v3
+                           movq mm6, mm0       ; X X v2 v1 v0 v5 v4 v3
+                           psllq mm0, 24       ; v1 v0 v5 v4 v3 0 0 0
+                           pand mm7, const4    ; 0 0 0 0 0 v5 v4 v3
+                           psrlq mm6, 24       ; 0 0 0 X X v2 v1 v0
+                           por mm0, mm7        ; v1 v0 v5 v4 v3 v5 v4 v3
+                           movq mm5, mm6       ; 0 0 0 X X v2 v1 v0
+                           psllq mm6, 8        ; 0 0 X X v2 v1 v0 0
+                           movq [edi], mm0     ; move quad to memory
+                           psrlq mm5, 16       ; 0 0 0 0 0 X X v2
+                           pand mm5, const6    ; 0 0 0 0 0 0 0 v2
+                           por mm6, mm5        ; 0 0 X X v2 v1 v0 v2
+                           movd [edi+8], mm6   ; move double to memory
+                           sub esi, 6
+                           sub edi, 12
+                           sub ecx, 2
+                           jnz loop_pass4
+                           EMMS
+                        }
+                     }
+
+                     sptr -= width_mmx*3;
+                     dp -= width_mmx*6;
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+
+                        png_memcpy(v, sptr, 3);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           png_memcpy(dp, v, 3);
+                           dp -= 3;
+                        }
+                        sptr -= 3;
+                     }
+                  }
+               } /* end of pixel_bytes == 3 */
+
+               else if (pixel_bytes == 1)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int width_mmx = ((width >> 2) << 2);
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub edi, 31
+                           sub esi, 3
+loop1_pass0:
+                           movd mm0, [esi]     ; X X X X v0 v1 v2 v3
+                           movq mm1, mm0       ; X X X X v0 v1 v2 v3
+                           punpcklbw mm0, mm0  ; v0 v0 v1 v1 v2 v2 v3 v3
+                           movq mm2, mm0       ; v0 v0 v1 v1 v2 v2 v3 v3
+                           punpcklwd mm0, mm0  ; v2 v2 v2 v2 v3 v3 v3 v3
+                           movq mm3, mm0       ; v2 v2 v2 v2 v3 v3 v3 v3
+                           punpckldq mm0, mm0  ; v3 v3 v3 v3 v3 v3 v3 v3
+                           punpckhdq mm3, mm3  ; v2 v2 v2 v2 v2 v2 v2 v2
+                           movq [edi], mm0     ; move to memory v3
+                           punpckhwd mm2, mm2  ; v0 v0 v0 v0 v1 v1 v1 v1
+                           movq [edi+8], mm3   ; move to memory v2
+                           movq mm4, mm2       ; v0 v0 v0 v0 v1 v1 v1 v1
+                           punpckldq mm2, mm2  ; v1 v1 v1 v1 v1 v1 v1 v1
+                           punpckhdq mm4, mm4  ; v0 v0 v0 v0 v0 v0 v0 v0
+                           movq [edi+16], mm2  ; move to memory v1
+                           movq [edi+24], mm4  ; move to memory v0
+                           sub esi, 4
+                           sub edi, 32
+                           sub ecx, 4
+                           jnz loop1_pass0
+                           EMMS
+                        }
+                     }
+
+                     sptr -= width_mmx;
+                     dp -= width_mmx*8;
+                     for (i = width; i; i--)
+                     {
+                        int j;
+
+                       /* I simplified this part in version 1.0.4e
+                        * here and in several other instances where
+                        * pixel_bytes == 1  -- GR-P
+                        *
+                        * Original code:
+                        *
+                        * png_byte v[8];
+                        * png_memcpy(v, sptr, pixel_bytes);
+                        * for (j = 0; j < png_pass_inc[pass]; j++)
+                        * {
+                        *    png_memcpy(dp, v, pixel_bytes);
+                        *    dp -= pixel_bytes;
+                        * }
+                        * sptr -= pixel_bytes;
+                        *
+                        * Replacement code is in the next three lines:
+                        */
+
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                           *dp-- = *sptr;
+                        sptr--;
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int width_mmx = ((width >> 2) << 2);
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub edi, 15
+                           sub esi, 3
+loop1_pass2:
+                           movd mm0, [esi]     ; X X X X v0 v1 v2 v3
+                           punpcklbw mm0, mm0  ; v0 v0 v1 v1 v2 v2 v3 v3
+                           movq mm1, mm0       ; v0 v0 v1 v1 v2 v2 v3 v3
+                           punpcklwd mm0, mm0  ; v2 v2 v2 v2 v3 v3 v3 v3
+                           punpckhwd mm1, mm1  ; v0 v0 v0 v0 v1 v1 v1 v1
+                           movq [edi], mm0     ; move to memory v2 and v3
+                           sub esi, 4
+                           movq [edi+8], mm1   ; move to memory v1     and v0
+                           sub edi, 16
+                           sub ecx, 4
+                           jnz loop1_pass2
+                           EMMS
+                        }
+                     }
+
+                     sptr -= width_mmx;
+                     dp -= width_mmx*4;
+                     for (i = width; i; i--)
+                     {
+                        int j;
+
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           *dp-- = *sptr;
+                        }
+                        sptr --;
+                     }
+                  }
+                  else if (width) /* && ((pass == 4) || (pass == 5))) */
+                  {
+                     int width_mmx = ((width >> 3) << 3);
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub edi, 15
+                           sub esi, 7
+loop1_pass4:
+                           movq mm0, [esi]     ; v0 v1 v2 v3 v4 v5 v6 v7
+                           movq mm1, mm0       ; v0 v1 v2 v3 v4 v5 v6 v7
+                           punpcklbw mm0, mm0  ; v4 v4 v5 v5 v6 v6 v7 v7
+                           //movq mm1, mm0     ; v0 v0 v1 v1 v2 v2 v3 v3
+                           punpckhbw mm1, mm1  ;v0 v0 v1 v1 v2 v2 v3 v3
+                           movq [edi+8], mm1   ; move to memory v0 v1 v2 and v3
+                           sub esi, 8
+                           movq [edi], mm0     ; move to memory v4 v5 v6 and v7
+                           //sub esi, 4
+                           sub edi, 16
+                           sub ecx, 8
+                           jnz loop1_pass4
+                           EMMS
+                        }
+                     }
+
+                     sptr -= width_mmx;
+                     dp -= width_mmx*2;
+                     for (i = width; i; i--)
+                     {
+                        int j;
+
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           *dp-- = *sptr;
+                        }
+                        sptr --;
+                     }
+                  }
+               } /* end of pixel_bytes == 1 */
+
+               else if (pixel_bytes == 2)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1);
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 2
+                           sub edi, 30
+loop2_pass0:
+                           movd mm0, [esi]        ; X X X X v1 v0 v3 v2
+                           punpcklwd mm0, mm0     ; v1 v0 v1 v0 v3 v2 v3 v2
+                           movq mm1, mm0          ; v1 v0 v1 v0 v3 v2 v3 v2
+                           punpckldq mm0, mm0     ; v3 v2 v3 v2 v3 v2 v3 v2
+                           punpckhdq mm1, mm1     ; v1 v0 v1 v0 v1 v0 v1 v0
+                           movq [edi], mm0
+                           movq [edi + 8], mm0
+                           movq [edi + 16], mm1
+                           movq [edi + 24], mm1
+                           sub esi, 4
+                           sub edi, 32
+                           sub ecx, 2
+                           jnz loop2_pass0
+                           EMMS
+                        }
+                     }
+
+                     sptr -= (width_mmx*2 - 2);            // sign fixed
+                     dp -= (width_mmx*16 - 2);            // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 2;
+                        png_memcpy(v, sptr, 2);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 2;
+                           png_memcpy(dp, v, 2);
+                        }
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 2
+                           sub edi, 14
+loop2_pass2:
+                           movd mm0, [esi]        ; X X X X v1 v0 v3 v2
+                           punpcklwd mm0, mm0     ; v1 v0 v1 v0 v3 v2 v3 v2
+                           movq mm1, mm0          ; v1 v0 v1 v0 v3 v2 v3 v2
+                           punpckldq mm0, mm0     ; v3 v2 v3 v2 v3 v2 v3 v2
+                           punpckhdq mm1, mm1     ; v1 v0 v1 v0 v1 v0 v1 v0
+                           movq [edi], mm0
+                           sub esi, 4
+                           movq [edi + 8], mm1
+                           //sub esi, 4
+                           sub edi, 16
+                           sub ecx, 2
+                           jnz loop2_pass2
+                           EMMS
+                        }
+                     }
+
+                     sptr -= (width_mmx*2 - 2);            // sign fixed
+                     dp -= (width_mmx*8 - 2);            // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 2;
+                        png_memcpy(v, sptr, 2);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 2;
+                           png_memcpy(dp, v, 2);
+                        }
+                     }
+                  }
+                  else if (width)  // pass == 4 or 5
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 2
+                           sub edi, 6
+loop2_pass4:
+                           movd mm0, [esi]        ; X X X X v1 v0 v3 v2
+                           punpcklwd mm0, mm0     ; v1 v0 v1 v0 v3 v2 v3 v2
+                           sub esi, 4
+                           movq [edi], mm0
+                           sub edi, 8
+                           sub ecx, 2
+                           jnz loop2_pass4
+                           EMMS
+                        }
+                     }
+
+                     sptr -= (width_mmx*2 - 2);            // sign fixed
+                     dp -= (width_mmx*4 - 2);            // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 2;
+                        png_memcpy(v, sptr, 2);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 2;
+                           png_memcpy(dp, v, 2);
+                        }
+                     }
+                  }
+               } /* end of pixel_bytes == 2 */
+
+               else if (pixel_bytes == 4)
+               {
+                  if (((pass == 0) || (pass == 1)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 4
+                           sub edi, 60
+loop4_pass0:
+                           movq mm0, [esi]        ; v3 v2 v1 v0 v7 v6 v5 v4
+                           movq mm1, mm0          ; v3 v2 v1 v0 v7 v6 v5 v4
+                           punpckldq mm0, mm0     ; v7 v6 v5 v4 v7 v6 v5 v4
+                           punpckhdq mm1, mm1     ; v3 v2 v1 v0 v3 v2 v1 v0
+                           movq [edi], mm0
+                           movq [edi + 8], mm0
+                           movq [edi + 16], mm0
+                           movq [edi + 24], mm0
+                           movq [edi+32], mm1
+                           movq [edi + 40], mm1
+                           movq [edi+ 48], mm1
+                           sub esi, 8
+                           movq [edi + 56], mm1
+                           sub edi, 64
+                           sub ecx, 2
+                           jnz loop4_pass0
+                           EMMS
+                        }
+                     }
+
+                     sptr -= (width_mmx*4 - 4);            // sign fixed
+                     dp -= (width_mmx*32 - 4);            // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 4;
+                        png_memcpy(v, sptr, 4);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 4;
+                           png_memcpy(dp, v, 4);
+                        }
+                     }
+                  }
+                  else if (((pass == 2) || (pass == 3)) && width)
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 4
+                           sub edi, 28
+loop4_pass2:
+                           movq mm0, [esi]      ; v3 v2 v1 v0 v7 v6 v5 v4
+                           movq mm1, mm0        ; v3 v2 v1 v0 v7 v6 v5 v4
+                           punpckldq mm0, mm0   ; v7 v6 v5 v4 v7 v6 v5 v4
+                           punpckhdq mm1, mm1   ; v3 v2 v1 v0 v3 v2 v1 v0
+                           movq [edi], mm0
+                           movq [edi + 8], mm0
+                           movq [edi+16], mm1
+                           movq [edi + 24], mm1
+                           sub esi, 8
+                           sub edi, 32
+                           sub ecx, 2
+                           jnz loop4_pass2
+                           EMMS
+                        }
+                     }
+
+                     sptr -= (width_mmx*4 - 4);            // sign fixed
+                     dp -= (width_mmx*16 - 4);            // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 4;
+                        png_memcpy(v, sptr, 4);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 4;
+                           png_memcpy(dp, v, 4);
+                        }
+                     }
+                  }
+                  else if (width)  // pass == 4 or 5
+                  {
+                     int width_mmx = ((width >> 1) << 1) ;
+                     width -= width_mmx;
+                     if (width_mmx)
+                     {
+                        _asm
+                        {
+                           mov esi, sptr
+                           mov edi, dp
+                           mov ecx, width_mmx
+                           sub esi, 4
+                           sub edi, 12
+loop4_pass4:
+                           movq mm0, [esi]      ; v3 v2 v1 v0 v7 v6 v5 v4
+                           movq mm1, mm0        ; v3 v2 v1 v0 v7 v6 v5 v4
+                           punpckldq mm0, mm0   ; v7 v6 v5 v4 v7 v6 v5 v4
+                           punpckhdq mm1, mm1   ; v3 v2 v1 v0 v3 v2 v1 v0
+                           movq [edi], mm0
+                           sub esi, 8
+                           movq [edi + 8], mm1
+                           sub edi, 16
+                           sub ecx, 2
+                           jnz loop4_pass4
+                           EMMS
+                        }
+                     }
+
+                     sptr -= (width_mmx*4 - 4);          // sign fixed
+                     dp -= (width_mmx*8 - 4);            // sign fixed
+                     for (i = width; i; i--)
+                     {
+                        png_byte v[8];
+                        int j;
+                        sptr -= 4;
+                        png_memcpy(v, sptr, 4);
+                        for (j = 0; j < png_pass_inc[pass]; j++)
+                        {
+                           dp -= 4;
+                           png_memcpy(dp, v, 4);
+                        }
+                     }
+                  }
+
+               } /* end of pixel_bytes == 4 */
+
+               else if (pixel_bytes == 6)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, 6);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, 6);
+                        dp -= 6;
+                     }
+                     sptr -= 6;
+                  }
+               } /* end of pixel_bytes == 6 */
+
+               else
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr-= pixel_bytes;
+                  }
+               }
+            } /* end of mmx_supported */
+
+            else /* MMX not supported:  use modified C code - takes advantage
+                  * of inlining of memcpy for a constant */
+            {
+               if (pixel_bytes == 1)
+               {
+                  for (i = width; i; i--)
+                  {
+                     int j;
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                        *dp-- = *sptr;
+                     sptr--;
+                  }
+               }
+               else if (pixel_bytes == 3)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr -= pixel_bytes;
+                  }
+               }
+               else if (pixel_bytes == 2)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr -= pixel_bytes;
+                  }
+               }
+               else if (pixel_bytes == 4)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr -= pixel_bytes;
+                  }
+               }
+               else if (pixel_bytes == 6)
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr -= pixel_bytes;
+                  }
+               }
+               else
+               {
+                  for (i = width; i; i--)
+                  {
+                     png_byte v[8];
+                     int j;
+                     png_memcpy(v, sptr, pixel_bytes);
+                     for (j = 0; j < png_pass_inc[pass]; j++)
+                     {
+                        png_memcpy(dp, v, pixel_bytes);
+                        dp -= pixel_bytes;
+                     }
+                     sptr -= pixel_bytes;
+                  }
+               }
+
+            } /* end of MMX not supported */
+            break;
+         }
+      } /* end switch (row_info->pixel_depth) */
+
+      row_info->width = final_width;
+      row_info->rowbytes = ((final_width *
+         (png_uint_32)row_info->pixel_depth + 7) >> 3);
+   }
+
+}
+
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+
+
+// These variables are utilized in the functions below.  They are declared
+// globally here to ensure alignment on 8-byte boundaries.
+
+union uAll {
+   __int64 use;
+   double  align;
+} LBCarryMask = {0x0101010101010101},
+  HBClearMask = {0x7f7f7f7f7f7f7f7f},
+  ActiveMask, ActiveMask2, ActiveMaskEnd, ShiftBpp, ShiftRem;
+
+
+// Optimized code for PNG Average filter decoder
+void /* PRIVATE */
+png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row
+                            , png_bytep prev_row)
+{
+   int bpp;
+   png_uint_32 FullLength;
+   png_uint_32 MMXLength;
+   //png_uint_32 len;
+   int diff;
+
+   bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
+   FullLength  = row_info->rowbytes; // # of bytes to filter
+   _asm {
+         // Init address pointers and offset
+         mov edi, row          // edi ==> Avg(x)
+         xor ebx, ebx          // ebx ==> x
+         mov edx, edi
+         mov esi, prev_row           // esi ==> Prior(x)
+         sub edx, bpp          // edx ==> Raw(x-bpp)
+
+         xor eax, eax
+         // Compute the Raw value for the first bpp bytes
+         //    Raw(x) = Avg(x) + (Prior(x)/2)
+davgrlp:
+         mov al, [esi + ebx]   // Load al with Prior(x)
+         inc ebx
+         shr al, 1             // divide by 2
+         add al, [edi+ebx-1]   // Add Avg(x); -1 to offset inc ebx
+         cmp ebx, bpp
+         mov [edi+ebx-1], al    // Write back Raw(x);
+                            // mov does not affect flags; -1 to offset inc ebx
+         jb davgrlp
+         // get # of bytes to alignment
+         mov diff, edi         // take start of row
+         add diff, ebx         // add bpp
+         add diff, 0xf         // add 7 + 8 to incr past alignment boundary
+         and diff, 0xfffffff8  // mask to alignment boundary
+         sub diff, edi         // subtract from start ==> value ebx at alignment
+         jz davggo
+         // fix alignment
+         // Compute the Raw value for the bytes upto the alignment boundary
+         //    Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+         xor ecx, ecx
+davglp1:
+         xor eax, eax
+         mov cl, [esi + ebx]        // load cl with Prior(x)
+         mov al, [edx + ebx]  // load al with Raw(x-bpp)
+         add ax, cx
+         inc ebx
+         shr ax, 1            // divide by 2
+         add al, [edi+ebx-1]  // Add Avg(x); -1 to offset inc ebx
+         cmp ebx, diff              // Check if at alignment boundary
+         mov [edi+ebx-1], al        // Write back Raw(x);
+                            // mov does not affect flags; -1 to offset inc ebx
+         jb davglp1               // Repeat until at alignment boundary
+davggo:
+         mov eax, FullLength
+         mov ecx, eax
+         sub eax, ebx          // subtract alignment fix
+         and eax, 0x00000007   // calc bytes over mult of 8
+         sub ecx, eax          // drop over bytes from original length
+         mov MMXLength, ecx
+   } // end _asm block
+   // Now do the math for the rest of the row
+   switch ( bpp )
+   {
+      case 3:
+      {
+         ActiveMask.use  = 0x0000000000ffffff;
+         ShiftBpp.use = 24;    // == 3 * 8
+         ShiftRem.use = 40;    // == 64 - 24
+         _asm {
+            // Re-init address pointers and offset
+            movq mm7, ActiveMask
+            mov ebx, diff      // ebx ==> x = offset to alignment boundary
+            movq mm5, LBCarryMask
+            mov edi, row       // edi ==> Avg(x)
+            movq mm4, HBClearMask
+            mov esi, prev_row        // esi ==> Prior(x)
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
+                               // (we correct position in loop below)
+davg3lp:
+            movq mm0, [edi + ebx]      // Load mm0 with Avg(x)
+            // Add (Prev_row/2) to Average
+            movq mm3, mm5
+            psrlq mm2, ShiftRem      // Correct position Raw(x-bpp) data
+            movq mm1, [esi + ebx]    // Load mm1 with Prior(x)
+            movq mm6, mm7
+            pand mm3, mm1      // get lsb for each prev_row byte
+            psrlq mm1, 1       // divide prev_row bytes by 2
+            pand  mm1, mm4     // clear invalid bit 7 of each byte
+            paddb mm0, mm1     // add (Prev_row/2) to Avg for each byte
+            // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
+            movq mm1, mm3      // now use mm1 for getting LBCarrys
+            pand mm1, mm2      // get LBCarrys for each byte where both
+                               // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1       // divide raw bytes by 2
+            pand  mm2, mm4     // clear invalid bit 7 of each byte
+            paddb mm2, mm1     // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6      // Leave only Active Group 1 bytes to add to Avg
+            paddb mm0, mm2     // add (Raw/2) + LBCarrys to Avg for each Active
+                               //  byte
+            // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
+            psllq mm6, ShiftBpp  // shift the mm6 mask to cover bytes 3-5
+            movq mm2, mm0        // mov updated Raws to mm2
+            psllq mm2, ShiftBpp  // shift data to position correctly
+            movq mm1, mm3        // now use mm1 for getting LBCarrys
+            pand mm1, mm2      // get LBCarrys for each byte where both
+                               // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1       // divide raw bytes by 2
+            pand  mm2, mm4     // clear invalid bit 7 of each byte
+            paddb mm2, mm1     // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6      // Leave only Active Group 2 bytes to add to Avg
+            paddb mm0, mm2     // add (Raw/2) + LBCarrys to Avg for each Active
+                               //  byte
+
+            // Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry
+            psllq mm6, ShiftBpp  // shift the mm6 mask to cover the last two
+                                 // bytes
+            movq mm2, mm0        // mov updated Raws to mm2
+            psllq mm2, ShiftBpp  // shift data to position correctly
+                              // Data only needs to be shifted once here to
+                              // get the correct x-bpp offset.
+            movq mm1, mm3     // now use mm1 for getting LBCarrys
+            pand mm1, mm2     // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1      // divide raw bytes by 2
+            pand  mm2, mm4    // clear invalid bit 7 of each byte
+            paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6     // Leave only Active Group 2 bytes to add to Avg
+            add ebx, 8
+            paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
+                              // byte
+
+            // Now ready to write back to memory
+            movq [edi + ebx - 8], mm0
+            // Move updated Raw(x) to use as Raw(x-bpp) for next loop
+            cmp ebx, MMXLength
+            movq mm2, mm0     // mov updated Raw(x) to mm2
+            jb davg3lp
+         } // end _asm block
+      }
+      break;
+
+      case 6:
+      case 4:
+      case 7:
+      case 5:
+      {
+         ActiveMask.use  = 0xffffffffffffffff;  // use shift below to clear
+                                                // appropriate inactive bytes
+         ShiftBpp.use = bpp << 3;
+         ShiftRem.use = 64 - ShiftBpp.use;
+         _asm {
+            movq mm4, HBClearMask
+            // Re-init address pointers and offset
+            mov ebx, diff       // ebx ==> x = offset to alignment boundary
+            // Load ActiveMask and clear all bytes except for 1st active group
+            movq mm7, ActiveMask
+            mov edi, row         // edi ==> Avg(x)
+            psrlq mm7, ShiftRem
+            mov esi, prev_row    // esi ==> Prior(x)
+            movq mm6, mm7
+            movq mm5, LBCarryMask
+            psllq mm6, ShiftBpp  // Create mask for 2nd active group
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
+                                 // (we correct position in loop below)
+davg4lp:
+            movq mm0, [edi + ebx]
+            psrlq mm2, ShiftRem  // shift data to position correctly
+            movq mm1, [esi + ebx]
+            // Add (Prev_row/2) to Average
+            movq mm3, mm5
+            pand mm3, mm1     // get lsb for each prev_row byte
+            psrlq mm1, 1      // divide prev_row bytes by 2
+            pand  mm1, mm4    // clear invalid bit 7 of each byte
+            paddb mm0, mm1    // add (Prev_row/2) to Avg for each byte
+            // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
+            movq mm1, mm3     // now use mm1 for getting LBCarrys
+            pand mm1, mm2     // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1      // divide raw bytes by 2
+            pand  mm2, mm4    // clear invalid bit 7 of each byte
+            paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm7     // Leave only Active Group 1 bytes to add to Avg
+            paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
+                              // byte
+            // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
+            movq mm2, mm0     // mov updated Raws to mm2
+            psllq mm2, ShiftBpp // shift data to position correctly
+            add ebx, 8
+            movq mm1, mm3     // now use mm1 for getting LBCarrys
+            pand mm1, mm2     // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1      // divide raw bytes by 2
+            pand  mm2, mm4    // clear invalid bit 7 of each byte
+            paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6     // Leave only Active Group 2 bytes to add to Avg
+            paddb mm0, mm2    // add (Raw/2) + LBCarrys to Avg for each Active
+                              // byte
+            cmp ebx, MMXLength
+            // Now ready to write back to memory
+            movq [edi + ebx - 8], mm0
+            // Prep Raw(x-bpp) for next loop
+            movq mm2, mm0     // mov updated Raws to mm2
+            jb davg4lp
+         } // end _asm block
+      }
+      break;
+      case 2:
+      {
+         ActiveMask.use  = 0x000000000000ffff;
+         ShiftBpp.use = 16;   // == 2 * 8     [BUGFIX]
+         ShiftRem.use = 48;   // == 64 - 16   [BUGFIX]
+         _asm {
+            // Load ActiveMask
+            movq mm7, ActiveMask
+            // Re-init address pointers and offset
+            mov ebx, diff     // ebx ==> x = offset to alignment boundary
+            movq mm5, LBCarryMask
+            mov edi, row      // edi ==> Avg(x)
+            movq mm4, HBClearMask
+            mov esi, prev_row  // esi ==> Prior(x)
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
+                              // (we correct position in loop below)
+davg2lp:
+            movq mm0, [edi + ebx]
+            psrlq mm2, ShiftRem  // shift data to position correctly   [BUGFIX]
+            movq mm1, [esi + ebx]
+            // Add (Prev_row/2) to Average
+            movq mm3, mm5
+            pand mm3, mm1     // get lsb for each prev_row byte
+            psrlq mm1, 1      // divide prev_row bytes by 2
+            pand  mm1, mm4    // clear invalid bit 7 of each byte
+            movq mm6, mm7
+            paddb mm0, mm1    // add (Prev_row/2) to Avg for each byte
+            // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry
+            movq mm1, mm3     // now use mm1 for getting LBCarrys
+            pand mm1, mm2     // get LBCarrys for each byte where both
+                              // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1      // divide raw bytes by 2
+            pand  mm2, mm4    // clear invalid bit 7 of each byte
+            paddb mm2, mm1    // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6     // Leave only Active Group 1 bytes to add to Avg
+            paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
+            // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry
+            psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 2 & 3
+            movq mm2, mm0       // mov updated Raws to mm2
+            psllq mm2, ShiftBpp // shift data to position correctly
+            movq mm1, mm3       // now use mm1 for getting LBCarrys
+            pand mm1, mm2       // get LBCarrys for each byte where both
+                                // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1        // divide raw bytes by 2
+            pand  mm2, mm4      // clear invalid bit 7 of each byte
+            paddb mm2, mm1      // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6       // Leave only Active Group 2 bytes to add to Avg
+            paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
+
+            // Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry
+            psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 4 & 5
+            movq mm2, mm0       // mov updated Raws to mm2
+            psllq mm2, ShiftBpp // shift data to position correctly
+                                // Data only needs to be shifted once here to
+                                // get the correct x-bpp offset.
+            movq mm1, mm3       // now use mm1 for getting LBCarrys
+            pand mm1, mm2       // get LBCarrys for each byte where both
+                                // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1        // divide raw bytes by 2
+            pand  mm2, mm4      // clear invalid bit 7 of each byte
+            paddb mm2, mm1      // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6       // Leave only Active Group 2 bytes to add to Avg
+            paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
+
+            // Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry
+            psllq mm6, ShiftBpp  // shift the mm6 mask to cover bytes 6 & 7
+            movq mm2, mm0        // mov updated Raws to mm2
+            psllq mm2, ShiftBpp  // shift data to position correctly
+                                 // Data only needs to be shifted once here to
+                                 // get the correct x-bpp offset.
+            add ebx, 8
+            movq mm1, mm3    // now use mm1 for getting LBCarrys
+            pand mm1, mm2    // get LBCarrys for each byte where both
+                             // lsb's were == 1 (Only valid for active group)
+            psrlq mm2, 1     // divide raw bytes by 2
+            pand  mm2, mm4   // clear invalid bit 7 of each byte
+            paddb mm2, mm1   // add LBCarrys to (Raw(x-bpp)/2) for each byte
+            pand mm2, mm6    // Leave only Active Group 2 bytes to add to Avg
+            paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte
+
+            cmp ebx, MMXLength
+            // Now ready to write back to memory
+            movq [edi + ebx - 8], mm0
+            // Prep Raw(x-bpp) for next loop
+            movq mm2, mm0    // mov updated Raws to mm2
+            jb davg2lp
+        } // end _asm block
+      }
+      break;
+
+      case 1:                 // bpp == 1
+      {
+         _asm {
+            // Re-init address pointers and offset
+            mov ebx, diff     // ebx ==> x = offset to alignment boundary
+            mov edi, row      // edi ==> Avg(x)
+            cmp ebx, FullLength  // Test if offset at end of array
+            jnb davg1end
+            // Do Paeth decode for remaining bytes
+            mov esi, prev_row    // esi ==> Prior(x)
+            mov edx, edi
+            xor ecx, ecx         // zero ecx before using cl & cx in loop below
+            sub edx, bpp         // edx ==> Raw(x-bpp)
+davg1lp:
+            // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+            xor eax, eax
+            mov cl, [esi + ebx]  // load cl with Prior(x)
+            mov al, [edx + ebx]  // load al with Raw(x-bpp)
+            add ax, cx
+            inc ebx
+            shr ax, 1            // divide by 2
+            add al, [edi+ebx-1]  // Add Avg(x); -1 to offset inc ebx
+            cmp ebx, FullLength  // Check if at end of array
+            mov [edi+ebx-1], al  // Write back Raw(x);
+                         // mov does not affect flags; -1 to offset inc ebx
+            jb davg1lp
+davg1end:
+         } // end _asm block
+      }
+      return;
+
+      case 8:             // bpp == 8
+      {
+         _asm {
+            // Re-init address pointers and offset
+            mov ebx, diff           // ebx ==> x = offset to alignment boundary
+            movq mm5, LBCarryMask
+            mov edi, row            // edi ==> Avg(x)
+            movq mm4, HBClearMask
+            mov esi, prev_row       // esi ==> Prior(x)
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm2, [edi + ebx - 8]  // Load previous aligned 8 bytes
+                                // (NO NEED to correct position in loop below)
+davg8lp:
+            movq mm0, [edi + ebx]
+            movq mm3, mm5
+            movq mm1, [esi + ebx]
+            add ebx, 8
+            pand mm3, mm1       // get lsb for each prev_row byte
+            psrlq mm1, 1        // divide prev_row bytes by 2
+            pand mm3, mm2       // get LBCarrys for each byte where both
+                                // lsb's were == 1
+            psrlq mm2, 1        // divide raw bytes by 2
+            pand  mm1, mm4      // clear invalid bit 7 of each byte
+            paddb mm0, mm3      // add LBCarrys to Avg for each byte
+            pand  mm2, mm4      // clear invalid bit 7 of each byte
+            paddb mm0, mm1      // add (Prev_row/2) to Avg for each byte
+            paddb mm0, mm2      // add (Raw/2) to Avg for each byte
+            cmp ebx, MMXLength
+            movq [edi + ebx - 8], mm0
+            movq mm2, mm0       // reuse as Raw(x-bpp)
+            jb davg8lp
+        } // end _asm block
+      }
+      break;
+      default:                  // bpp greater than 8
+      {
+        _asm {
+            movq mm5, LBCarryMask
+            // Re-init address pointers and offset
+            mov ebx, diff       // ebx ==> x = offset to alignment boundary
+            mov edi, row        // edi ==> Avg(x)
+            movq mm4, HBClearMask
+            mov edx, edi
+            mov esi, prev_row   // esi ==> Prior(x)
+            sub edx, bpp        // edx ==> Raw(x-bpp)
+davgAlp:
+            movq mm0, [edi + ebx]
+            movq mm3, mm5
+            movq mm1, [esi + ebx]
+            pand mm3, mm1       // get lsb for each prev_row byte
+            movq mm2, [edx + ebx]
+            psrlq mm1, 1        // divide prev_row bytes by 2
+            pand mm3, mm2       // get LBCarrys for each byte where both
+                                // lsb's were == 1
+            psrlq mm2, 1        // divide raw bytes by 2
+            pand  mm1, mm4      // clear invalid bit 7 of each byte
+            paddb mm0, mm3      // add LBCarrys to Avg for each byte
+            pand  mm2, mm4      // clear invalid bit 7 of each byte
+            paddb mm0, mm1      // add (Prev_row/2) to Avg for each byte
+            add ebx, 8
+            paddb mm0, mm2      // add (Raw/2) to Avg for each byte
+            cmp ebx, MMXLength
+            movq [edi + ebx - 8], mm0
+            jb davgAlp
+        } // end _asm block
+      }
+      break;
+   }                         // end switch ( bpp )
+
+   _asm {
+         // MMX acceleration complete now do clean-up
+         // Check if any remaining bytes left to decode
+         mov ebx, MMXLength    // ebx ==> x = offset bytes remaining after MMX
+         mov edi, row          // edi ==> Avg(x)
+         cmp ebx, FullLength   // Test if offset at end of array
+         jnb davgend
+         // Do Paeth decode for remaining bytes
+         mov esi, prev_row     // esi ==> Prior(x)
+         mov edx, edi
+         xor ecx, ecx          // zero ecx before using cl & cx in loop below
+         sub edx, bpp          // edx ==> Raw(x-bpp)
+davglp2:
+         // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2)
+         xor eax, eax
+         mov cl, [esi + ebx]   // load cl with Prior(x)
+         mov al, [edx + ebx]   // load al with Raw(x-bpp)
+         add ax, cx
+         inc ebx
+         shr ax, 1              // divide by 2
+         add al, [edi+ebx-1]    // Add Avg(x); -1 to offset inc ebx
+         cmp ebx, FullLength    // Check if at end of array
+         mov [edi+ebx-1], al    // Write back Raw(x);
+                          // mov does not affect flags; -1 to offset inc ebx
+         jb davglp2
+davgend:
+         emms             // End MMX instructions; prep for possible FP instrs.
+   } // end _asm block
+}
+
+// Optimized code for PNG Paeth filter decoder
+void /* PRIVATE */
+png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row,
+                              png_bytep prev_row)
+{
+   png_uint_32 FullLength;
+   png_uint_32 MMXLength;
+   //png_uint_32 len;
+   int bpp;
+   int diff;
+   //int ptemp;
+   int patemp, pbtemp, pctemp;
+
+   bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
+   FullLength  = row_info->rowbytes; // # of bytes to filter
+   _asm
+   {
+         xor ebx, ebx        // ebx ==> x offset
+         mov edi, row
+         xor edx, edx        // edx ==> x-bpp offset
+         mov esi, prev_row
+         xor eax, eax
+
+         // Compute the Raw value for the first bpp bytes
+         // Note: the formula works out to be always
+         //   Paeth(x) = Raw(x) + Prior(x)      where x < bpp
+dpthrlp:
+         mov al, [edi + ebx]
+         add al, [esi + ebx]
+         inc ebx
+         cmp ebx, bpp
+         mov [edi + ebx - 1], al
+         jb dpthrlp
+         // get # of bytes to alignment
+         mov diff, edi         // take start of row
+         add diff, ebx         // add bpp
+         xor ecx, ecx
+         add diff, 0xf         // add 7 + 8 to incr past alignment boundary
+         and diff, 0xfffffff8  // mask to alignment boundary
+         sub diff, edi         // subtract from start ==> value ebx at alignment
+         jz dpthgo
+         // fix alignment
+dpthlp1:
+         xor eax, eax
+         // pav = p - a = (a + b - c) - a = b - c
+         mov al, [esi + ebx]   // load Prior(x) into al
+         mov cl, [esi + edx]   // load Prior(x-bpp) into cl
+         sub eax, ecx          // subtract Prior(x-bpp)
+         mov patemp, eax       // Save pav for later use
+         xor eax, eax
+         // pbv = p - b = (a + b - c) - b = a - c
+         mov al, [edi + edx]   // load Raw(x-bpp) into al
+         sub eax, ecx          // subtract Prior(x-bpp)
+         mov ecx, eax
+         // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+         add eax, patemp       // pcv = pav + pbv
+         // pc = abs(pcv)
+         test eax, 0x80000000
+         jz dpthpca
+         neg eax               // reverse sign of neg values
+dpthpca:
+         mov pctemp, eax       // save pc for later use
+         // pb = abs(pbv)
+         test ecx, 0x80000000
+         jz dpthpba
+         neg ecx               // reverse sign of neg values
+dpthpba:
+         mov pbtemp, ecx       // save pb for later use
+         // pa = abs(pav)
+         mov eax, patemp
+         test eax, 0x80000000
+         jz dpthpaa
+         neg eax               // reverse sign of neg values
+dpthpaa:
+         mov patemp, eax       // save pa for later use
+         // test if pa <= pb
+         cmp eax, ecx
+         jna dpthabb
+         // pa > pb; now test if pb <= pc
+         cmp ecx, pctemp
+         jna dpthbbc
+         // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+         mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+         jmp dpthpaeth
+dpthbbc:
+         // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+         mov cl, [esi + ebx]   // load Prior(x) into cl
+         jmp dpthpaeth
+dpthabb:
+         // pa <= pb; now test if pa <= pc
+         cmp eax, pctemp
+         jna dpthabc
+         // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+         mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+         jmp dpthpaeth
+dpthabc:
+         // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+         mov cl, [edi + edx]  // load Raw(x-bpp) into cl
+dpthpaeth:
+         inc ebx
+         inc edx
+         // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+         add [edi + ebx - 1], cl
+         cmp ebx, diff
+         jb dpthlp1
+dpthgo:
+         mov ecx, FullLength
+         mov eax, ecx
+         sub eax, ebx          // subtract alignment fix
+         and eax, 0x00000007   // calc bytes over mult of 8
+         sub ecx, eax          // drop over bytes from original length
+         mov MMXLength, ecx
+   } // end _asm block
+   // Now do the math for the rest of the row
+   switch ( bpp )
+   {
+      case 3:
+      {
+         ActiveMask.use = 0x0000000000ffffff;
+         ActiveMaskEnd.use = 0xffff000000000000;
+         ShiftBpp.use = 24;    // == bpp(3) * 8
+         ShiftRem.use = 40;    // == 64 - 24
+         _asm
+         {
+            mov ebx, diff
+            mov edi, row
+            mov esi, prev_row
+            pxor mm0, mm0
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]
+dpth3lp:
+            psrlq mm1, ShiftRem     // shift last 3 bytes to 1st 3 bytes
+            movq mm2, [esi + ebx]   // load b=Prior(x)
+            punpcklbw mm1, mm0      // Unpack High bytes of a
+            movq mm3, [esi+ebx-8]   // Prep c=Prior(x-bpp) bytes
+            punpcklbw mm2, mm0      // Unpack High bytes of b
+            psrlq mm3, ShiftRem     // shift last 3 bytes to 1st 3 bytes
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            punpcklbw mm3, mm0      // Unpack High bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4    // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4       // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5       // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
+            pand mm0, mm6       // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5    // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            paddw mm7, mm3
+            pxor mm0, mm0
+            packuswb mm7, mm1
+            movq mm3, [esi + ebx]   // load c=Prior(x-bpp)
+            pand mm7, ActiveMask
+            movq mm2, mm3           // load b=Prior(x) step 1
+            paddb mm7, [edi + ebx]  // add Paeth predictor with Raw(x)
+            punpcklbw mm3, mm0      // Unpack High bytes of c
+            movq [edi + ebx], mm7   // write back updated value
+            movq mm1, mm7           // Now mm1 will be used as Raw(x-bpp)
+            // Now do Paeth for 2nd set of bytes (3-5)
+            psrlq mm2, ShiftBpp     // load b=Prior(x) step 2
+            punpcklbw mm1, mm0      // Unpack High bytes of a
+            pxor mm7, mm7
+            punpcklbw mm2, mm0      // Unpack High bytes of b
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            psubw mm5, mm3
+            psubw mm4, mm3
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) =
+            //       pav + pbv = pbv + pav
+            movq mm6, mm5
+            paddw mm6, mm4
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm5       // Create mask pbv bytes < 0
+            pcmpgtw mm7, mm4       // Create mask pav bytes < 0
+            pand mm0, mm5          // Only pbv bytes < 0 in mm0
+            pand mm7, mm4          // Only pav bytes < 0 in mm7
+            psubw mm5, mm0
+            psubw mm4, mm7
+            psubw mm5, mm0
+            psubw mm4, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            movq mm2, [esi + ebx]  // load b=Prior(x)
+            pand mm3, mm7
+            pandn mm7, mm0
+            pxor mm1, mm1
+            paddw mm7, mm3
+            pxor mm0, mm0
+            packuswb mm7, mm1
+            movq mm3, mm2           // load c=Prior(x-bpp) step 1
+            pand mm7, ActiveMask
+            punpckhbw mm2, mm0      // Unpack High bytes of b
+            psllq mm7, ShiftBpp     // Shift bytes to 2nd group of 3 bytes
+             // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            paddb mm7, [edi + ebx]  // add Paeth predictor with Raw(x)
+            psllq mm3, ShiftBpp     // load c=Prior(x-bpp) step 2
+            movq [edi + ebx], mm7   // write back updated value
+            movq mm1, mm7
+            punpckhbw mm3, mm0      // Unpack High bytes of c
+            psllq mm1, ShiftBpp     // Shift bytes
+                                    // Now mm1 will be used as Raw(x-bpp)
+            // Now do Paeth for 3rd, and final, set of bytes (6-7)
+            pxor mm7, mm7
+            punpckhbw mm1, mm0      // Unpack High bytes of a
+            psubw mm4, mm3
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            pxor mm0, mm0
+            paddw mm6, mm5
+
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4    // Create mask pav bytes < 0
+            pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
+            pand mm0, mm4       // Only pav bytes < 0 in mm7
+            pand mm7, mm5       // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
+            pand mm0, mm6       // Only pav bytes < 0 in mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5    // pa > pb?
+            movq mm0, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            pandn mm0, mm1
+            pandn mm7, mm4
+            paddw mm0, mm2
+            paddw mm7, mm5
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6    // pab > pc?
+            pand mm3, mm7
+            pandn mm7, mm0
+            paddw mm7, mm3
+            pxor mm1, mm1
+            packuswb mm1, mm7
+            // Step ebx to next set of 8 bytes and repeat loop til done
+            add ebx, 8
+            pand mm1, ActiveMaskEnd
+            paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x)
+
+            cmp ebx, MMXLength
+            pxor mm0, mm0              // pxor does not affect flags
+            movq [edi + ebx - 8], mm1  // write back updated value
+                                 // mm1 will be used as Raw(x-bpp) next loop
+                           // mm3 ready to be used as Prior(x-bpp) next loop
+            jb dpth3lp
+         } // end _asm block
+      }
+      break;
+
+      case 6:
+      case 7:
+      case 5:
+      {
+         ActiveMask.use  = 0x00000000ffffffff;
+         ActiveMask2.use = 0xffffffff00000000;
+         ShiftBpp.use = bpp << 3;    // == bpp * 8
+         ShiftRem.use = 64 - ShiftBpp.use;
+         _asm
+         {
+            mov ebx, diff
+            mov edi, row
+            mov esi, prev_row
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]
+            pxor mm0, mm0
+dpth6lp:
+            // Must shift to position Raw(x-bpp) data
+            psrlq mm1, ShiftRem
+            // Do first set of 4 bytes
+            movq mm3, [esi+ebx-8]      // read c=Prior(x-bpp) bytes
+            punpcklbw mm1, mm0      // Unpack Low bytes of a
+            movq mm2, [esi + ebx]   // load b=Prior(x)
+            punpcklbw mm2, mm0      // Unpack Low bytes of b
+            // Must shift to position Prior(x-bpp) data
+            psrlq mm3, ShiftRem
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            punpcklbw mm3, mm0      // Unpack Low bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4    // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4       // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5    // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5       // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6    // Create mask pcv bytes < 0
+            pand mm0, mm6       // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5    // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6    // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            paddw mm7, mm3
+            pxor mm0, mm0
+            packuswb mm7, mm1
+            movq mm3, [esi + ebx - 8]  // load c=Prior(x-bpp)
+            pand mm7, ActiveMask
+            psrlq mm3, ShiftRem
+            movq mm2, [esi + ebx]      // load b=Prior(x) step 1
+            paddb mm7, [edi + ebx]     // add Paeth predictor with Raw(x)
+            movq mm6, mm2
+            movq [edi + ebx], mm7      // write back updated value
+            movq mm1, [edi+ebx-8]
+            psllq mm6, ShiftBpp
+            movq mm5, mm7
+            psrlq mm1, ShiftRem
+            por mm3, mm6
+            psllq mm5, ShiftBpp
+            punpckhbw mm3, mm0         // Unpack High bytes of c
+            por mm1, mm5
+            // Do second set of 4 bytes
+            punpckhbw mm2, mm0         // Unpack High bytes of b
+            punpckhbw mm1, mm0         // Unpack High bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4       // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4          // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5          // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6           // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            pxor mm1, mm1
+            paddw mm7, mm3
+            pxor mm0, mm0
+            // Step ex to next set of 8 bytes and repeat loop til done
+            add ebx, 8
+            packuswb mm1, mm7
+            paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
+            cmp ebx, MMXLength
+            movq [edi + ebx - 8], mm1      // write back updated value
+                                // mm1 will be used as Raw(x-bpp) next loop
+            jb dpth6lp
+         } // end _asm block
+      }
+      break;
+
+      case 4:
+      {
+         ActiveMask.use  = 0x00000000ffffffff;
+         _asm {
+            mov ebx, diff
+            mov edi, row
+            mov esi, prev_row
+            pxor mm0, mm0
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]    // Only time should need to read
+                                     //  a=Raw(x-bpp) bytes
+dpth4lp:
+            // Do first set of 4 bytes
+            movq mm3, [esi+ebx-8]    // read c=Prior(x-bpp) bytes
+            punpckhbw mm1, mm0       // Unpack Low bytes of a
+            movq mm2, [esi + ebx]    // load b=Prior(x)
+            punpcklbw mm2, mm0       // Unpack High bytes of b
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            punpckhbw mm3, mm0       // Unpack High bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4       // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4          // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5          // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            paddw mm7, mm3
+            pxor mm0, mm0
+            packuswb mm7, mm1
+            movq mm3, [esi + ebx]      // load c=Prior(x-bpp)
+            pand mm7, ActiveMask
+            movq mm2, mm3              // load b=Prior(x) step 1
+            paddb mm7, [edi + ebx]     // add Paeth predictor with Raw(x)
+            punpcklbw mm3, mm0         // Unpack High bytes of c
+            movq [edi + ebx], mm7      // write back updated value
+            movq mm1, mm7              // Now mm1 will be used as Raw(x-bpp)
+            // Do second set of 4 bytes
+            punpckhbw mm2, mm0         // Unpack Low bytes of b
+            punpcklbw mm1, mm0         // Unpack Low bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4       // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4          // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5          // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            pxor mm1, mm1
+            paddw mm7, mm3
+            pxor mm0, mm0
+            // Step ex to next set of 8 bytes and repeat loop til done
+            add ebx, 8
+            packuswb mm1, mm7
+            paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
+            cmp ebx, MMXLength
+            movq [edi + ebx - 8], mm1      // write back updated value
+                                // mm1 will be used as Raw(x-bpp) next loop
+            jb dpth4lp
+         } // end _asm block
+      }
+      break;
+      case 8:                          // bpp == 8
+      {
+         ActiveMask.use  = 0x00000000ffffffff;
+         _asm {
+            mov ebx, diff
+            mov edi, row
+            mov esi, prev_row
+            pxor mm0, mm0
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]      // Only time should need to read
+                                       //  a=Raw(x-bpp) bytes
+dpth8lp:
+            // Do first set of 4 bytes
+            movq mm3, [esi+ebx-8]      // read c=Prior(x-bpp) bytes
+            punpcklbw mm1, mm0         // Unpack Low bytes of a
+            movq mm2, [esi + ebx]      // load b=Prior(x)
+            punpcklbw mm2, mm0         // Unpack Low bytes of b
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            punpcklbw mm3, mm0         // Unpack Low bytes of c
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4       // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4          // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5          // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            paddw mm7, mm3
+            pxor mm0, mm0
+            packuswb mm7, mm1
+            movq mm3, [esi+ebx-8]    // read c=Prior(x-bpp) bytes
+            pand mm7, ActiveMask
+            movq mm2, [esi + ebx]    // load b=Prior(x)
+            paddb mm7, [edi + ebx]   // add Paeth predictor with Raw(x)
+            punpckhbw mm3, mm0       // Unpack High bytes of c
+            movq [edi + ebx], mm7    // write back updated value
+            movq mm1, [edi+ebx-8]    // read a=Raw(x-bpp) bytes
+
+            // Do second set of 4 bytes
+            punpckhbw mm2, mm0       // Unpack High bytes of b
+            punpckhbw mm1, mm0       // Unpack High bytes of a
+            // pav = p - a = (a + b - c) - a = b - c
+            movq mm4, mm2
+            // pbv = p - b = (a + b - c) - b = a - c
+            movq mm5, mm1
+            psubw mm4, mm3
+            pxor mm7, mm7
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            movq mm6, mm4
+            psubw mm5, mm3
+            // pa = abs(p-a) = abs(pav)
+            // pb = abs(p-b) = abs(pbv)
+            // pc = abs(p-c) = abs(pcv)
+            pcmpgtw mm0, mm4       // Create mask pav bytes < 0
+            paddw mm6, mm5
+            pand mm0, mm4          // Only pav bytes < 0 in mm7
+            pcmpgtw mm7, mm5       // Create mask pbv bytes < 0
+            psubw mm4, mm0
+            pand mm7, mm5          // Only pbv bytes < 0 in mm0
+            psubw mm4, mm0
+            psubw mm5, mm7
+            pxor mm0, mm0
+            pcmpgtw mm0, mm6       // Create mask pcv bytes < 0
+            pand mm0, mm6          // Only pav bytes < 0 in mm7
+            psubw mm5, mm7
+            psubw mm6, mm0
+            //  test pa <= pb
+            movq mm7, mm4
+            psubw mm6, mm0
+            pcmpgtw mm7, mm5       // pa > pb?
+            movq mm0, mm7
+            // use mm7 mask to merge pa & pb
+            pand mm5, mm7
+            // use mm0 mask copy to merge a & b
+            pand mm2, mm0
+            pandn mm7, mm4
+            pandn mm0, mm1
+            paddw mm7, mm5
+            paddw mm0, mm2
+            //  test  ((pa <= pb)? pa:pb) <= pc
+            pcmpgtw mm7, mm6       // pab > pc?
+            pxor mm1, mm1
+            pand mm3, mm7
+            pandn mm7, mm0
+            pxor mm1, mm1
+            paddw mm7, mm3
+            pxor mm0, mm0
+            // Step ex to next set of 8 bytes and repeat loop til done
+            add ebx, 8
+            packuswb mm1, mm7
+            paddb mm1, [edi + ebx - 8]     // add Paeth predictor with Raw(x)
+            cmp ebx, MMXLength
+            movq [edi + ebx - 8], mm1      // write back updated value
+                            // mm1 will be used as Raw(x-bpp) next loop
+            jb dpth8lp
+         } // end _asm block
+      }
+      break;
+
+      case 1:                // bpp = 1
+      case 2:                // bpp = 2
+      default:               // bpp > 8
+      {
+         _asm {
+            mov ebx, diff
+            cmp ebx, FullLength
+            jnb dpthdend
+            mov edi, row
+            mov esi, prev_row
+            // Do Paeth decode for remaining bytes
+            mov edx, ebx
+            xor ecx, ecx        // zero ecx before using cl & cx in loop below
+            sub edx, bpp        // Set edx = ebx - bpp
+dpthdlp:
+            xor eax, eax
+            // pav = p - a = (a + b - c) - a = b - c
+            mov al, [esi + ebx]        // load Prior(x) into al
+            mov cl, [esi + edx]        // load Prior(x-bpp) into cl
+            sub eax, ecx                 // subtract Prior(x-bpp)
+            mov patemp, eax                 // Save pav for later use
+            xor eax, eax
+            // pbv = p - b = (a + b - c) - b = a - c
+            mov al, [edi + edx]        // load Raw(x-bpp) into al
+            sub eax, ecx                 // subtract Prior(x-bpp)
+            mov ecx, eax
+            // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+            add eax, patemp                 // pcv = pav + pbv
+            // pc = abs(pcv)
+            test eax, 0x80000000
+            jz dpthdpca
+            neg eax                     // reverse sign of neg values
+dpthdpca:
+            mov pctemp, eax             // save pc for later use
+            // pb = abs(pbv)
+            test ecx, 0x80000000
+            jz dpthdpba
+            neg ecx                     // reverse sign of neg values
+dpthdpba:
+            mov pbtemp, ecx             // save pb for later use
+            // pa = abs(pav)
+            mov eax, patemp
+            test eax, 0x80000000
+            jz dpthdpaa
+            neg eax                     // reverse sign of neg values
+dpthdpaa:
+            mov patemp, eax             // save pa for later use
+            // test if pa <= pb
+            cmp eax, ecx
+            jna dpthdabb
+            // pa > pb; now test if pb <= pc
+            cmp ecx, pctemp
+            jna dpthdbbc
+            // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+            mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+            jmp dpthdpaeth
+dpthdbbc:
+            // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+            mov cl, [esi + ebx]        // load Prior(x) into cl
+            jmp dpthdpaeth
+dpthdabb:
+            // pa <= pb; now test if pa <= pc
+            cmp eax, pctemp
+            jna dpthdabc
+            // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+            mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+            jmp dpthdpaeth
+dpthdabc:
+            // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+            mov cl, [edi + edx]  // load Raw(x-bpp) into cl
+dpthdpaeth:
+            inc ebx
+            inc edx
+            // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+            add [edi + ebx - 1], cl
+            cmp ebx, FullLength
+            jb dpthdlp
+dpthdend:
+         } // end _asm block
+      }
+      return;                   // No need to go further with this one
+   }                         // end switch ( bpp )
+   _asm
+   {
+         // MMX acceleration complete now do clean-up
+         // Check if any remaining bytes left to decode
+         mov ebx, MMXLength
+         cmp ebx, FullLength
+         jnb dpthend
+         mov edi, row
+         mov esi, prev_row
+         // Do Paeth decode for remaining bytes
+         mov edx, ebx
+         xor ecx, ecx         // zero ecx before using cl & cx in loop below
+         sub edx, bpp         // Set edx = ebx - bpp
+dpthlp2:
+         xor eax, eax
+         // pav = p - a = (a + b - c) - a = b - c
+         mov al, [esi + ebx]  // load Prior(x) into al
+         mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+         sub eax, ecx         // subtract Prior(x-bpp)
+         mov patemp, eax      // Save pav for later use
+         xor eax, eax
+         // pbv = p - b = (a + b - c) - b = a - c
+         mov al, [edi + edx]  // load Raw(x-bpp) into al
+         sub eax, ecx         // subtract Prior(x-bpp)
+         mov ecx, eax
+         // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv
+         add eax, patemp      // pcv = pav + pbv
+         // pc = abs(pcv)
+         test eax, 0x80000000
+         jz dpthpca2
+         neg eax              // reverse sign of neg values
+dpthpca2:
+         mov pctemp, eax      // save pc for later use
+         // pb = abs(pbv)
+         test ecx, 0x80000000
+         jz dpthpba2
+         neg ecx              // reverse sign of neg values
+dpthpba2:
+         mov pbtemp, ecx      // save pb for later use
+         // pa = abs(pav)
+         mov eax, patemp
+         test eax, 0x80000000
+         jz dpthpaa2
+         neg eax              // reverse sign of neg values
+dpthpaa2:
+         mov patemp, eax      // save pa for later use
+         // test if pa <= pb
+         cmp eax, ecx
+         jna dpthabb2
+         // pa > pb; now test if pb <= pc
+         cmp ecx, pctemp
+         jna dpthbbc2
+         // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+         mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+         jmp dpthpaeth2
+dpthbbc2:
+         // pb <= pc; Raw(x) = Paeth(x) + Prior(x)
+         mov cl, [esi + ebx]        // load Prior(x) into cl
+         jmp dpthpaeth2
+dpthabb2:
+         // pa <= pb; now test if pa <= pc
+         cmp eax, pctemp
+         jna dpthabc2
+         // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp)
+         mov cl, [esi + edx]  // load Prior(x-bpp) into cl
+         jmp dpthpaeth2
+dpthabc2:
+         // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp)
+         mov cl, [edi + edx]  // load Raw(x-bpp) into cl
+dpthpaeth2:
+         inc ebx
+         inc edx
+         // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256
+         add [edi + ebx - 1], cl
+         cmp ebx, FullLength
+         jb dpthlp2
+dpthend:
+         emms             // End MMX instructions; prep for possible FP instrs.
+   } // end _asm block
+}
+
+// Optimized code for PNG Sub filter decoder
+void /* PRIVATE */
+png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row)
+{
+   //int test;
+   int bpp;
+   png_uint_32 FullLength;
+   png_uint_32 MMXLength;
+   int diff;
+
+   bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel
+   FullLength  = row_info->rowbytes - bpp; // # of bytes to filter
+   _asm {
+        mov edi, row
+        mov esi, edi               // lp = row
+        add edi, bpp               // rp = row + bpp
+        xor eax, eax
+        // get # of bytes to alignment
+        mov diff, edi               // take start of row
+        add diff, 0xf               // add 7 + 8 to incr past
+                                        // alignment boundary
+        xor ebx, ebx
+        and diff, 0xfffffff8        // mask to alignment boundary
+        sub diff, edi               // subtract from start ==> value
+                                        //  ebx at alignment
+        jz dsubgo
+        // fix alignment
+dsublp1:
+        mov al, [esi+ebx]
+        add [edi+ebx], al
+        inc ebx
+        cmp ebx, diff
+        jb dsublp1
+dsubgo:
+        mov ecx, FullLength
+        mov edx, ecx
+        sub edx, ebx                  // subtract alignment fix
+        and edx, 0x00000007           // calc bytes over mult of 8
+        sub ecx, edx                  // drop over bytes from length
+        mov MMXLength, ecx
+   } // end _asm block
+
+   // Now do the math for the rest of the row
+   switch ( bpp )
+   {
+        case 3:
+        {
+         ActiveMask.use  = 0x0000ffffff000000;
+         ShiftBpp.use = 24;       // == 3 * 8
+         ShiftRem.use  = 40;      // == 64 - 24
+         _asm {
+            mov edi, row
+            movq mm7, ActiveMask  // Load ActiveMask for 2nd active byte group
+            mov esi, edi              // lp = row
+            add edi, bpp          // rp = row + bpp
+            movq mm6, mm7
+            mov ebx, diff
+            psllq mm6, ShiftBpp   // Move mask in mm6 to cover 3rd active
+                                  // byte group
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]
+dsub3lp:
+            psrlq mm1, ShiftRem   // Shift data for adding 1st bpp bytes
+                          // no need for mask; shift clears inactive bytes
+            // Add 1st active group
+            movq mm0, [edi+ebx]
+            paddb mm0, mm1
+            // Add 2nd active group
+            movq mm1, mm0         // mov updated Raws to mm1
+            psllq mm1, ShiftBpp   // shift data to position correctly
+            pand mm1, mm7         // mask to use only 2nd active group
+            paddb mm0, mm1
+            // Add 3rd active group
+            movq mm1, mm0         // mov updated Raws to mm1
+            psllq mm1, ShiftBpp   // shift data to position correctly
+            pand mm1, mm6         // mask to use only 3rd active group
+            add ebx, 8
+            paddb mm0, mm1
+            cmp ebx, MMXLength
+            movq [edi+ebx-8], mm0     // Write updated Raws back to array
+            // Prep for doing 1st add at top of loop
+            movq mm1, mm0
+            jb dsub3lp
+         } // end _asm block
+      }
+      break;
+
+      case 1:
+      {
+         // Placed here just in case this is a duplicate of the
+         // non-MMX code for the SUB filter in png_read_filter_row below
+         //
+         //         png_bytep rp;
+         //         png_bytep lp;
+         //         png_uint_32 i;
+         //         bpp = (row_info->pixel_depth + 7) >> 3;
+         //         for (i = (png_uint_32)bpp, rp = row + bpp, lp = row;
+         //            i < row_info->rowbytes; i++, rp++, lp++)
+         //      {
+         //            *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff);
+         //      }
+         _asm {
+            mov ebx, diff
+            mov edi, row
+            cmp ebx, FullLength
+            jnb dsub1end
+            mov esi, edi          // lp = row
+            xor eax, eax
+            add edi, bpp      // rp = row + bpp
+dsub1lp:
+            mov al, [esi+ebx]
+            add [edi+ebx], al
+            inc ebx
+            cmp ebx, FullLength
+            jb dsub1lp
+dsub1end:
+         } // end _asm block
+      }
+      return;
+
+      case 6:
+      case 7:
+      case 4:
+      case 5:
+      {
+         ShiftBpp.use = bpp << 3;
+         ShiftRem.use = 64 - ShiftBpp.use;
+         _asm {
+            mov edi, row
+            mov ebx, diff
+            mov esi, edi               // lp = row
+            add edi, bpp           // rp = row + bpp
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]
+dsub4lp:
+            psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes
+                          // no need for mask; shift clears inactive bytes
+            movq mm0, [edi+ebx]
+            paddb mm0, mm1
+            // Add 2nd active group
+            movq mm1, mm0          // mov updated Raws to mm1
+            psllq mm1, ShiftBpp    // shift data to position correctly
+                                   // there is no need for any mask
+                                   // since shift clears inactive bits/bytes
+            add ebx, 8
+            paddb mm0, mm1
+            cmp ebx, MMXLength
+            movq [edi+ebx-8], mm0
+            movq mm1, mm0          // Prep for doing 1st add at top of loop
+            jb dsub4lp
+         } // end _asm block
+      }
+      break;
+
+      case 2:
+      {
+         ActiveMask.use  = 0x00000000ffff0000;
+         ShiftBpp.use = 16;       // == 2 * 8
+         ShiftRem.use = 48;       // == 64 - 16
+         _asm {
+            movq mm7, ActiveMask  // Load ActiveMask for 2nd active byte group
+            mov ebx, diff
+            movq mm6, mm7
+            mov edi, row
+            psllq mm6, ShiftBpp     // Move mask in mm6 to cover 3rd active
+                                    //  byte group
+            mov esi, edi            // lp = row
+            movq mm5, mm6
+            add edi, bpp            // rp = row + bpp
+            psllq mm5, ShiftBpp     // Move mask in mm5 to cover 4th active
+                                    //  byte group
+            // PRIME the pump (load the first Raw(x-bpp) data set
+            movq mm1, [edi+ebx-8]
+dsub2lp:
+            // Add 1st active group
+            psrlq mm1, ShiftRem     // Shift data for adding 1st bpp bytes
+                                    // no need for mask; shift clears inactive
+                                    //  bytes
+            movq mm0, [edi+ebx]
+            paddb mm0, mm1
+            // Add 2nd active group
+            movq mm1, mm0           // mov updated Raws to mm1
+            psllq mm1, ShiftBpp     // shift data to position correctly
+            pand mm1, mm7           // mask to use only 2nd active group
+            paddb mm0, mm1
+            // Add 3rd active group
+            movq mm1, mm0           // mov updated Raws to mm1
+            psllq mm1, ShiftBpp     // shift data to position correctly
+            pand mm1, mm6           // mask to use only 3rd active group
+            paddb mm0, mm1
+            // Add 4th active group
+            movq mm1, mm0           // mov updated Raws to mm1
+            psllq mm1, ShiftBpp     // shift data to position correctly
+            pand mm1, mm5           // mask to use only 4th active group
+            add ebx, 8
+            paddb mm0, mm1
+            cmp ebx, MMXLength
+            movq [edi+ebx-8], mm0   // Write updated Raws back to array
+            movq mm1, mm0           // Prep for doing 1st add at top of loop
+            jb dsub2lp
+         } // end _asm block
+      }
+      break;
+      case 8:
+      {
+         _asm {
+            mov edi, row
+            mov ebx, diff
+            mov esi, edi            // lp = row
+            add edi, bpp            // rp = row + bpp
+            mov ecx, MMXLength
+            movq mm7, [edi+ebx-8]   // PRIME the pump (load the first
+                                    // Raw(x-bpp) data set
+            and ecx, 0x0000003f     // calc bytes over mult of 64
+dsub8lp:
+            movq mm0, [edi+ebx]     // Load Sub(x) for 1st 8 bytes
+            paddb mm0, mm7
+            movq mm1, [edi+ebx+8]   // Load Sub(x) for 2nd 8 bytes
+            movq [edi+ebx], mm0    // Write Raw(x) for 1st 8 bytes
+                                   // Now mm0 will be used as Raw(x-bpp) for
+                                   // the 2nd group of 8 bytes.  This will be
+                                   // repeated for each group of 8 bytes with
+                                   // the 8th group being used as the Raw(x-bpp)
+                                   // for the 1st group of the next loop.
+            paddb mm1, mm0
+            movq mm2, [edi+ebx+16]  // Load Sub(x) for 3rd 8 bytes
+            movq [edi+ebx+8], mm1   // Write Raw(x) for 2nd 8 bytes
+            paddb mm2, mm1
+            movq mm3, [edi+ebx+24]  // Load Sub(x) for 4th 8 bytes
+            movq [edi+ebx+16], mm2  // Write Raw(x) for 3rd 8 bytes
+            paddb mm3, mm2
+            movq mm4, [edi+ebx+32]  // Load Sub(x) for 5th 8 bytes
+            movq [edi+ebx+24], mm3  // Write Raw(x) for 4th 8 bytes
+            paddb mm4, mm3
+            movq mm5, [edi+ebx+40]  // Load Sub(x) for 6th 8 bytes
+            movq [edi+ebx+32], mm4  // Write Raw(x) for 5th 8 bytes
+            paddb mm5, mm4
+            movq mm6, [edi+ebx+48]  // Load Sub(x) for 7th 8 bytes
+            movq [edi+ebx+40], mm5  // Write Raw(x) for 6th 8 bytes
+            paddb mm6, mm5
+            movq mm7, [edi+ebx+56]  // Load Sub(x) for 8th 8 bytes
+            movq [edi+ebx+48], mm6  // Write Raw(x) for 7th 8 bytes
+            add ebx, 64
+            paddb mm7, mm6
+            cmp ebx, ecx
+            movq [edi+ebx-8], mm7   // Write Raw(x) for 8th 8 bytes
+            jb dsub8lp
+            cmp ebx, MMXLength
+            jnb dsub8lt8
+dsub8lpA:
+            movq mm0, [edi+ebx]
+            add ebx, 8
+            paddb mm0, mm7
+            cmp ebx, MMXLength
+            movq [edi+ebx-8], mm0   // use -8 to offset early add to ebx
+            movq mm7, mm0           // Move calculated Raw(x) data to mm1 to
+                                    // be the new Raw(x-bpp) for the next loop
+            jb dsub8lpA
+dsub8lt8:
+         } // end _asm block
+      }
+      break;
+
+      default:                // bpp greater than 8 bytes
+      {
+         _asm {
+            mov ebx, diff
+            mov edi, row
+            mov esi, edi           // lp = row
+            add edi, bpp           // rp = row + bpp
+dsubAlp:
+            movq mm0, [edi+ebx]
+            movq mm1, [esi+ebx]
+            add ebx, 8
+            paddb mm0, mm1
+            cmp ebx, MMXLength
+            movq [edi+ebx-8], mm0  // mov does not affect flags; -8 to offset
+                                   //  add ebx
+            jb dsubAlp
+         } // end _asm block
+      }
+      break;
+
+   } // end switch ( bpp )
+
+   _asm {
+        mov ebx, MMXLength
+        mov edi, row
+        cmp ebx, FullLength
+        jnb dsubend
+        mov esi, edi               // lp = row
+        xor eax, eax
+        add edi, bpp               // rp = row + bpp
+dsublp2:
+        mov al, [esi+ebx]
+        add [edi+ebx], al
+        inc ebx
+        cmp ebx, FullLength
+        jb dsublp2
+dsubend:
+        emms             // End MMX instructions; prep for possible FP instrs.
+   } // end _asm block
+}
+
+// Optimized code for PNG Up filter decoder
+void /* PRIVATE */
+png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row,
+   png_bytep prev_row)
+{
+   png_uint_32 len;
+   len  = row_info->rowbytes;       // # of bytes to filter
+   _asm {
+      mov edi, row
+      // get # of bytes to alignment
+      mov ecx, edi
+      xor ebx, ebx
+      add ecx, 0x7
+      xor eax, eax
+      and ecx, 0xfffffff8
+      mov esi, prev_row
+      sub ecx, edi
+      jz dupgo
+      // fix alignment
+duplp1:
+      mov al, [edi+ebx]
+      add al, [esi+ebx]
+      inc ebx
+      cmp ebx, ecx
+      mov [edi + ebx-1], al  // mov does not affect flags; -1 to offset inc ebx
+      jb duplp1
+dupgo:
+      mov ecx, len
+      mov edx, ecx
+      sub edx, ebx                  // subtract alignment fix
+      and edx, 0x0000003f           // calc bytes over mult of 64
+      sub ecx, edx                  // drop over bytes from length
+      // Unrolled loop - use all MMX registers and interleave to reduce
+      // number of branch instructions (loops) and reduce partial stalls
+duploop:
+      movq mm1, [esi+ebx]
+      movq mm0, [edi+ebx]
+      movq mm3, [esi+ebx+8]
+      paddb mm0, mm1
+      movq mm2, [edi+ebx+8]
+      movq [edi+ebx], mm0
+      paddb mm2, mm3
+      movq mm5, [esi+ebx+16]
+      movq [edi+ebx+8], mm2
+      movq mm4, [edi+ebx+16]
+      movq mm7, [esi+ebx+24]
+      paddb mm4, mm5
+      movq mm6, [edi+ebx+24]
+      movq [edi+ebx+16], mm4
+      paddb mm6, mm7
+      movq mm1, [esi+ebx+32]
+      movq [edi+ebx+24], mm6
+      movq mm0, [edi+ebx+32]
+      movq mm3, [esi+ebx+40]
+      paddb mm0, mm1
+      movq mm2, [edi+ebx+40]
+      movq [edi+ebx+32], mm0
+      paddb mm2, mm3
+      movq mm5, [esi+ebx+48]
+      movq [edi+ebx+40], mm2
+      movq mm4, [edi+ebx+48]
+      movq mm7, [esi+ebx+56]
+      paddb mm4, mm5
+      movq mm6, [edi+ebx+56]
+      movq [edi+ebx+48], mm4
+      add ebx, 64
+      paddb mm6, mm7
+      cmp ebx, ecx
+      movq [edi+ebx-8], mm6 // (+56)movq does not affect flags;
+                                     // -8 to offset add ebx
+      jb duploop
+
+      cmp edx, 0                     // Test for bytes over mult of 64
+      jz dupend
+
+
+      // 2 lines added by lcreeve@netins.net
+      // (mail 11 Jul 98 in png-implement list)
+      cmp edx, 8 //test for less than 8 bytes
+      jb duplt8
+
+
+      add ecx, edx
+      and edx, 0x00000007           // calc bytes over mult of 8
+      sub ecx, edx                  // drop over bytes from length
+      jz duplt8
+      // Loop using MMX registers mm0 & mm1 to update 8 bytes simultaneously
+duplpA:
+      movq mm1, [esi+ebx]
+      movq mm0, [edi+ebx]
+      add ebx, 8
+      paddb mm0, mm1
+      cmp ebx, ecx
+      movq [edi+ebx-8], mm0 // movq does not affect flags; -8 to offset add ebx
+      jb duplpA
+      cmp edx, 0            // Test for bytes over mult of 8
+      jz dupend
+duplt8:
+      xor eax, eax
+      add ecx, edx          // move over byte count into counter
+      // Loop using x86 registers to update remaining bytes
+duplp2:
+      mov al, [edi + ebx]
+      add al, [esi + ebx]
+      inc ebx
+      cmp ebx, ecx
+      mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx
+      jb duplp2
+dupend:
+      // Conversion of filtered row completed
+      emms          // End MMX instructions; prep for possible FP instrs.
+   } // end _asm block
+}
+
+
+// Optimized png_read_filter_row routines
+void /* PRIVATE */
+png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep
+   row, png_bytep prev_row, int filter)
+{
+#ifdef PNG_DEBUG
+   char filnm[10];
+#endif
+
+   if (mmx_supported == 2) {
+       /* this should have happened in png_init_mmx_flags() already */
+       png_warning(png_ptr, "asm_flags may not have been initialized");
+       png_mmx_support();
+   }
+
+#ifdef PNG_DEBUG
+   png_debug(1, "in png_read_filter_row\n");
+   switch (filter)
+   {
+      case 0: sprintf(filnm, "none");
+         break;
+      case 1: sprintf(filnm, "sub-%s",
+        (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "MMX" : "x86");
+         break;
+      case 2: sprintf(filnm, "up-%s",
+        (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "MMX" : "x86");
+         break;
+      case 3: sprintf(filnm, "avg-%s",
+        (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "MMX" : "x86");
+         break;
+      case 4: sprintf(filnm, "Paeth-%s",
+        (png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "MMX":"x86");
+         break;
+      default: sprintf(filnm, "unknw");
+         break;
+   }
+   png_debug2(0,"row=%5d, %s, ", png_ptr->row_number, filnm);
+   png_debug2(0, "pd=%2d, b=%d, ", (int)row_info->pixel_depth,
+      (int)((row_info->pixel_depth + 7) >> 3));
+   png_debug1(0,"len=%8d, ", row_info->rowbytes);
+#endif /* PNG_DEBUG */
+
+   switch (filter)
+   {
+      case PNG_FILTER_VALUE_NONE:
+         break;
+
+      case PNG_FILTER_VALUE_SUB:
+      {
+         if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB) &&
+             (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
+             (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
+         {
+            png_read_filter_row_mmx_sub(row_info, row);
+         }
+         else
+         {
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+            png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+            png_bytep rp = row + bpp;
+            png_bytep lp = row;
+
+            for (i = bpp; i < istop; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
+               rp++;
+            }
+         }
+         break;
+      }
+
+      case PNG_FILTER_VALUE_UP:
+      {
+         if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP) &&
+             (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
+             (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
+         {
+            png_read_filter_row_mmx_up(row_info, row, prev_row);
+         }
+         else
+         {
+            png_uint_32 i;
+            png_uint_32 istop = row_info->rowbytes;
+            png_bytep rp = row;
+            png_bytep pp = prev_row;
+
+            for (i = 0; i < istop; ++i)
+            {
+               *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+               rp++;
+            }
+         }
+         break;
+      }
+
+      case PNG_FILTER_VALUE_AVG:
+      {
+         if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG) &&
+             (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
+             (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
+         {
+            png_read_filter_row_mmx_avg(row_info, row, prev_row);
+         }
+         else
+         {
+            png_uint_32 i;
+            png_bytep rp = row;
+            png_bytep pp = prev_row;
+            png_bytep lp = row;
+            png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+            png_uint_32 istop = row_info->rowbytes - bpp;
+
+            for (i = 0; i < bpp; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) +
+                  ((int)(*pp++) >> 1)) & 0xff);
+               rp++;
+            }
+
+            for (i = 0; i < istop; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) +
+                  ((int)(*pp++ + *lp++) >> 1)) & 0xff);
+               rp++;
+            }
+         }
+         break;
+      }
+
+      case PNG_FILTER_VALUE_PAETH:
+      {
+         if ((png_ptr->asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH) &&
+             (row_info->pixel_depth >= png_ptr->mmx_bitdepth_threshold) &&
+             (row_info->rowbytes >= png_ptr->mmx_rowbytes_threshold))
+         {
+            png_read_filter_row_mmx_paeth(row_info, row, prev_row);
+         }
+         else
+         {
+            png_uint_32 i;
+            png_bytep rp = row;
+            png_bytep pp = prev_row;
+            png_bytep lp = row;
+            png_bytep cp = prev_row;
+            png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+            png_uint_32 istop=row_info->rowbytes - bpp;
+
+            for (i = 0; i < bpp; i++)
+            {
+               *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+               rp++;
+            }
+
+            for (i = 0; i < istop; i++)   // use leftover rp,pp
+            {
+               int a, b, c, pa, pb, pc, p;
+
+               a = *lp++;
+               b = *pp++;
+               c = *cp++;
+
+               p = b - c;
+               pc = a - c;
+
+#ifdef PNG_USE_ABS
+               pa = abs(p);
+               pb = abs(pc);
+               pc = abs(p + pc);
+#else
+               pa = p < 0 ? -p : p;
+               pb = pc < 0 ? -pc : pc;
+               pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+               /*
+                  if (pa <= pb && pa <= pc)
+                     p = a;
+                  else if (pb <= pc)
+                     p = b;
+                  else
+                     p = c;
+                */
+
+               p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+
+               *rp = (png_byte)(((int)(*rp) + p) & 0xff);
+               rp++;
+            }
+         }
+         break;
+      }
+
+      default:
+         png_warning(png_ptr, "Ignoring bad row filter type");
+         *row=0;
+         break;
+   }
+}
+
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED && PNG_USE_PNGVCRD */
diff --git a/libraries/libpng-1.2.0/pngwio.c b/libraries/libpng-1.2.0/pngwio.c
new file mode 100644 (file)
index 0000000..efc39e6
--- /dev/null
@@ -0,0 +1,228 @@
+
+/* pngwio.c - functions for data output
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This file provides a location for all output.  Users who need
+ * special handling are expected to write functions that have the same
+ * arguments as these and perform similar functions, but that possibly
+ * use different output methods.  Note that you shouldn't change these
+ * functions, but rather write replacement functions and then change
+ * them at run time with png_set_write_fn(...).
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Write the data to whatever output you are using.  The default routine
+   writes to a file pointer.  Note that this routine sometimes gets called
+   with very small lengths, so you should implement some kind of simple
+   buffering if you are using unbuffered writes.  This should never be asked
+   to write more than 64K on a 16 bit machine.  */
+
+void /* PRIVATE */
+png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   if (png_ptr->write_data_fn != NULL )
+      (*(png_ptr->write_data_fn))(png_ptr, data, length);
+   else
+      png_error(png_ptr, "Call to NULL write function");
+}
+
+#if !defined(PNG_NO_STDIO)
+/* This is the function that does the actual writing of data.  If you are
+   not writing to a standard C stream, you should create a replacement
+   write_data function and use it at run time with png_set_write_fn(), rather
+   than changing the library. */
+#ifndef USE_FAR_KEYWORD
+static void /* PRIVATE */
+png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_uint_32 check;
+
+#if defined(_WIN32_WCE)
+   if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
+      check = 0;
+#else
+   check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
+#endif
+   if (check != length)
+      png_error(png_ptr, "Write Error");
+}
+#else
+/* this is the model-independent version. Since the standard I/O library
+   can't handle far buffers in the medium and small models, we have to copy
+   the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void /* PRIVATE */
+png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   png_uint_32 check;
+   png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
+   png_FILE_p io_ptr;
+
+   /* Check if data really is near. If so, use usual code. */
+   near_data = (png_byte *)CVT_PTR_NOCHECK(data);
+   io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+   if ((png_bytep)near_data == data)
+   {
+#if defined(_WIN32_WCE)
+      if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
+         check = 0;
+#else
+      check = fwrite(near_data, 1, length, io_ptr);
+#endif
+   }
+   else
+   {
+      png_byte buf[NEAR_BUF_SIZE];
+      png_size_t written, remaining, err;
+      check = 0;
+      remaining = length;
+      do
+      {
+         written = MIN(NEAR_BUF_SIZE, remaining);
+         png_memcpy(buf, data, written); /* copy far buffer to near buffer */
+#if defined(_WIN32_WCE)
+         if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
+            err = 0;
+#else
+         err = fwrite(buf, 1, written, io_ptr);
+#endif
+         if (err != written)
+            break;
+         else
+            check += err;
+         data += written;
+         remaining -= written;
+      }
+      while (remaining != 0);
+   }
+   if (check != length)
+      png_error(png_ptr, "Write Error");
+}
+
+#endif
+#endif
+
+/* This function is called to output any data pending writing (normally
+   to disk).  After png_flush is called, there should be no data pending
+   writing in any buffers. */
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+void /* PRIVATE */
+png_flush(png_structp png_ptr)
+{
+   if (png_ptr->output_flush_fn != NULL)
+      (*(png_ptr->output_flush_fn))(png_ptr);
+}
+
+#if !defined(PNG_NO_STDIO)
+static void /* PRIVATE */
+png_default_flush(png_structp png_ptr)
+{
+#if !defined(_WIN32_WCE)
+   png_FILE_p io_ptr;
+   io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
+   if (io_ptr != NULL)
+      fflush(io_ptr);
+#endif
+}
+#endif
+#endif
+
+/* This function allows the application to supply new output functions for
+   libpng if standard C streams aren't being used.
+
+   This function takes as its arguments:
+   png_ptr       - pointer to a png output data structure
+   io_ptr        - pointer to user supplied structure containing info about
+                   the output functions.  May be NULL.
+   write_data_fn - pointer to a new output function that takes as its
+                   arguments a pointer to a png_struct, a pointer to
+                   data to be written, and a 32-bit unsigned int that is
+                   the number of bytes to be written.  The new write
+                   function should call png_error(png_ptr, "Error msg")
+                   to exit and output any fatal error messages.
+   flush_data_fn - pointer to a new flush function that takes as its
+                   arguments a pointer to a png_struct.  After a call to
+                   the flush function, there should be no data in any buffers
+                   or pending transmission.  If the output method doesn't do
+                   any buffering of ouput, a function prototype must still be
+                   supplied although it doesn't have to do anything.  If
+                   PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
+                   time, output_flush_fn will be ignored, although it must be
+                   supplied for compatibility. */
+void PNGAPI
+png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
+   png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
+{
+   png_ptr->io_ptr = io_ptr;
+
+#if !defined(PNG_NO_STDIO)
+   if (write_data_fn != NULL)
+      png_ptr->write_data_fn = write_data_fn;
+   else
+      png_ptr->write_data_fn = png_default_write_data;
+#else
+   png_ptr->write_data_fn = write_data_fn;
+#endif
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+#if !defined(PNG_NO_STDIO)
+   if (output_flush_fn != NULL)
+      png_ptr->output_flush_fn = output_flush_fn;
+   else
+      png_ptr->output_flush_fn = png_default_flush;
+#else
+   png_ptr->output_flush_fn = output_flush_fn;
+#endif
+#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+
+   /* It is an error to read while writing a png file */
+   if (png_ptr->read_data_fn != NULL)
+   {
+      png_ptr->read_data_fn = NULL;
+      png_warning(png_ptr,
+         "Attempted to set both read_data_fn and write_data_fn in");
+      png_warning(png_ptr,
+         "the same structure.  Resetting read_data_fn to NULL.");
+   }
+}
+
+#if defined(USE_FAR_KEYWORD)
+#if defined(_MSC_VER)
+void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
+{
+   void *near_ptr;
+   void FAR *far_ptr;
+   FP_OFF(near_ptr) = FP_OFF(ptr);
+   far_ptr = (void FAR *)near_ptr;
+   if(check != 0)
+      if(FP_SEG(ptr) != FP_SEG(far_ptr))
+         png_error(png_ptr,"segment lost in conversion");
+   return(near_ptr);
+}
+#  else
+void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
+{
+   void *near_ptr;
+   void FAR *far_ptr;
+   near_ptr = (void FAR *)ptr;
+   far_ptr = (void FAR *)near_ptr;
+   if(check != 0)
+      if(far_ptr != ptr)
+         png_error(png_ptr,"segment lost in conversion");
+   return(near_ptr);
+}
+#   endif
+#   endif
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/libraries/libpng-1.2.0/pngwrite.c b/libraries/libpng-1.2.0/pngwrite.c
new file mode 100644 (file)
index 0000000..afec136
--- /dev/null
@@ -0,0 +1,1427 @@
+
+/* pngwrite.c - general routines to write a PNG file
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+/* get internal access to png.h */
+#define PNG_INTERNAL
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Writes all the PNG information.  This is the suggested way to use the
+ * library.  If you have a new chunk to add, make a function to write it,
+ * and put it in the correct location here.  If you want the chunk written
+ * after the image data, put it in png_write_end().  I strongly encourage
+ * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
+ * the chunk, as that will keep the code from breaking if you want to just
+ * write a plain PNG file.  If you have long comments, I suggest writing
+ * them in png_write_end(), and compressing them.
+ */
+void PNGAPI
+png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_write_info_before_PLTE\n");
+   if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
+   {
+   png_write_sig(png_ptr); /* write PNG signature */
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted))
+   {
+      png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n");
+      png_ptr->mng_features_permitted=0;
+   }
+#endif
+   /* write IHDR information. */
+   png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
+      info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
+      info_ptr->filter_type,
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+      info_ptr->interlace_type);
+#else
+      0);
+#endif
+   /* the rest of these check to see if the valid field has the appropriate
+      flag set, and if it does, writes the chunk. */
+#if defined(PNG_WRITE_gAMA_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_gAMA)
+   {
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+      png_write_gAMA(png_ptr, info_ptr->gamma);
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+      png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma);
+#  endif
+#endif
+   }
+#endif
+#if defined(PNG_WRITE_sRGB_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sRGB)
+      png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
+#endif
+#if defined(PNG_WRITE_iCCP_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_iCCP)
+      png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
+                     info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
+#endif
+#if defined(PNG_WRITE_sBIT_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sBIT)
+      png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
+#endif
+#if defined(PNG_WRITE_cHRM_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_cHRM)
+   {
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+      png_write_cHRM(png_ptr,
+         info_ptr->x_white, info_ptr->y_white,
+         info_ptr->x_red, info_ptr->y_red,
+         info_ptr->x_green, info_ptr->y_green,
+         info_ptr->x_blue, info_ptr->y_blue);
+#else
+#  ifdef PNG_FIXED_POINT_SUPPORTED
+      png_write_cHRM_fixed(png_ptr,
+         info_ptr->int_x_white, info_ptr->int_y_white,
+         info_ptr->int_x_red, info_ptr->int_y_red,
+         info_ptr->int_x_green, info_ptr->int_y_green,
+         info_ptr->int_x_blue, info_ptr->int_y_blue);
+#  endif
+#endif
+   }
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   if (info_ptr->unknown_chunks_num)
+   {
+       png_unknown_chunk *up;
+
+       png_debug(5, "writing extra chunks\n");
+
+       for (up = info_ptr->unknown_chunks;
+            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+            up++)
+       {
+         int keep=png_handle_as_unknown(png_ptr, up->name);
+         if (keep != HANDLE_CHUNK_NEVER &&
+            up->location && (!(up->location & PNG_HAVE_PLTE)) &&
+            ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS ||
+            (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+         {
+            png_write_chunk(png_ptr, up->name, up->data, up->size);
+         }
+       }
+   }
+#endif
+      png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
+   }
+}
+
+void PNGAPI
+png_write_info(png_structp png_ptr, png_infop info_ptr)
+{
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
+   int i;
+#endif
+
+   png_debug(1, "in png_write_info\n");
+
+   png_write_info_before_PLTE(png_ptr, info_ptr);
+
+   if (info_ptr->valid & PNG_INFO_PLTE)
+      png_write_PLTE(png_ptr, info_ptr->palette,
+         (png_uint_32)info_ptr->num_palette);
+   else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+      png_error(png_ptr, "Valid palette required for paletted images\n");
+
+#if defined(PNG_WRITE_tRNS_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_tRNS)
+      {
+#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+         /* invert the alpha channel (in tRNS) */
+         if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
+            info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+         {
+            int j;
+            for (j=0; j<(int)info_ptr->num_trans; j++)
+               info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
+         }
+#endif
+      png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
+         info_ptr->num_trans, info_ptr->color_type);
+      }
+#endif
+#if defined(PNG_WRITE_bKGD_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_bKGD)
+      png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
+#endif
+#if defined(PNG_WRITE_hIST_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_hIST)
+      png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
+#endif
+#if defined(PNG_WRITE_oFFs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_oFFs)
+      png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
+         info_ptr->offset_unit_type);
+#endif
+#if defined(PNG_WRITE_pCAL_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pCAL)
+      png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
+         info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
+         info_ptr->pcal_units, info_ptr->pcal_params);
+#endif
+#if defined(PNG_WRITE_sCAL_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sCAL)
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
+      png_write_sCAL(png_ptr, (int)info_ptr->scal_unit,
+          info_ptr->scal_pixel_width, info_ptr->scal_pixel_height);
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+      png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
+          info_ptr->scal_s_width, info_ptr->scal_s_height);
+#else
+      png_warning(png_ptr,
+          "png_write_sCAL not supported; sCAL chunk not written.\n");
+#endif
+#endif
+#endif
+#if defined(PNG_WRITE_pHYs_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_pHYs)
+      png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
+         info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
+#endif
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_tIME)
+   {
+      png_write_tIME(png_ptr, &(info_ptr->mod_time));
+      png_ptr->mode |= PNG_WROTE_tIME;
+   }
+#endif
+#if defined(PNG_WRITE_sPLT_SUPPORTED)
+   if (info_ptr->valid & PNG_INFO_sPLT)
+     for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
+       png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
+#endif
+#if defined(PNG_WRITE_TEXT_SUPPORTED)
+   /* Check to see if we need to write text chunks */
+   for (i = 0; i < info_ptr->num_text; i++)
+   {
+      png_debug2(2, "Writing header text chunk %d, type %d\n", i,
+         info_ptr->text[i].compression);
+      /* an internationalized chunk? */
+      if (info_ptr->text[i].compression > 0)
+      {
+#if defined(PNG_WRITE_iTXt_SUPPORTED)
+          /* write international chunk */
+          png_write_iTXt(png_ptr,
+                         info_ptr->text[i].compression,
+                         info_ptr->text[i].key,
+                         info_ptr->text[i].lang,
+                         info_ptr->text[i].lang_key,
+                         info_ptr->text[i].text);
+#else
+          png_warning(png_ptr, "Unable to write international text\n");
+#endif
+          /* Mark this chunk as written */
+          info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+      }
+      /* If we want a compressed text chunk */
+      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
+      {
+#if defined(PNG_WRITE_zTXt_SUPPORTED)
+         /* write compressed chunk */
+         png_write_zTXt(png_ptr, info_ptr->text[i].key,
+            info_ptr->text[i].text, 0,
+            info_ptr->text[i].compression);
+#else
+         png_warning(png_ptr, "Unable to write compressed text\n");
+#endif
+         /* Mark this chunk as written */
+         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
+      }
+      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+      {
+#if defined(PNG_WRITE_tEXt_SUPPORTED)
+         /* write uncompressed chunk */
+         png_write_tEXt(png_ptr, info_ptr->text[i].key,
+                         info_ptr->text[i].text,
+                         0);
+#else
+         png_warning(png_ptr, "Unable to write uncompressed text\n");
+#endif
+         /* Mark this chunk as written */
+         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+      }
+   }
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   if (info_ptr->unknown_chunks_num)
+   {
+       png_unknown_chunk *up;
+
+       png_debug(5, "writing extra chunks\n");
+
+       for (up = info_ptr->unknown_chunks;
+            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+            up++)
+       {
+         int keep=png_handle_as_unknown(png_ptr, up->name);
+         if (keep != HANDLE_CHUNK_NEVER &&
+            up->location && (up->location & PNG_HAVE_PLTE) &&
+            !(up->location & PNG_HAVE_IDAT) &&
+            ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS ||
+            (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+         {
+            png_write_chunk(png_ptr, up->name, up->data, up->size);
+         }
+       }
+   }
+#endif
+}
+
+/* Writes the end of the PNG file.  If you don't want to write comments or
+ * time information, you can pass NULL for info.  If you already wrote these
+ * in png_write_info(), do not write them again here.  If you have long
+ * comments, I suggest writing them here, and compressing them.
+ */
+void PNGAPI
+png_write_end(png_structp png_ptr, png_infop info_ptr)
+{
+   png_debug(1, "in png_write_end\n");
+   if (!(png_ptr->mode & PNG_HAVE_IDAT))
+      png_error(png_ptr, "No IDATs written into file");
+
+   /* see if user wants us to write information chunks */
+   if (info_ptr != NULL)
+   {
+#if defined(PNG_WRITE_TEXT_SUPPORTED)
+      int i; /* local index variable */
+#endif
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+      /* check to see if user has supplied a time chunk */
+      if ((info_ptr->valid & PNG_INFO_tIME) &&
+         !(png_ptr->mode & PNG_WROTE_tIME))
+         png_write_tIME(png_ptr, &(info_ptr->mod_time));
+#endif
+#if defined(PNG_WRITE_TEXT_SUPPORTED)
+      /* loop through comment chunks */
+      for (i = 0; i < info_ptr->num_text; i++)
+      {
+         png_debug2(2, "Writing trailer text chunk %d, type %d\n", i,
+            info_ptr->text[i].compression);
+         /* an internationalized chunk? */
+         if (info_ptr->text[i].compression > 0)
+         {
+#if defined(PNG_WRITE_iTXt_SUPPORTED)
+             /* write international chunk */
+             png_write_iTXt(png_ptr,
+                         info_ptr->text[i].compression,
+                         info_ptr->text[i].key,
+                         info_ptr->text[i].lang,
+                         info_ptr->text[i].lang_key,
+                         info_ptr->text[i].text);
+#else
+             png_warning(png_ptr, "Unable to write international text\n");
+#endif
+             /* Mark this chunk as written */
+             info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+         }
+         else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
+         {
+#if defined(PNG_WRITE_zTXt_SUPPORTED)
+            /* write compressed chunk */
+            png_write_zTXt(png_ptr, info_ptr->text[i].key,
+               info_ptr->text[i].text, 0,
+               info_ptr->text[i].compression);
+#else
+            png_warning(png_ptr, "Unable to write compressed text\n");
+#endif
+            /* Mark this chunk as written */
+            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
+         }
+         else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+         {
+#if defined(PNG_WRITE_tEXt_SUPPORTED)
+            /* write uncompressed chunk */
+            png_write_tEXt(png_ptr, info_ptr->text[i].key,
+               info_ptr->text[i].text, 0);
+#else
+            png_warning(png_ptr, "Unable to write uncompressed text\n");
+#endif
+
+            /* Mark this chunk as written */
+            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+         }
+      }
+#endif
+#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
+   if (info_ptr->unknown_chunks_num)
+   {
+       png_unknown_chunk *up;
+
+       png_debug(5, "writing extra chunks\n");
+
+       for (up = info_ptr->unknown_chunks;
+            up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+            up++)
+       {
+         int keep=png_handle_as_unknown(png_ptr, up->name);
+         if (keep != HANDLE_CHUNK_NEVER &&
+            up->location && (up->location & PNG_AFTER_IDAT) &&
+            ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS ||
+            (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+         {
+            png_write_chunk(png_ptr, up->name, up->data, up->size);
+         }
+       }
+   }
+#endif
+   }
+
+   png_ptr->mode |= PNG_AFTER_IDAT;
+
+   /* write end of PNG file */
+   png_write_IEND(png_ptr);
+#if 0
+/* This flush, added in libpng-1.0.8,  causes some applications to crash
+   because they do not set png_ptr->output_flush_fn */
+   png_flush(png_ptr);
+#endif
+}
+
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+#if !defined(_WIN32_WCE)
+/* "time.h" functions are not supported on WindowsCE */
+void PNGAPI
+png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
+{
+   png_debug(1, "in png_convert_from_struct_tm\n");
+   ptime->year = (png_uint_16)(1900 + ttime->tm_year);
+   ptime->month = (png_byte)(ttime->tm_mon + 1);
+   ptime->day = (png_byte)ttime->tm_mday;
+   ptime->hour = (png_byte)ttime->tm_hour;
+   ptime->minute = (png_byte)ttime->tm_min;
+   ptime->second = (png_byte)ttime->tm_sec;
+}
+
+void PNGAPI
+png_convert_from_time_t(png_timep ptime, time_t ttime)
+{
+   struct tm *tbuf;
+
+   png_debug(1, "in png_convert_from_time_t\n");
+   tbuf = gmtime(&ttime);
+   png_convert_from_struct_tm(ptime, tbuf);
+}
+#endif
+#endif
+
+/* Initialize png_ptr structure, and allocate any memory needed */
+png_structp PNGAPI
+png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+   return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
+      warn_fn, NULL, NULL, NULL));
+}
+
+/* Alternate initialize png_ptr structure, and allocate any memory needed */
+png_structp PNGAPI
+png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
+   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+   png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+   png_structp png_ptr;
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+   jmp_buf jmpbuf;
+#endif
+#endif
+   int i;
+   png_debug(1, "in png_create_write_struct\n");
+#ifdef PNG_USER_MEM_SUPPORTED
+   if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
+      (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr)) == NULL)
+#else
+   if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
+#endif /* PNG_USER_MEM_SUPPORTED */
+   {
+      return ((png_structp)NULL);
+   }
+
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+   png_init_mmx_flags(png_ptr);   /* 1.2.0 addition */
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+   if (setjmp(jmpbuf))
+#else
+   if (setjmp(png_ptr->jmpbuf))
+#endif
+   {
+      png_free(png_ptr, png_ptr->zbuf);
+      png_ptr->zbuf=NULL;
+      png_destroy_struct(png_ptr);
+      return ((png_structp)NULL);
+   }
+#ifdef USE_FAR_KEYWORD
+   png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
+#endif
+#endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
+#endif /* PNG_USER_MEM_SUPPORTED */
+   png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
+
+   i=0;
+   do
+   {
+     if(user_png_ver[i] != png_libpng_ver[i])
+        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+   } while (png_libpng_ver[i++]);
+
+   if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+   {
+     /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
+      * we must recompile any applications that use any older library version.
+      * For versions after libpng 1.0, we will be compatible, so we need
+      * only check the first digit.
+      */
+     if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
+         (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
+         (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
+     {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+        char msg[80];
+        if (user_png_ver)
+        {
+          sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
+             user_png_ver);
+          png_warning(png_ptr, msg);
+        }
+        sprintf(msg, "Application  is running with png.c from libpng-%.20s",
+           png_libpng_ver);
+        png_warning(png_ptr, msg);
+#endif
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+        png_ptr->flags=0;
+#endif
+        png_error(png_ptr,
+           "Incompatible libpng version in application and library");
+     }
+   }
+
+   /* initialize zbuf - compression buffer */
+   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+      (png_uint_32)png_ptr->zbuf_size);
+
+   png_set_write_fn(png_ptr, NULL, NULL, NULL);
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
+      1, NULL, NULL);
+#endif
+
+   return ((png_structp)png_ptr);
+}
+
+/* Initialize png_ptr structure, and allocate any memory needed */
+#undef png_write_init
+void PNGAPI
+png_write_init(png_structp png_ptr)
+{
+   /* We only come here via pre-1.0.7-compiled applications */
+   png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0);
+}
+
+#undef png_write_init_2
+void PNGAPI
+png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver,
+   png_size_t png_struct_size, png_size_t png_info_size)
+{
+   /* We only come here via pre-1.0.12-compiled applications */
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+   if(sizeof(png_struct) > png_struct_size || sizeof(png_info) > png_info_size)
+   {
+      char msg[80];
+      png_ptr->warning_fn=(png_error_ptr)NULL;
+      if (user_png_ver)
+      {
+        sprintf(msg, "Application was compiled with png.h from libpng-%.20s",
+           user_png_ver);
+        png_warning(png_ptr, msg);
+      }
+      sprintf(msg, "Application  is running with png.c from libpng-%.20s",
+         png_libpng_ver);
+      png_warning(png_ptr, msg);
+   }
+#endif
+   if(sizeof(png_struct) > png_struct_size)
+     {
+       png_ptr->error_fn=(png_error_ptr)NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+       png_ptr->flags=0;
+#endif
+       png_error(png_ptr,
+       "The png struct allocated by the application for writing is too small.");
+     }
+   if(sizeof(png_info) > png_info_size)
+     {
+       png_ptr->error_fn=(png_error_ptr)NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+       png_ptr->flags=0;
+#endif
+       png_error(png_ptr,
+       "The info struct allocated by the application for writing is too small.");
+     }
+   png_write_init_3(&png_ptr, user_png_ver, png_struct_size);
+}
+
+
+void PNGAPI
+png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
+   png_size_t png_struct_size)
+{
+   png_structp png_ptr=*ptr_ptr;
+#ifdef PNG_SETJMP_SUPPORTED
+   jmp_buf tmp_jmp; /* to save current jump buffer */
+#endif
+   int i = 0;
+   do
+   {
+     if (user_png_ver[i] != png_libpng_ver[i])
+     {
+#ifdef PNG_LEGACY_SUPPORTED
+       png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+#else
+       png_ptr->warning_fn=(png_error_ptr)NULL;
+       png_warning(png_ptr,
+     "Application uses deprecated png_write_init() and should be recompiled.");
+       break;
+#endif
+     }
+   } while (png_libpng_ver[i++]);
+
+   png_debug(1, "in png_write_init_3\n");
+
+#ifdef PNG_SETJMP_SUPPORTED
+   /* save jump buffer and error functions */
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
+#endif
+
+   if (sizeof(png_struct) > png_struct_size)
+     {
+       png_destroy_struct(png_ptr);
+       png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
+       *ptr_ptr = png_ptr;
+     }
+
+   /* reset all variables to 0 */
+   png_memset(png_ptr, 0, sizeof (png_struct));
+
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+   png_init_mmx_flags(png_ptr);   /* 1.2.0 addition */
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+   /* restore jump buffer */
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
+#endif
+
+   png_set_write_fn(png_ptr, NULL, NULL, NULL);
+
+   /* initialize zbuf - compression buffer */
+   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+      (png_uint_32)png_ptr->zbuf_size);
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
+      1, NULL, NULL);
+#endif
+}
+
+/* Write a few rows of image data.  If the image is interlaced,
+ * either you will have to write the 7 sub images, or, if you
+ * have called png_set_interlace_handling(), you will have to
+ * "write" the image seven times.
+ */
+void PNGAPI
+png_write_rows(png_structp png_ptr, png_bytepp row,
+   png_uint_32 num_rows)
+{
+   png_uint_32 i; /* row counter */
+   png_bytepp rp; /* row pointer */
+
+   png_debug(1, "in png_write_rows\n");
+   /* loop through the rows */
+   for (i = 0, rp = row; i < num_rows; i++, rp++)
+   {
+      png_write_row(png_ptr, *rp);
+   }
+}
+
+/* Write the image.  You only need to call this function once, even
+ * if you are writing an interlaced image.
+ */
+void PNGAPI
+png_write_image(png_structp png_ptr, png_bytepp image)
+{
+   png_uint_32 i; /* row index */
+   int pass, num_pass; /* pass variables */
+   png_bytepp rp; /* points to current row */
+
+   png_debug(1, "in png_write_image\n");
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+   /* intialize interlace handling.  If image is not interlaced,
+      this will set pass to 1 */
+   num_pass = png_set_interlace_handling(png_ptr);
+#else
+   num_pass = 1;
+#endif
+   /* loop through passes */
+   for (pass = 0; pass < num_pass; pass++)
+   {
+      /* loop through image */
+      for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
+      {
+         png_write_row(png_ptr, *rp);
+      }
+   }
+}
+
+/* called by user to write a row of image data */
+void PNGAPI
+png_write_row(png_structp png_ptr, png_bytep row)
+{
+   png_debug2(1, "in png_write_row (row %ld, pass %d)\n",
+      png_ptr->row_number, png_ptr->pass);
+   /* initialize transformations and other stuff if first time */
+   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
+   {
+   /* check for transforms that have been set but were defined out */
+#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_MONO)
+      png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
+   if (png_ptr->transformations & PNG_FILLER)
+      png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACKSWAP)
+      png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACK)
+      png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
+   if (png_ptr->transformations & PNG_SHIFT)
+      png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
+   if (png_ptr->transformations & PNG_BGR)
+      png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
+#endif
+
+      png_write_start_row(png_ptr);
+   }
+
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+   /* if interlaced and not interested in row, return */
+   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+   {
+      switch (png_ptr->pass)
+      {
+         case 0:
+            if (png_ptr->row_number & 0x07)
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 1:
+            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 2:
+            if ((png_ptr->row_number & 0x07) != 4)
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 3:
+            if ((png_ptr->row_number & 0x03) || png_ptr->width < 3)
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 4:
+            if ((png_ptr->row_number & 0x03) != 2)
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 5:
+            if ((png_ptr->row_number & 0x01) || png_ptr->width < 2)
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+         case 6:
+            if (!(png_ptr->row_number & 0x01))
+            {
+               png_write_finish_row(png_ptr);
+               return;
+            }
+            break;
+      }
+   }
+#endif
+
+   /* set up row info for transformations */
+   png_ptr->row_info.color_type = png_ptr->color_type;
+   png_ptr->row_info.width = png_ptr->usr_width;
+   png_ptr->row_info.channels = png_ptr->usr_channels;
+   png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
+   png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
+      png_ptr->row_info.channels);
+
+   png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
+      (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
+
+   png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type);
+   png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width);
+   png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels);
+   png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth);
+   png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth);
+   png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes);
+
+   /* Copy user's row into buffer, leaving room for filter byte. */
+   png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row,
+      png_ptr->row_info.rowbytes);
+
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+   /* handle interlacing */
+   if (png_ptr->interlaced && png_ptr->pass < 6 &&
+      (png_ptr->transformations & PNG_INTERLACE))
+   {
+      png_do_write_interlace(&(png_ptr->row_info),
+         png_ptr->row_buf + 1, png_ptr->pass);
+      /* this should always get caught above, but still ... */
+      if (!(png_ptr->row_info.width))
+      {
+         png_write_finish_row(png_ptr);
+         return;
+      }
+   }
+#endif
+
+   /* handle other transformations */
+   if (png_ptr->transformations)
+      png_do_write_transformations(png_ptr);
+
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   /* Write filter_method 64 (intrapixel differencing) only if
+    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+    * 2. Libpng did not write a PNG signature (this filter_method is only
+    *    used in PNG datastreams that are embedded in MNG datastreams) and
+    * 3. The application called png_permit_mng_features with a mask that
+    *    included PNG_FLAG_MNG_FILTER_64 and
+    * 4. The filter_method is 64 and
+    * 5. The color_type is RGB or RGBA
+    */
+   if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+      (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
+   {
+      /* Intrapixel differencing */
+      png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
+   }
+#endif
+
+   /* Find a filter if necessary, filter the row and write it out. */
+   png_write_find_filter(png_ptr, &(png_ptr->row_info));
+
+   if (png_ptr->write_row_fn != NULL)
+      (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
+}
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+/* Set the automatic flush interval or 0 to turn flushing off */
+void PNGAPI
+png_set_flush(png_structp png_ptr, int nrows)
+{
+   png_debug(1, "in png_set_flush\n");
+   png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
+}
+
+/* flush the current output buffers now */
+void PNGAPI
+png_write_flush(png_structp png_ptr)
+{
+   int wrote_IDAT;
+
+   png_debug(1, "in png_write_flush\n");
+   /* We have already written out all of the data */
+   if (png_ptr->row_number >= png_ptr->num_rows)
+     return;
+
+   do
+   {
+      int ret;
+
+      /* compress the data */
+      ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
+      wrote_IDAT = 0;
+
+      /* check for compression errors */
+      if (ret != Z_OK)
+      {
+         if (png_ptr->zstream.msg != NULL)
+            png_error(png_ptr, png_ptr->zstream.msg);
+         else
+            png_error(png_ptr, "zlib error");
+      }
+
+      if (!(png_ptr->zstream.avail_out))
+      {
+         /* write the IDAT and reset the zlib output buffer */
+         png_write_IDAT(png_ptr, png_ptr->zbuf,
+                        png_ptr->zbuf_size);
+         png_ptr->zstream.next_out = png_ptr->zbuf;
+         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+         wrote_IDAT = 1;
+      }
+   } while(wrote_IDAT == 1);
+
+   /* If there is any data left to be output, write it into a new IDAT */
+   if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
+   {
+      /* write the IDAT and reset the zlib output buffer */
+      png_write_IDAT(png_ptr, png_ptr->zbuf,
+                     png_ptr->zbuf_size - png_ptr->zstream.avail_out);
+      png_ptr->zstream.next_out = png_ptr->zbuf;
+      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+   }
+   png_ptr->flush_rows = 0;
+   png_flush(png_ptr);
+}
+#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+
+/* free all memory used by the write */
+void PNGAPI
+png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
+{
+   png_structp png_ptr = NULL;
+   png_infop info_ptr = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn = NULL;
+   png_voidp mem_ptr = NULL;
+#endif
+
+   png_debug(1, "in png_destroy_write_struct\n");
+   if (png_ptr_ptr != NULL)
+   {
+      png_ptr = *png_ptr_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+      free_fn = png_ptr->free_fn;
+#endif
+   }
+
+   if (info_ptr_ptr != NULL)
+      info_ptr = *info_ptr_ptr;
+
+   if (info_ptr != NULL)
+   {
+      png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+      if (png_ptr->num_chunk_list)
+      {
+         png_free(png_ptr, png_ptr->chunk_list);
+         png_ptr->chunk_list=NULL;
+         png_ptr->num_chunk_list=0;
+      }
+#endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
+         (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)info_ptr);
+#endif
+      *info_ptr_ptr = (png_infop)NULL;
+   }
+
+   if (png_ptr != NULL)
+   {
+      png_write_destroy(png_ptr);
+#ifdef PNG_USER_MEM_SUPPORTED
+      png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
+         (png_voidp)mem_ptr);
+#else
+      png_destroy_struct((png_voidp)png_ptr);
+#endif
+      *png_ptr_ptr = (png_structp)NULL;
+   }
+}
+
+
+/* Free any memory used in png_ptr struct (old method) */
+void /* PRIVATE */
+png_write_destroy(png_structp png_ptr)
+{
+#ifdef PNG_SETJMP_SUPPORTED
+   jmp_buf tmp_jmp; /* save jump buffer */
+#endif
+   png_error_ptr error_fn;
+   png_error_ptr warning_fn;
+   png_voidp error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_free_ptr free_fn;
+#endif
+
+   png_debug(1, "in png_write_destroy\n");
+   /* free any memory zlib uses */
+   deflateEnd(&png_ptr->zstream);
+
+   /* free our memory.  png_free checks NULL for us. */
+   png_free(png_ptr, png_ptr->zbuf);
+   png_free(png_ptr, png_ptr->row_buf);
+   png_free(png_ptr, png_ptr->prev_row);
+   png_free(png_ptr, png_ptr->sub_row);
+   png_free(png_ptr, png_ptr->up_row);
+   png_free(png_ptr, png_ptr->avg_row);
+   png_free(png_ptr, png_ptr->paeth_row);
+
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+   png_free(png_ptr, png_ptr->time_buffer);
+#endif
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   png_free(png_ptr, png_ptr->prev_filters);
+   png_free(png_ptr, png_ptr->filter_weights);
+   png_free(png_ptr, png_ptr->inv_filter_weights);
+   png_free(png_ptr, png_ptr->filter_costs);
+   png_free(png_ptr, png_ptr->inv_filter_costs);
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+   /* reset structure */
+   png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
+#endif
+
+   error_fn = png_ptr->error_fn;
+   warning_fn = png_ptr->warning_fn;
+   error_ptr = png_ptr->error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   free_fn = png_ptr->free_fn;
+#endif
+
+   png_memset(png_ptr, 0, sizeof (png_struct));
+
+   png_ptr->error_fn = error_fn;
+   png_ptr->warning_fn = warning_fn;
+   png_ptr->error_ptr = error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+   png_ptr->free_fn = free_fn;
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+   png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
+#endif
+}
+
+/* Allow the application to select one or more row filters to use. */
+void PNGAPI
+png_set_filter(png_structp png_ptr, int method, int filters)
+{
+   png_debug(1, "in png_set_filter\n");
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+      (method == PNG_INTRAPIXEL_DIFFERENCING))
+         method = PNG_FILTER_TYPE_BASE;
+#endif
+   if (method == PNG_FILTER_TYPE_BASE)
+   {
+      switch (filters & (PNG_ALL_FILTERS | 0x07))
+      {
+         case 5:
+         case 6:
+         case 7: png_warning(png_ptr, "Unknown row filter for method 0");
+         case PNG_FILTER_VALUE_NONE:  png_ptr->do_filter=PNG_FILTER_NONE; break;
+         case PNG_FILTER_VALUE_SUB:   png_ptr->do_filter=PNG_FILTER_SUB;  break;
+         case PNG_FILTER_VALUE_UP:    png_ptr->do_filter=PNG_FILTER_UP;   break;
+         case PNG_FILTER_VALUE_AVG:   png_ptr->do_filter=PNG_FILTER_AVG;  break;
+         case PNG_FILTER_VALUE_PAETH: png_ptr->do_filter=PNG_FILTER_PAETH;break;
+         default: png_ptr->do_filter = (png_byte)filters; break;
+      }
+
+      /* If we have allocated the row_buf, this means we have already started
+       * with the image and we should have allocated all of the filter buffers
+       * that have been selected.  If prev_row isn't already allocated, then
+       * it is too late to start using the filters that need it, since we
+       * will be missing the data in the previous row.  If an application
+       * wants to start and stop using particular filters during compression,
+       * it should start out with all of the filters, and then add and
+       * remove them after the start of compression.
+       */
+      if (png_ptr->row_buf != NULL)
+      {
+         if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
+         {
+            png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
+              (png_ptr->rowbytes + 1));
+            png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
+         }
+
+         if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL)
+         {
+            if (png_ptr->prev_row == NULL)
+            {
+               png_warning(png_ptr, "Can't add Up filter after starting");
+               png_ptr->do_filter &= ~PNG_FILTER_UP;
+            }
+            else
+            {
+               png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
+                  (png_ptr->rowbytes + 1));
+               png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
+            }
+         }
+
+         if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL)
+         {
+            if (png_ptr->prev_row == NULL)
+            {
+               png_warning(png_ptr, "Can't add Average filter after starting");
+               png_ptr->do_filter &= ~PNG_FILTER_AVG;
+            }
+            else
+            {
+               png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
+                  (png_ptr->rowbytes + 1));
+               png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
+            }
+         }
+
+         if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
+             png_ptr->paeth_row == NULL)
+         {
+            if (png_ptr->prev_row == NULL)
+            {
+               png_warning(png_ptr, "Can't add Paeth filter after starting");
+               png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH);
+            }
+            else
+            {
+               png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
+                  (png_ptr->rowbytes + 1));
+               png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
+            }
+         }
+
+         if (png_ptr->do_filter == PNG_NO_FILTERS)
+            png_ptr->do_filter = PNG_FILTER_NONE;
+      }
+   }
+   else
+      png_error(png_ptr, "Unknown custom filter method");
+}
+
+/* This allows us to influence the way in which libpng chooses the "best"
+ * filter for the current scanline.  While the "minimum-sum-of-absolute-
+ * differences metric is relatively fast and effective, there is some
+ * question as to whether it can be improved upon by trying to keep the
+ * filtered data going to zlib more consistent, hopefully resulting in
+ * better compression.
+ */
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)      /* GRR 970116 */
+void PNGAPI
+png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
+   int num_weights, png_doublep filter_weights,
+   png_doublep filter_costs)
+{
+   int i;
+
+   png_debug(1, "in png_set_filter_heuristics\n");
+   if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
+   {
+      png_warning(png_ptr, "Unknown filter heuristic method");
+      return;
+   }
+
+   if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT)
+   {
+      heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
+   }
+
+   if (num_weights < 0 || filter_weights == NULL ||
+      heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
+   {
+      num_weights = 0;
+   }
+
+   png_ptr->num_prev_filters = (png_byte)num_weights;
+   png_ptr->heuristic_method = (png_byte)heuristic_method;
+
+   if (num_weights > 0)
+   {
+      if (png_ptr->prev_filters == NULL)
+      {
+         png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
+            (png_uint_32)(sizeof(png_byte) * num_weights));
+
+         /* To make sure that the weighting starts out fairly */
+         for (i = 0; i < num_weights; i++)
+         {
+            png_ptr->prev_filters[i] = 255;
+         }
+      }
+
+      if (png_ptr->filter_weights == NULL)
+      {
+         png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
+            (png_uint_32)(sizeof(png_uint_16) * num_weights));
+
+         png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
+            (png_uint_32)(sizeof(png_uint_16) * num_weights));
+         for (i = 0; i < num_weights; i++)
+         {
+            png_ptr->inv_filter_weights[i] =
+            png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
+         }
+      }
+
+      for (i = 0; i < num_weights; i++)
+      {
+         if (filter_weights[i] < 0.0)
+         {
+            png_ptr->inv_filter_weights[i] =
+            png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
+         }
+         else
+         {
+            png_ptr->inv_filter_weights[i] =
+               (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5);
+            png_ptr->filter_weights[i] =
+               (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5);
+         }
+      }
+   }
+
+   /* If, in the future, there are other filter methods, this would
+    * need to be based on png_ptr->filter.
+    */
+   if (png_ptr->filter_costs == NULL)
+   {
+      png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
+         (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
+
+      png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
+         (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
+
+      for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
+      {
+         png_ptr->inv_filter_costs[i] =
+         png_ptr->filter_costs[i] = PNG_COST_FACTOR;
+      }
+   }
+
+   /* Here is where we set the relative costs of the different filters.  We
+    * should take the desired compression level into account when setting
+    * the costs, so that Paeth, for instance, has a high relative cost at low
+    * compression levels, while it has a lower relative cost at higher
+    * compression settings.  The filter types are in order of increasing
+    * relative cost, so it would be possible to do this with an algorithm.
+    */
+   for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
+   {
+      if (filter_costs == NULL || filter_costs[i] < 0.0)
+      {
+         png_ptr->inv_filter_costs[i] =
+         png_ptr->filter_costs[i] = PNG_COST_FACTOR;
+      }
+      else if (filter_costs[i] >= 1.0)
+      {
+         png_ptr->inv_filter_costs[i] =
+            (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5);
+         png_ptr->filter_costs[i] =
+            (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5);
+      }
+   }
+}
+#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+
+void PNGAPI
+png_set_compression_level(png_structp png_ptr, int level)
+{
+   png_debug(1, "in png_set_compression_level\n");
+   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
+   png_ptr->zlib_level = level;
+}
+
+void PNGAPI
+png_set_compression_mem_level(png_structp png_ptr, int mem_level)
+{
+   png_debug(1, "in png_set_compression_mem_level\n");
+   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
+   png_ptr->zlib_mem_level = mem_level;
+}
+
+void PNGAPI
+png_set_compression_strategy(png_structp png_ptr, int strategy)
+{
+   png_debug(1, "in png_set_compression_strategy\n");
+   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
+   png_ptr->zlib_strategy = strategy;
+}
+
+void PNGAPI
+png_set_compression_window_bits(png_structp png_ptr, int window_bits)
+{
+   if (window_bits > 15)
+      png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
+   else if (window_bits < 8)
+      png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
+#ifndef WBITS_8_OK
+   /* avoid libpng bug with 256-byte windows */
+   if (window_bits == 8)
+     {
+       png_warning(png_ptr, "Compression window is being reset to 512");
+       window_bits=9;
+     }
+#endif
+   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
+   png_ptr->zlib_window_bits = window_bits;
+}
+
+void PNGAPI
+png_set_compression_method(png_structp png_ptr, int method)
+{
+   png_debug(1, "in png_set_compression_method\n");
+   if (method != 8)
+      png_warning(png_ptr, "Only compression method 8 is supported by PNG");
+   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
+   png_ptr->zlib_method = method;
+}
+
+void PNGAPI
+png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
+{
+   png_ptr->write_row_fn = write_row_fn;
+}
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+void PNGAPI
+png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+   write_user_transform_fn)
+{
+   png_debug(1, "in png_set_write_user_transform_fn\n");
+   png_ptr->transformations |= PNG_USER_TRANSFORM;
+   png_ptr->write_user_transform_fn = write_user_transform_fn;
+}
+#endif
+
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED)
+void PNGAPI
+png_write_png(png_structp png_ptr, png_infop info_ptr,
+              int transforms, voidp params)
+{
+#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+   /* invert the alpha channel from opacity to transparency */
+   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+       png_set_invert_alpha(png_ptr);
+#endif
+
+   /* Write the file header information. */
+   png_write_info(png_ptr, info_ptr);
+
+   /* ------ these transformations don't touch the info structure ------- */
+
+#if defined(PNG_WRITE_INVERT_SUPPORTED)
+   /* invert monochrome pixels */
+   if (transforms & PNG_TRANSFORM_INVERT_MONO)
+       png_set_invert_mono(png_ptr);
+#endif
+
+#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+   /* Shift the pixels up to a legal bit depth and fill in
+    * as appropriate to correctly scale the image.
+    */
+   if ((transforms & PNG_TRANSFORM_SHIFT)
+               && (info_ptr->valid & PNG_INFO_sBIT))
+       png_set_shift(png_ptr, &info_ptr->sig_bit);
+#endif
+
+#if defined(PNG_WRITE_PACK_SUPPORTED)
+   /* pack pixels into bytes */
+   if (transforms & PNG_TRANSFORM_PACKING)
+       png_set_packing(png_ptr);
+#endif
+
+#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+   /* swap location of alpha bytes from ARGB to RGBA */
+   if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+       png_set_swap_alpha(png_ptr);
+#endif
+
+#if defined(PNG_WRITE_FILLER_SUPPORTED)
+   /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
+    * RGB (4 channels -> 3 channels). The second parameter is not used.
+    */
+   if (transforms & PNG_TRANSFORM_STRIP_FILLER)
+       png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+#endif
+
+#if defined(PNG_WRITE_BGR_SUPPORTED)
+   /* flip BGR pixels to RGB */
+   if (transforms & PNG_TRANSFORM_BGR)
+       png_set_bgr(png_ptr);
+#endif
+
+#if defined(PNG_WRITE_SWAP_SUPPORTED)
+   /* swap bytes of 16-bit files to most significant byte first */
+   if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+       png_set_swap(png_ptr);
+#endif
+
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+   /* swap bits of 1, 2, 4 bit packed pixel formats */
+   if (transforms & PNG_TRANSFORM_PACKSWAP)
+       png_set_packswap(png_ptr);
+#endif
+
+   /* ----------------------- end of transformations ------------------- */
+
+   /* write the bits */
+   if (info_ptr->valid & PNG_INFO_IDAT)
+       png_write_image(png_ptr, info_ptr->row_pointers);
+
+   /* It is REQUIRED to call this to finish writing the rest of the file */
+   png_write_end(png_ptr, info_ptr);
+
+   if(transforms == 0 || params == NULL)
+      /* quiet compiler warnings */ return;
+}
+#endif
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/libraries/libpng-1.2.0/pngwtran.c b/libraries/libpng-1.2.0/pngwtran.c
new file mode 100644 (file)
index 0000000..7a38b9c
--- /dev/null
@@ -0,0 +1,563 @@
+
+/* pngwtran.c - transforms the data in a row for PNG writers
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Transform the data according to the user's wishes.  The order of
+ * transformations is significant.
+ */
+void /* PRIVATE */
+png_do_write_transformations(png_structp png_ptr)
+{
+   png_debug(1, "in png_do_write_transformations\n");
+
+   if (png_ptr == NULL)
+      return;
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+   if (png_ptr->transformations & PNG_USER_TRANSFORM)
+      if(png_ptr->write_user_transform_fn != NULL)
+        (*(png_ptr->write_user_transform_fn)) /* user write transform function */
+          (png_ptr,                    /* png_ptr */
+           &(png_ptr->row_info),       /* row_info:     */
+             /*  png_uint_32 width;          width of row */
+             /*  png_uint_32 rowbytes;       number of bytes in row */
+             /*  png_byte color_type;        color type of pixels */
+             /*  png_byte bit_depth;         bit depth of samples */
+             /*  png_byte channels;          number of channels (1-4) */
+             /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
+           png_ptr->row_buf + 1);      /* start of pixel data for row */
+#endif
+#if defined(PNG_WRITE_FILLER_SUPPORTED)
+   if (png_ptr->transformations & PNG_FILLER)
+      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         png_ptr->flags);
+#endif
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACKSWAP)
+      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#if defined(PNG_WRITE_PACK_SUPPORTED)
+   if (png_ptr->transformations & PNG_PACK)
+      png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         (png_uint_32)png_ptr->bit_depth);
+#endif
+#if defined(PNG_WRITE_SWAP_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_BYTES)
+      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+   if (png_ptr->transformations & PNG_SHIFT)
+      png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
+         &(png_ptr->shift));
+#endif
+#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_ALPHA)
+      png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+   if (png_ptr->transformations & PNG_SWAP_ALPHA)
+      png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#if defined(PNG_WRITE_BGR_SUPPORTED)
+   if (png_ptr->transformations & PNG_BGR)
+      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#if defined(PNG_WRITE_INVERT_SUPPORTED)
+   if (png_ptr->transformations & PNG_INVERT_MONO)
+      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+}
+
+#if defined(PNG_WRITE_PACK_SUPPORTED)
+/* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
+ * row_info bit depth should be 8 (one pixel per byte).  The channels
+ * should be 1 (this only happens on grayscale and paletted images).
+ */
+void /* PRIVATE */
+png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
+{
+   png_debug(1, "in png_do_pack\n");
+   if (row_info->bit_depth == 8 &&
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+      row_info->channels == 1)
+   {
+      switch ((int)bit_depth)
+      {
+         case 1:
+         {
+            png_bytep sp, dp;
+            int mask, v;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            sp = row;
+            dp = row;
+            mask = 0x80;
+            v = 0;
+
+            for (i = 0; i < row_width; i++)
+            {
+               if (*sp != 0)
+                  v |= mask;
+               sp++;
+               if (mask > 1)
+                  mask >>= 1;
+               else
+               {
+                  mask = 0x80;
+                  *dp = (png_byte)v;
+                  dp++;
+                  v = 0;
+               }
+            }
+            if (mask != 0x80)
+               *dp = (png_byte)v;
+            break;
+         }
+         case 2:
+         {
+            png_bytep sp, dp;
+            int shift, v;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            sp = row;
+            dp = row;
+            shift = 6;
+            v = 0;
+            for (i = 0; i < row_width; i++)
+            {
+               png_byte value;
+
+               value = (png_byte)(*sp & 0x03);
+               v |= (value << shift);
+               if (shift == 0)
+               {
+                  shift = 6;
+                  *dp = (png_byte)v;
+                  dp++;
+                  v = 0;
+               }
+               else
+                  shift -= 2;
+               sp++;
+            }
+            if (shift != 6)
+               *dp = (png_byte)v;
+            break;
+         }
+         case 4:
+         {
+            png_bytep sp, dp;
+            int shift, v;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            sp = row;
+            dp = row;
+            shift = 4;
+            v = 0;
+            for (i = 0; i < row_width; i++)
+            {
+               png_byte value;
+
+               value = (png_byte)(*sp & 0x0f);
+               v |= (value << shift);
+
+               if (shift == 0)
+               {
+                  shift = 4;
+                  *dp = (png_byte)v;
+                  dp++;
+                  v = 0;
+               }
+               else
+                  shift -= 4;
+
+               sp++;
+            }
+            if (shift != 4)
+               *dp = (png_byte)v;
+            break;
+         }
+      }
+      row_info->bit_depth = (png_byte)bit_depth;
+      row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
+      row_info->rowbytes =
+         ((row_info->width * row_info->pixel_depth + 7) >> 3);
+   }
+}
+#endif
+
+#if defined(PNG_WRITE_SHIFT_SUPPORTED)
+/* Shift pixel values to take advantage of whole range.  Pass the
+ * true number of bits in bit_depth.  The row should be packed
+ * according to row_info->bit_depth.  Thus, if you had a row of
+ * bit depth 4, but the pixels only had values from 0 to 7, you
+ * would pass 3 as bit_depth, and this routine would translate the
+ * data to 0 to 15.
+ */
+void /* PRIVATE */
+png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
+{
+   png_debug(1, "in png_do_shift\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL &&
+#else
+   if (
+#endif
+      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
+   {
+      int shift_start[4], shift_dec[4];
+      int channels = 0;
+
+      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+      {
+         shift_start[channels] = row_info->bit_depth - bit_depth->red;
+         shift_dec[channels] = bit_depth->red;
+         channels++;
+         shift_start[channels] = row_info->bit_depth - bit_depth->green;
+         shift_dec[channels] = bit_depth->green;
+         channels++;
+         shift_start[channels] = row_info->bit_depth - bit_depth->blue;
+         shift_dec[channels] = bit_depth->blue;
+         channels++;
+      }
+      else
+      {
+         shift_start[channels] = row_info->bit_depth - bit_depth->gray;
+         shift_dec[channels] = bit_depth->gray;
+         channels++;
+      }
+      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+      {
+         shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
+         shift_dec[channels] = bit_depth->alpha;
+         channels++;
+      }
+
+      /* with low row depths, could only be grayscale, so one channel */
+      if (row_info->bit_depth < 8)
+      {
+         png_bytep bp = row;
+         png_uint_32 i;
+         png_byte mask;
+         png_uint_32 row_bytes = row_info->rowbytes;
+
+         if (bit_depth->gray == 1 && row_info->bit_depth == 2)
+            mask = 0x55;
+         else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
+            mask = 0x11;
+         else
+            mask = 0xff;
+
+         for (i = 0; i < row_bytes; i++, bp++)
+         {
+            png_uint_16 v;
+            int j;
+
+            v = *bp;
+            *bp = 0;
+            for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
+            {
+               if (j > 0)
+                  *bp |= (png_byte)((v << j) & 0xff);
+               else
+                  *bp |= (png_byte)((v >> (-j)) & mask);
+            }
+         }
+      }
+      else if (row_info->bit_depth == 8)
+      {
+         png_bytep bp = row;
+         png_uint_32 i;
+         png_uint_32 istop = channels * row_info->width;
+
+         for (i = 0; i < istop; i++, bp++)
+         {
+
+            png_uint_16 v;
+            int j;
+            int c = (int)(i%channels);
+
+            v = *bp;
+            *bp = 0;
+            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
+            {
+               if (j > 0)
+                  *bp |= (png_byte)((v << j) & 0xff);
+               else
+                  *bp |= (png_byte)((v >> (-j)) & 0xff);
+            }
+         }
+      }
+      else
+      {
+         png_bytep bp;
+         png_uint_32 i;
+         png_uint_32 istop = channels * row_info->width;
+
+         for (bp = row, i = 0; i < istop; i++)
+         {
+            int c = (int)(i%channels);
+            png_uint_16 value, v;
+            int j;
+
+            v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
+            value = 0;
+            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
+            {
+               if (j > 0)
+                  value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
+               else
+                  value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
+            }
+            *bp++ = (png_byte)(value >> 8);
+            *bp++ = (png_byte)(value & 0xff);
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+void /* PRIVATE */
+png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_write_swap_alpha\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         /* This converts from ARGB to RGBA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               png_byte save = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = save;
+            }
+         }
+         /* This converts from AARRGGBB to RRGGBBAA */
+         else
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               png_byte save[2];
+               save[0] = *(sp++);
+               save[1] = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = save[0];
+               *(dp++) = save[1];
+            }
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         /* This converts from AG to GA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               png_byte save = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = save;
+            }
+         }
+         /* This converts from AAGG to GGAA */
+         else
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               png_byte save[2];
+               save[0] = *(sp++);
+               save[1] = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = save[0];
+               *(dp++) = save[1];
+            }
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+void /* PRIVATE */
+png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_write_invert_alpha\n");
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL)
+#endif
+   {
+      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+      {
+         /* This inverts the alpha channel in RGBA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = (png_byte)(255 - *(sp++));
+            }
+         }
+         /* This inverts the alpha channel in RRGGBBAA */
+         else
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = (png_byte)(255 - *(sp++));
+               *(dp++) = (png_byte)(255 - *(sp++));
+            }
+         }
+      }
+      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+      {
+         /* This inverts the alpha channel in GA */
+         if (row_info->bit_depth == 8)
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               *(dp++) = *(sp++);
+               *(dp++) = (png_byte)(255 - *(sp++));
+            }
+         }
+         /* This inverts the alpha channel in GGAA */
+         else
+         {
+            png_bytep sp, dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            for (i = 0, sp = dp = row; i < row_width; i++)
+            {
+               *(dp++) = *(sp++);
+               *(dp++) = *(sp++);
+               *(dp++) = (png_byte)(255 - *(sp++));
+               *(dp++) = (png_byte)(255 - *(sp++));
+            }
+         }
+      }
+   }
+}
+#endif
+
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+/* undoes intrapixel differencing  */
+void /* PRIVATE */
+png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
+{
+   png_debug(1, "in png_do_write_intrapixel\n");
+   if (
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+       row != NULL && row_info != NULL &&
+#endif
+       (row_info->color_type & PNG_COLOR_MASK_COLOR))
+   {
+      int bytes_per_pixel;
+      png_uint_32 row_width = row_info->width;
+      if (row_info->bit_depth == 8)
+      {
+         png_bytep rp;
+         png_uint_32 i;
+
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+            bytes_per_pixel = 3;
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+            bytes_per_pixel = 4;
+         else
+            return;
+
+         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+         {
+            *(rp)   = (png_byte)((*rp     - *(rp+1))&0xff);
+            *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
+         }
+      }
+      else if (row_info->bit_depth == 16)
+      {
+         png_bytep rp;
+         png_uint_32 i;
+
+         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+            bytes_per_pixel = 6;
+         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+            bytes_per_pixel = 8;
+         else
+            return;
+
+         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+         {
+            png_uint_32 s0=*(rp  )<<8 | *(rp+1);
+            png_uint_32 s1=*(rp+2)<<8 | *(rp+3);
+            png_uint_32 s2=*(rp+4)<<8 | *(rp+5);
+            png_uint_32 red=(s0-s1)&0xffff;
+            png_uint_32 blue=(s2-s1)&0xffff;
+            *(rp  ) = (png_byte)((red>>8)&0xff);
+            *(rp+1) = (png_byte)(red&0xff);
+            *(rp+4) = (png_byte)((blue>>8)&0xff);
+            *(rp+5) = (png_byte)(blue&0xff);
+         }
+      }
+   }
+}
+#endif /* PNG_MNG_FEATURES_SUPPORTED */
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/libraries/libpng-1.2.0/pngwutil.c b/libraries/libpng-1.2.0/pngwutil.c
new file mode 100644 (file)
index 0000000..5613a1f
--- /dev/null
@@ -0,0 +1,2668 @@
+
+/* pngwutil.c - utilities to write a PNG file
+ *
+ * libpng 1.2.0 - September 1, 2001
+ * For conditions of distribution and use, see copyright notice in png.h
+ * Copyright (c) 1998-2001 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+#define PNG_INTERNAL
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Place a 32-bit number into a buffer in PNG byte order.  We work
+ * with unsigned numbers for convenience, although one supported
+ * ancillary chunk uses signed (two's complement) numbers.
+ */
+void /* PRIVATE */
+png_save_uint_32(png_bytep buf, png_uint_32 i)
+{
+   buf[0] = (png_byte)((i >> 24) & 0xff);
+   buf[1] = (png_byte)((i >> 16) & 0xff);
+   buf[2] = (png_byte)((i >> 8) & 0xff);
+   buf[3] = (png_byte)(i & 0xff);
+}
+
+#if defined(PNG_WRITE_pCAL_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED)
+/* The png_save_int_32 function assumes integers are stored in two's
+ * complement format.  If this isn't the case, then this routine needs to
+ * be modified to write data in two's complement format.
+ */
+void /* PRIVATE */
+png_save_int_32(png_bytep buf, png_int_32 i)
+{
+   buf[0] = (png_byte)((i >> 24) & 0xff);
+   buf[1] = (png_byte)((i >> 16) & 0xff);
+   buf[2] = (png_byte)((i >> 8) & 0xff);
+   buf[3] = (png_byte)(i & 0xff);
+}
+#endif
+
+/* Place a 16-bit number into a buffer in PNG byte order.
+ * The parameter is declared unsigned int, not png_uint_16,
+ * just to avoid potential problems on pre-ANSI C compilers.
+ */
+void /* PRIVATE */
+png_save_uint_16(png_bytep buf, unsigned int i)
+{
+   buf[0] = (png_byte)((i >> 8) & 0xff);
+   buf[1] = (png_byte)(i & 0xff);
+}
+
+/* Write a PNG chunk all at once.  The type is an array of ASCII characters
+ * representing the chunk name.  The array must be at least 4 bytes in
+ * length, and does not need to be null terminated.  To be safe, pass the
+ * pre-defined chunk names here, and if you need a new one, define it
+ * where the others are defined.  The length is the length of the data.
+ * All the data must be present.  If that is not possible, use the
+ * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
+ * functions instead.
+ */
+void PNGAPI
+png_write_chunk(png_structp png_ptr, png_bytep chunk_name,
+   png_bytep data, png_size_t length)
+{
+   png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
+   png_write_chunk_data(png_ptr, data, length);
+   png_write_chunk_end(png_ptr);
+}
+
+/* Write the start of a PNG chunk.  The type is the chunk type.
+ * The total_length is the sum of the lengths of all the data you will be
+ * passing in png_write_chunk_data().
+ */
+void PNGAPI
+png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name,
+   png_uint_32 length)
+{
+   png_byte buf[4];
+   png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length);
+
+   /* write the length */
+   png_save_uint_32(buf, length);
+   png_write_data(png_ptr, buf, (png_size_t)4);
+
+   /* write the chunk name */
+   png_write_data(png_ptr, chunk_name, (png_size_t)4);
+   /* reset the crc and run it over the chunk name */
+   png_reset_crc(png_ptr);
+   png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
+}
+
+/* Write the data of a PNG chunk started with png_write_chunk_start().
+ * Note that multiple calls to this function are allowed, and that the
+ * sum of the lengths from these calls *must* add up to the total_length
+ * given to png_write_chunk_start().
+ */
+void PNGAPI
+png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+   /* write the data, and run the CRC over it */
+   if (data != NULL && length > 0)
+   {
+      png_calculate_crc(png_ptr, data, length);
+      png_write_data(png_ptr, data, length);
+   }
+}
+
+/* Finish a chunk started with png_write_chunk_start(). */
+void PNGAPI
+png_write_chunk_end(png_structp png_ptr)
+{
+   png_byte buf[4];
+
+   /* write the crc */
+   png_save_uint_32(buf, png_ptr->crc);
+
+   png_write_data(png_ptr, buf, (png_size_t)4);
+}
+
+/* Simple function to write the signature.  If we have already written
+ * the magic bytes of the signature, or more likely, the PNG stream is
+ * being embedded into another stream and doesn't need its own signature,
+ * we should call png_set_sig_bytes() to tell libpng how many of the
+ * bytes have already been written.
+ */
+void /* PRIVATE */
+png_write_sig(png_structp png_ptr)
+{
+   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+   /* write the rest of the 8 byte signature */
+   png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
+      (png_size_t)8 - png_ptr->sig_bytes);
+   if(png_ptr->sig_bytes < 3)
+      png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
+}
+
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED)
+/*
+ * This pair of functions encapsulates the operation of (a) compressing a
+ * text string, and (b) issuing it later as a series of chunk data writes.
+ * The compression_state structure is shared context for these functions
+ * set up by the caller in order to make the whole mess thread-safe.
+ */
+
+typedef struct
+{
+    char *input;   /* the uncompressed input data */
+    int input_len;   /* its length */
+    int num_output_ptr; /* number of output pointers used */
+    int max_output_ptr; /* size of output_ptr */
+    png_charpp output_ptr; /* array of pointers to output */
+} compression_state;
+
+/* compress given text into storage in the png_ptr structure */
+static int /* PRIVATE */
+png_text_compress(png_structp png_ptr,
+        png_charp text, png_size_t text_len, int compression,
+        compression_state *comp)
+{
+   int ret;
+
+   comp->num_output_ptr = comp->max_output_ptr = 0;
+   comp->output_ptr = NULL;
+   comp->input = NULL;
+
+   /* we may just want to pass the text right through */
+   if (compression == PNG_TEXT_COMPRESSION_NONE)
+   {
+       comp->input = text;
+       comp->input_len = text_len;
+       return((int)text_len);
+   }
+
+   if (compression >= PNG_TEXT_COMPRESSION_LAST)
+   {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+      char msg[50];
+      sprintf(msg, "Unknown compression type %d", compression);
+      png_warning(png_ptr, msg);
+#else
+      png_warning(png_ptr, "Unknown compression type");
+#endif
+   }
+
+   /* We can't write the chunk until we find out how much data we have,
+    * which means we need to run the compressor first and save the
+    * output.  This shouldn't be a problem, as the vast majority of
+    * comments should be reasonable, but we will set up an array of
+    * malloc'd pointers to be sure.
+    *
+    * If we knew the application was well behaved, we could simplify this
+    * greatly by assuming we can always malloc an output buffer large
+    * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
+    * and malloc this directly.  The only time this would be a bad idea is
+    * if we can't malloc more than 64K and we have 64K of random input
+    * data, or if the input string is incredibly large (although this
+    * wouldn't cause a failure, just a slowdown due to swapping).
+    */
+
+   /* set up the compression buffers */
+   png_ptr->zstream.avail_in = (uInt)text_len;
+   png_ptr->zstream.next_in = (Bytef *)text;
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+   png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
+
+   /* this is the same compression loop as in png_write_row() */
+   do
+   {
+      /* compress the data */
+      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
+      if (ret != Z_OK)
+      {
+         /* error */
+         if (png_ptr->zstream.msg != NULL)
+            png_error(png_ptr, png_ptr->zstream.msg);
+         else
+            png_error(png_ptr, "zlib error");
+      }
+      /* check to see if we need more room */
+      if (!png_ptr->zstream.avail_out && png_ptr->zstream.avail_in)
+      {
+         /* make sure the output array has room */
+         if (comp->num_output_ptr >= comp->max_output_ptr)
+         {
+            int old_max;
+
+            old_max = comp->max_output_ptr;
+            comp->max_output_ptr = comp->num_output_ptr + 4;
+            if (comp->output_ptr != NULL)
+            {
+               png_charpp old_ptr;
+
+               old_ptr = comp->output_ptr;
+               comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+                  (png_uint_32)(comp->max_output_ptr * sizeof (png_charpp)));
+               png_memcpy(comp->output_ptr, old_ptr, old_max
+                  * sizeof (png_charp));
+               png_free(png_ptr, old_ptr);
+            }
+            else
+               comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+                  (png_uint_32)(comp->max_output_ptr * sizeof (png_charp)));
+         }
+
+         /* save the data */
+         comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr,
+            (png_uint_32)png_ptr->zbuf_size);
+         png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
+            png_ptr->zbuf_size);
+         comp->num_output_ptr++;
+
+         /* and reset the buffer */
+         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+         png_ptr->zstream.next_out = png_ptr->zbuf;
+      }
+   /* continue until we don't have any more to compress */
+   } while (png_ptr->zstream.avail_in);
+
+   /* finish the compression */
+   do
+   {
+      /* tell zlib we are finished */
+      ret = deflate(&png_ptr->zstream, Z_FINISH);
+
+      if (ret == Z_OK)
+      {
+         /* check to see if we need more room */
+         if (!(png_ptr->zstream.avail_out))
+         {
+            /* check to make sure our output array has room */
+            if (comp->num_output_ptr >= comp->max_output_ptr)
+            {
+               int old_max;
+
+               old_max = comp->max_output_ptr;
+               comp->max_output_ptr = comp->num_output_ptr + 4;
+               if (comp->output_ptr != NULL)
+               {
+                  png_charpp old_ptr;
+
+                  old_ptr = comp->output_ptr;
+                  /* This could be optimized to realloc() */
+                  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+                     (png_uint_32)(comp->max_output_ptr * sizeof (png_charpp)));
+                  png_memcpy(comp->output_ptr, old_ptr,
+                     old_max * sizeof (png_charp));
+                  png_free(png_ptr, old_ptr);
+               }
+               else
+                  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+                     (png_uint_32)(comp->max_output_ptr * sizeof (png_charp)));
+            }
+
+            /* save off the data */
+            comp->output_ptr[comp->num_output_ptr] =
+               (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size);
+            png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
+               png_ptr->zbuf_size);
+            comp->num_output_ptr++;
+
+            /* and reset the buffer pointers */
+            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+            png_ptr->zstream.next_out = png_ptr->zbuf;
+         }
+      }
+      else if (ret != Z_STREAM_END)
+      {
+         /* we got an error */
+         if (png_ptr->zstream.msg != NULL)
+            png_error(png_ptr, png_ptr->zstream.msg);
+         else
+            png_error(png_ptr, "zlib error");
+      }
+   } while (ret != Z_STREAM_END);
+
+   /* text length is number of buffers plus last buffer */
+   text_len = png_ptr->zbuf_size * comp->num_output_ptr;
+   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
+      text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
+
+   return((int)text_len);
+}
+
+/* ship the compressed text out via chunk writes */
+static void /* PRIVATE */
+png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
+{
+   int i;
+
+   /* handle the no-compression case */
+   if (comp->input)
+   {
+       png_write_chunk_data(png_ptr, (png_bytep)comp->input,
+                            (png_size_t)comp->input_len);
+       return;
+   }
+
+   /* write saved output buffers, if any */
+   for (i = 0; i < comp->num_output_ptr; i++)
+   {
+      png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i],
+         png_ptr->zbuf_size);
+      png_free(png_ptr, comp->output_ptr[i]);
+      comp->output_ptr[i]=NULL;
+   }
+   if (comp->max_output_ptr != 0)
+      png_free(png_ptr, comp->output_ptr);
+      comp->output_ptr=NULL;
+   /* write anything left in zbuf */
+   if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
+      png_write_chunk_data(png_ptr, png_ptr->zbuf,
+         png_ptr->zbuf_size - png_ptr->zstream.avail_out);
+
+   /* reset zlib for another zTXt/iTXt or the image data */
+   deflateReset(&png_ptr->zstream);
+
+}
+#endif
+
+/* Write the IHDR chunk, and update the png_struct with the necessary
+ * information.  Note that the rest of this code depends upon this
+ * information being correct.
+ */
+void /* PRIVATE */
+png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
+   int bit_depth, int color_type, int compression_type, int filter_type,
+   int interlace_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_IHDR;
+#endif
+   png_byte buf[13]; /* buffer to store the IHDR info */
+
+   png_debug(1, "in png_write_IHDR\n");
+   /* Check that we have valid input data from the application info */
+   switch (color_type)
+   {
+      case PNG_COLOR_TYPE_GRAY:
+         switch (bit_depth)
+         {
+            case 1:
+            case 2:
+            case 4:
+            case 8:
+            case 16: png_ptr->channels = 1; break;
+            default: png_error(png_ptr,"Invalid bit depth for grayscale image");
+         }
+         break;
+      case PNG_COLOR_TYPE_RGB:
+         if (bit_depth != 8 && bit_depth != 16)
+            png_error(png_ptr, "Invalid bit depth for RGB image");
+         png_ptr->channels = 3;
+         break;
+      case PNG_COLOR_TYPE_PALETTE:
+         switch (bit_depth)
+         {
+            case 1:
+            case 2:
+            case 4:
+            case 8: png_ptr->channels = 1; break;
+            default: png_error(png_ptr, "Invalid bit depth for paletted image");
+         }
+         break;
+      case PNG_COLOR_TYPE_GRAY_ALPHA:
+         if (bit_depth != 8 && bit_depth != 16)
+            png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
+         png_ptr->channels = 2;
+         break;
+      case PNG_COLOR_TYPE_RGB_ALPHA:
+         if (bit_depth != 8 && bit_depth != 16)
+            png_error(png_ptr, "Invalid bit depth for RGBA image");
+         png_ptr->channels = 4;
+         break;
+      default:
+         png_error(png_ptr, "Invalid image color type specified");
+   }
+
+   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+   {
+      png_warning(png_ptr, "Invalid compression type specified");
+      compression_type = PNG_COMPRESSION_TYPE_BASE;
+   }
+
+   /* Write filter_method 64 (intrapixel differencing) only if
+    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+    * 2. Libpng did not write a PNG signature (this filter_method is only
+    *    used in PNG datastreams that are embedded in MNG datastreams) and
+    * 3. The application called png_permit_mng_features with a mask that
+    *    included PNG_FLAG_MNG_FILTER_64 and
+    * 4. The filter_method is 64 and
+    * 5. The color_type is RGB or RGBA
+    */
+   if (
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+      !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+      ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
+      (color_type == PNG_COLOR_TYPE_RGB ||
+       color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
+      (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
+#endif
+      filter_type != PNG_FILTER_TYPE_BASE)
+   {
+      png_warning(png_ptr, "Invalid filter type specified");
+      filter_type = PNG_FILTER_TYPE_BASE;
+   }
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+   if (interlace_type != PNG_INTERLACE_NONE &&
+      interlace_type != PNG_INTERLACE_ADAM7)
+   {
+      png_warning(png_ptr, "Invalid interlace type specified");
+      interlace_type = PNG_INTERLACE_ADAM7;
+   }
+#else
+   interlace_type=PNG_INTERLACE_NONE;
+#endif
+
+   /* save off the relevent information */
+   png_ptr->bit_depth = (png_byte)bit_depth;
+   png_ptr->color_type = (png_byte)color_type;
+   png_ptr->interlaced = (png_byte)interlace_type;
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+   png_ptr->filter_type = (png_byte)filter_type;
+#endif
+   png_ptr->width = width;
+   png_ptr->height = height;
+
+   png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
+   png_ptr->rowbytes = ((width * (png_size_t)png_ptr->pixel_depth + 7) >> 3);
+   /* set the usr info, so any transformations can modify it */
+   png_ptr->usr_width = png_ptr->width;
+   png_ptr->usr_bit_depth = png_ptr->bit_depth;
+   png_ptr->usr_channels = png_ptr->channels;
+
+   /* pack the header information into the buffer */
+   png_save_uint_32(buf, width);
+   png_save_uint_32(buf + 4, height);
+   buf[8] = (png_byte)bit_depth;
+   buf[9] = (png_byte)color_type;
+   buf[10] = (png_byte)compression_type;
+   buf[11] = (png_byte)filter_type;
+   buf[12] = (png_byte)interlace_type;
+
+   /* write the chunk */
+   png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13);
+
+   /* initialize zlib with PNG info */
+   png_ptr->zstream.zalloc = png_zalloc;
+   png_ptr->zstream.zfree = png_zfree;
+   png_ptr->zstream.opaque = (voidpf)png_ptr;
+   if (!(png_ptr->do_filter))
+   {
+      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
+         png_ptr->bit_depth < 8)
+         png_ptr->do_filter = PNG_FILTER_NONE;
+      else
+         png_ptr->do_filter = PNG_ALL_FILTERS;
+   }
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
+   {
+      if (png_ptr->do_filter != PNG_FILTER_NONE)
+         png_ptr->zlib_strategy = Z_FILTERED;
+      else
+         png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
+   }
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
+      png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
+      png_ptr->zlib_mem_level = 8;
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
+      png_ptr->zlib_window_bits = 15;
+   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
+      png_ptr->zlib_method = 8;
+   deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
+      png_ptr->zlib_method, png_ptr->zlib_window_bits,
+      png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
+   png_ptr->zstream.next_out = png_ptr->zbuf;
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+   png_ptr->mode = PNG_HAVE_IHDR;
+}
+
+/* write the palette.  We are careful not to trust png_color to be in the
+ * correct order for PNG, so people can redefine it to any convenient
+ * structure.
+ */
+void /* PRIVATE */
+png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_PLTE;
+#endif
+   png_uint_32 i;
+   png_colorp pal_ptr;
+   png_byte buf[3];
+
+   png_debug(1, "in png_write_PLTE\n");
+   if ((
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+        !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
+#endif
+        num_pal == 0) || num_pal > 256)
+   {
+     if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+     {
+        png_error(png_ptr, "Invalid number of colors in palette");
+     }
+     else
+     {
+        png_warning(png_ptr, "Invalid number of colors in palette");
+        return;
+     }
+   }
+
+   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+   {
+      png_warning(png_ptr,
+        "Ignoring request to write a PLTE chunk in grayscale PNG");
+      return;
+   }
+
+   png_ptr->num_palette = (png_uint_16)num_pal;
+   png_debug1(3, "num_palette = %d\n", png_ptr->num_palette);
+
+   png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, num_pal * 3);
+#ifndef PNG_NO_POINTER_INDEXING
+   for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
+   {
+      buf[0] = pal_ptr->red;
+      buf[1] = pal_ptr->green;
+      buf[2] = pal_ptr->blue;
+      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
+   }
+#else
+   /* This is a little slower but some buggy compilers need to do this instead */
+   pal_ptr=palette;
+   for (i = 0; i < num_pal; i++)
+   {
+      buf[0] = pal_ptr[i].red;
+      buf[1] = pal_ptr[i].green;
+      buf[2] = pal_ptr[i].blue;
+      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
+   }
+#endif
+   png_write_chunk_end(png_ptr);
+   png_ptr->mode |= PNG_HAVE_PLTE;
+}
+
+/* write an IDAT chunk */
+void /* PRIVATE */
+png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_IDAT;
+#endif
+   png_debug(1, "in png_write_IDAT\n");
+   png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
+   png_ptr->mode |= PNG_HAVE_IDAT;
+}
+
+/* write an IEND chunk */
+void /* PRIVATE */
+png_write_IEND(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_IEND;
+#endif
+   png_debug(1, "in png_write_IEND\n");
+   png_write_chunk(png_ptr, (png_bytep)png_IEND, NULL, (png_size_t)0);
+   png_ptr->mode |= PNG_HAVE_IEND;
+}
+
+#if defined(PNG_WRITE_gAMA_SUPPORTED)
+/* write a gAMA chunk */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_gAMA(png_structp png_ptr, double file_gamma)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_gAMA;
+#endif
+   png_uint_32 igamma;
+   png_byte buf[4];
+
+   png_debug(1, "in png_write_gAMA\n");
+   /* file_gamma is saved in 1/100,000ths */
+   igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
+   png_save_uint_32(buf, igamma);
+   png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_gAMA;
+#endif
+   png_byte buf[4];
+
+   png_debug(1, "in png_write_gAMA\n");
+   /* file_gamma is saved in 1/100,000ths */
+   png_save_uint_32(buf, (png_uint_32)file_gamma);
+   png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
+}
+#endif
+#endif
+
+#if defined(PNG_WRITE_sRGB_SUPPORTED)
+/* write a sRGB chunk */
+void /* PRIVATE */
+png_write_sRGB(png_structp png_ptr, int srgb_intent)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_sRGB;
+#endif
+   png_byte buf[1];
+
+   png_debug(1, "in png_write_sRGB\n");
+   if(srgb_intent >= PNG_sRGB_INTENT_LAST)
+         png_warning(png_ptr,
+            "Invalid sRGB rendering intent specified");
+   buf[0]=(png_byte)srgb_intent;
+   png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1);
+}
+#endif
+
+#if defined(PNG_WRITE_iCCP_SUPPORTED)
+/* write an iCCP chunk */
+void /* PRIVATE */
+png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
+   png_charp profile, int profile_len)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_iCCP;
+#endif
+   png_size_t name_len;
+   png_charp new_name;
+   compression_state comp;
+
+   png_debug(1, "in png_write_iCCP\n");
+   if (name == NULL || (name_len = png_check_keyword(png_ptr, name,
+      &new_name)) == 0)
+   {
+      png_warning(png_ptr, "Empty keyword in iCCP chunk");
+      return;
+   }
+
+   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+      png_warning(png_ptr, "Unknown compression type in iCCP chunk");
+
+   if (profile == NULL)
+      profile_len = 0;
+
+   if (profile_len)
+       profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len,
+          PNG_COMPRESSION_TYPE_BASE, &comp);
+
+   /* make sure we include the NULL after the name and the compression type */
+   png_write_chunk_start(png_ptr, (png_bytep)png_iCCP,
+          (png_uint_32)name_len+profile_len+2);
+   new_name[name_len+1]=0x00;
+   png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2);
+
+   if (profile_len)
+      png_write_compressed_data_out(png_ptr, &comp);
+
+   png_write_chunk_end(png_ptr);
+   png_free(png_ptr, new_name);
+}
+#endif
+
+#if defined(PNG_WRITE_sPLT_SUPPORTED)
+/* write a sPLT chunk */
+void /* PRIVATE */
+png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_sPLT;
+#endif
+   png_size_t name_len;
+   png_charp new_name;
+   png_byte entrybuf[10];
+   int entry_size = (spalette->depth == 8 ? 6 : 10);
+   int palette_size = entry_size * spalette->nentries;
+   png_sPLT_entryp ep;
+#ifdef PNG_NO_POINTER_INDEXING
+   int i;
+#endif
+
+   png_debug(1, "in png_write_sPLT\n");
+   if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr,
+      spalette->name, &new_name))==0)
+   {
+      png_warning(png_ptr, "Empty keyword in sPLT chunk");
+      return;
+   }
+
+   /* make sure we include the NULL after the name */
+   png_write_chunk_start(png_ptr, (png_bytep)png_sPLT,
+          (png_uint_32)(name_len + 2 + palette_size));
+   png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1);
+   png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1);
+
+   /* loop through each palette entry, writing appropriately */
+#ifndef PNG_NO_POINTER_INDEXING
+   for (ep = spalette->entries; ep<spalette->entries+spalette->nentries; ep++)
+   {
+       if (spalette->depth == 8)
+       {
+           entrybuf[0] = (png_byte)ep->red;
+           entrybuf[1] = (png_byte)ep->green;
+           entrybuf[2] = (png_byte)ep->blue;
+           entrybuf[3] = (png_byte)ep->alpha;
+           png_save_uint_16(entrybuf + 4, ep->frequency);
+       }
+       else
+       {
+           png_save_uint_16(entrybuf + 0, ep->red);
+           png_save_uint_16(entrybuf + 2, ep->green);
+           png_save_uint_16(entrybuf + 4, ep->blue);
+           png_save_uint_16(entrybuf + 6, ep->alpha);
+           png_save_uint_16(entrybuf + 8, ep->frequency);
+       }
+       png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
+   }
+#else
+   ep=spalette->entries;
+   for (i=0; i>spalette->nentries; i++)
+   {
+       if (spalette->depth == 8)
+       {
+           entrybuf[0] = (png_byte)ep[i].red;
+           entrybuf[1] = (png_byte)ep[i].green;
+           entrybuf[2] = (png_byte)ep[i].blue;
+           entrybuf[3] = (png_byte)ep[i].alpha;
+           png_save_uint_16(entrybuf + 4, ep[i].frequency);
+       }
+       else
+       {
+           png_save_uint_16(entrybuf + 0, ep[i].red);
+           png_save_uint_16(entrybuf + 2, ep[i].green);
+           png_save_uint_16(entrybuf + 4, ep[i].blue);
+           png_save_uint_16(entrybuf + 6, ep[i].alpha);
+           png_save_uint_16(entrybuf + 8, ep[i].frequency);
+       }
+       png_write_chunk_data(png_ptr, entrybuf, entry_size);
+   }
+#endif
+
+   png_write_chunk_end(png_ptr);
+   png_free(png_ptr, new_name);
+}
+#endif
+
+#if defined(PNG_WRITE_sBIT_SUPPORTED)
+/* write the sBIT chunk */
+void /* PRIVATE */
+png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_sBIT;
+#endif
+   png_byte buf[4];
+   png_size_t size;
+
+   png_debug(1, "in png_write_sBIT\n");
+   /* make sure we don't depend upon the order of PNG_COLOR_8 */
+   if (color_type & PNG_COLOR_MASK_COLOR)
+   {
+      png_byte maxbits;
+
+      maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
+                png_ptr->usr_bit_depth);
+      if (sbit->red == 0 || sbit->red > maxbits ||
+          sbit->green == 0 || sbit->green > maxbits ||
+          sbit->blue == 0 || sbit->blue > maxbits)
+      {
+         png_warning(png_ptr, "Invalid sBIT depth specified");
+         return;
+      }
+      buf[0] = sbit->red;
+      buf[1] = sbit->green;
+      buf[2] = sbit->blue;
+      size = 3;
+   }
+   else
+   {
+      if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
+      {
+         png_warning(png_ptr, "Invalid sBIT depth specified");
+         return;
+      }
+      buf[0] = sbit->gray;
+      size = 1;
+   }
+
+   if (color_type & PNG_COLOR_MASK_ALPHA)
+   {
+      if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
+      {
+         png_warning(png_ptr, "Invalid sBIT depth specified");
+         return;
+      }
+      buf[size++] = sbit->alpha;
+   }
+
+   png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size);
+}
+#endif
+
+#if defined(PNG_WRITE_cHRM_SUPPORTED)
+/* write the cHRM chunk */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
+   double red_x, double red_y, double green_x, double green_y,
+   double blue_x, double blue_y)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_cHRM;
+#endif
+   png_byte buf[32];
+   png_uint_32 itemp;
+
+   png_debug(1, "in png_write_cHRM\n");
+   /* each value is saved in 1/100,000ths */
+   if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
+       white_x + white_y > 1.0)
+   {
+      png_warning(png_ptr, "Invalid cHRM white point specified");
+#if !defined(PNG_NO_CONSOLE_IO)
+      fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y);
+#endif
+      return;
+   }
+   itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
+   png_save_uint_32(buf, itemp);
+   itemp = (png_uint_32)(white_y * 100000.0 + 0.5);
+   png_save_uint_32(buf + 4, itemp);
+
+   if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 ||
+       red_x + red_y > 1.0)
+   {
+      png_warning(png_ptr, "Invalid cHRM red point specified");
+      return;
+   }
+   itemp = (png_uint_32)(red_x * 100000.0 + 0.5);
+   png_save_uint_32(buf + 8, itemp);
+   itemp = (png_uint_32)(red_y * 100000.0 + 0.5);
+   png_save_uint_32(buf + 12, itemp);
+
+   if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 ||
+       green_x + green_y > 1.0)
+   {
+      png_warning(png_ptr, "Invalid cHRM green point specified");
+      return;
+   }
+   itemp = (png_uint_32)(green_x * 100000.0 + 0.5);
+   png_save_uint_32(buf + 16, itemp);
+   itemp = (png_uint_32)(green_y * 100000.0 + 0.5);
+   png_save_uint_32(buf + 20, itemp);
+
+   if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 ||
+       blue_x + blue_y > 1.0)
+   {
+      png_warning(png_ptr, "Invalid cHRM blue point specified");
+      return;
+   }
+   itemp = (png_uint_32)(blue_x * 100000.0 + 0.5);
+   png_save_uint_32(buf + 24, itemp);
+   itemp = (png_uint_32)(blue_y * 100000.0 + 0.5);
+   png_save_uint_32(buf + 28, itemp);
+
+   png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
+   png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
+   png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
+   png_fixed_point blue_y)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_cHRM;
+#endif
+   png_byte buf[32];
+
+   png_debug(1, "in png_write_cHRM\n");
+   /* each value is saved in 1/100,000ths */
+   if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L)
+   {
+      png_warning(png_ptr, "Invalid fixed cHRM white point specified");
+#if !defined(PNG_NO_CONSOLE_IO)
+      fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y);
+#endif
+      return;
+   }
+   png_save_uint_32(buf, (png_uint_32)white_x);
+   png_save_uint_32(buf + 4, (png_uint_32)white_y);
+
+   if (red_x > 80000L || red_y > 80000L || red_x + red_y > 100000L)
+   {
+      png_warning(png_ptr, "Invalid cHRM fixed red point specified");
+      return;
+   }
+   png_save_uint_32(buf + 8, (png_uint_32)red_x);
+   png_save_uint_32(buf + 12, (png_uint_32)red_y);
+
+   if (green_x > 80000L || green_y > 80000L || green_x + green_y > 100000L)
+   {
+      png_warning(png_ptr, "Invalid fixed cHRM green point specified");
+      return;
+   }
+   png_save_uint_32(buf + 16, (png_uint_32)green_x);
+   png_save_uint_32(buf + 20, (png_uint_32)green_y);
+
+   if (blue_x > 80000L || blue_y > 80000L || blue_x + blue_y > 100000L)
+   {
+      png_warning(png_ptr, "Invalid fixed cHRM blue point specified");
+      return;
+   }
+   png_save_uint_32(buf + 24, (png_uint_32)blue_x);
+   png_save_uint_32(buf + 28, (png_uint_32)blue_y);
+
+   png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
+}
+#endif
+#endif
+
+#if defined(PNG_WRITE_tRNS_SUPPORTED)
+/* write the tRNS chunk */
+void /* PRIVATE */
+png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
+   int num_trans, int color_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_tRNS;
+#endif
+   png_byte buf[6];
+
+   png_debug(1, "in png_write_tRNS\n");
+   if (color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
+      {
+         png_warning(png_ptr,"Invalid number of transparent colors specified");
+         return;
+      }
+      /* write the chunk out as it is */
+      png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, (png_size_t)num_trans);
+   }
+   else if (color_type == PNG_COLOR_TYPE_GRAY)
+   {
+      /* one 16 bit value */
+      if(tran->gray >= (1 << png_ptr->bit_depth))
+      {
+         png_warning(png_ptr,
+           "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
+         return;
+      }
+      png_save_uint_16(buf, tran->gray);
+      png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2);
+   }
+   else if (color_type == PNG_COLOR_TYPE_RGB)
+   {
+      /* three 16 bit values */
+      png_save_uint_16(buf, tran->red);
+      png_save_uint_16(buf + 2, tran->green);
+      png_save_uint_16(buf + 4, tran->blue);
+      if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
+         {
+            png_warning(png_ptr,
+              "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
+            return;
+         }
+      png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6);
+   }
+   else
+   {
+      png_warning(png_ptr, "Can't write tRNS with an alpha channel");
+   }
+}
+#endif
+
+#if defined(PNG_WRITE_bKGD_SUPPORTED)
+/* write the background chunk */
+void /* PRIVATE */
+png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_bKGD;
+#endif
+   png_byte buf[6];
+
+   png_debug(1, "in png_write_bKGD\n");
+   if (color_type == PNG_COLOR_TYPE_PALETTE)
+   {
+      if (
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
+          (png_ptr->num_palette ||
+          (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
+#endif
+         back->index > png_ptr->num_palette)
+      {
+         png_warning(png_ptr, "Invalid background palette index");
+         return;
+      }
+      buf[0] = back->index;
+      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1);
+   }
+   else if (color_type & PNG_COLOR_MASK_COLOR)
+   {
+      png_save_uint_16(buf, back->red);
+      png_save_uint_16(buf + 2, back->green);
+      png_save_uint_16(buf + 4, back->blue);
+      if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
+         {
+            png_warning(png_ptr,
+              "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
+            return;
+         }
+      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6);
+   }
+   else
+   {
+      if(back->gray >= (1 << png_ptr->bit_depth))
+      {
+         png_warning(png_ptr,
+           "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
+         return;
+      }
+      png_save_uint_16(buf, back->gray);
+      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2);
+   }
+}
+#endif
+
+#if defined(PNG_WRITE_hIST_SUPPORTED)
+/* write the histogram */
+void /* PRIVATE */
+png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_hIST;
+#endif
+   int i;
+   png_byte buf[3];
+
+   png_debug(1, "in png_write_hIST\n");
+   if (num_hist > (int)png_ptr->num_palette)
+   {
+      png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist,
+         png_ptr->num_palette);
+      png_warning(png_ptr, "Invalid number of histogram entries specified");
+      return;
+   }
+
+   png_write_chunk_start(png_ptr, (png_bytep)png_hIST, (png_uint_32)(num_hist * 2));
+   for (i = 0; i < num_hist; i++)
+   {
+      png_save_uint_16(buf, hist[i]);
+      png_write_chunk_data(png_ptr, buf, (png_size_t)2);
+   }
+   png_write_chunk_end(png_ptr);
+}
+#endif
+
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
+    defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
+/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+ * and if invalid, correct the keyword rather than discarding the entire
+ * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
+ * length, forbids leading or trailing whitespace, multiple internal spaces,
+ * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
+ *
+ * The new_key is allocated to hold the corrected keyword and must be freed
+ * by the calling routine.  This avoids problems with trying to write to
+ * static keywords without having to have duplicate copies of the strings.
+ */
+png_size_t /* PRIVATE */
+png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
+{
+   png_size_t key_len;
+   png_charp kp, dp;
+   int kflag;
+   int kwarn=0;
+
+   png_debug(1, "in png_check_keyword\n");
+   *new_key = NULL;
+
+   if (key == NULL || (key_len = png_strlen(key)) == 0)
+   {
+      png_warning(png_ptr, "zero length keyword");
+      return ((png_size_t)0);
+   }
+
+   png_debug1(2, "Keyword to be checked is '%s'\n", key);
+
+   *new_key = (png_charp)png_malloc(png_ptr, (png_uint_32)(key_len + 2));
+
+   /* Replace non-printing characters with a blank and print a warning */
+   for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
+   {
+      if (*kp < 0x20 || (*kp > 0x7E && (png_byte)*kp < 0xA1))
+      {
+#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
+         char msg[40];
+
+         sprintf(msg, "invalid keyword character 0x%02X", *kp);
+         png_warning(png_ptr, msg);
+#else
+         png_warning(png_ptr, "invalid character in keyword");
+#endif
+         *dp = ' ';
+      }
+      else
+      {
+         *dp = *kp;
+      }
+   }
+   *dp = '\0';
+
+   /* Remove any trailing white space. */
+   kp = *new_key + key_len - 1;
+   if (*kp == ' ')
+   {
+      png_warning(png_ptr, "trailing spaces removed from keyword");
+
+      while (*kp == ' ')
+      {
+        *(kp--) = '\0';
+        key_len--;
+      }
+   }
+
+   /* Remove any leading white space. */
+   kp = *new_key;
+   if (*kp == ' ')
+   {
+      png_warning(png_ptr, "leading spaces removed from keyword");
+
+      while (*kp == ' ')
+      {
+        kp++;
+        key_len--;
+      }
+   }
+
+   png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp);
+
+   /* Remove multiple internal spaces. */
+   for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
+   {
+      if (*kp == ' ' && kflag == 0)
+      {
+         *(dp++) = *kp;
+         kflag = 1;
+      }
+      else if (*kp == ' ')
+      {
+         key_len--;
+         kwarn=1;
+      }
+      else
+      {
+         *(dp++) = *kp;
+         kflag = 0;
+      }
+   }
+   *dp = '\0';
+   if(kwarn)
+      png_warning(png_ptr, "extra interior spaces removed from keyword");
+
+   if (key_len == 0)
+   {
+      png_free(png_ptr, *new_key);
+      *new_key=NULL;
+      png_warning(png_ptr, "Zero length keyword");
+   }
+
+   if (key_len > 79)
+   {
+      png_warning(png_ptr, "keyword length must be 1 - 79 characters");
+      new_key[79] = '\0';
+      key_len = 79;
+   }
+
+   return (key_len);
+}
+#endif
+
+#if defined(PNG_WRITE_tEXt_SUPPORTED)
+/* write a tEXt chunk */
+void /* PRIVATE */
+png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
+   png_size_t text_len)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_tEXt;
+#endif
+   png_size_t key_len;
+   png_charp new_key;
+
+   png_debug(1, "in png_write_tEXt\n");
+   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
+   {
+      png_warning(png_ptr, "Empty keyword in tEXt chunk");
+      return;
+   }
+
+   if (text == NULL || *text == '\0')
+      text_len = 0;
+   else
+      text_len = png_strlen(text);
+
+   /* make sure we include the 0 after the key */
+   png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, (png_uint_32)key_len+text_len+1);
+   /*
+    * We leave it to the application to meet PNG-1.0 requirements on the
+    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
+    * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
+    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
+    */
+   png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
+   if (text_len)
+      png_write_chunk_data(png_ptr, (png_bytep)text, text_len);
+
+   png_write_chunk_end(png_ptr);
+   png_free(png_ptr, new_key);
+}
+#endif
+
+#if defined(PNG_WRITE_zTXt_SUPPORTED)
+/* write a compressed text chunk */
+void /* PRIVATE */
+png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
+   png_size_t text_len, int compression)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_zTXt;
+#endif
+   png_size_t key_len;
+   char buf[1];
+   png_charp new_key;
+   compression_state comp;
+
+   png_debug(1, "in png_write_zTXt\n");
+
+   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
+   {
+      png_warning(png_ptr, "Empty keyword in zTXt chunk");
+      return;
+   }
+
+   if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
+   {
+      png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
+      png_free(png_ptr, new_key);
+      return;
+   }
+
+   text_len = png_strlen(text);
+
+   png_free(png_ptr, new_key);
+
+   /* compute the compressed data; do it now for the length */
+   text_len = png_text_compress(png_ptr, text, text_len, compression,
+       &comp);
+
+   /* write start of chunk */
+   png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, (png_uint_32)
+      (key_len+text_len+2));
+   /* write key */
+   png_write_chunk_data(png_ptr, (png_bytep)key, key_len + 1);
+   buf[0] = (png_byte)compression;
+   /* write compression */
+   png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1);
+   /* write the compressed data */
+   png_write_compressed_data_out(png_ptr, &comp);
+
+   /* close the chunk */
+   png_write_chunk_end(png_ptr);
+}
+#endif
+
+#if defined(PNG_WRITE_iTXt_SUPPORTED)
+/* write an iTXt chunk */
+void /* PRIVATE */
+png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
+    png_charp lang, png_charp lang_key, png_charp text)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_iTXt;
+#endif
+   png_size_t lang_len, key_len, lang_key_len, text_len;
+   png_charp new_lang, new_key;
+   png_byte cbuf[2];
+   compression_state comp;
+
+   png_debug(1, "in png_write_iTXt\n");
+
+   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
+   {
+      png_warning(png_ptr, "Empty keyword in iTXt chunk");
+      return;
+   }
+   if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang,
+      &new_lang))==0)
+   {
+      png_warning(png_ptr, "Empty language field in iTXt chunk");
+      return;
+   }
+   lang_key_len = png_strlen(lang_key);
+   text_len = png_strlen(text);
+
+   if (text == NULL || *text == '\0')
+      text_len = 0;
+
+   /* compute the compressed data; do it now for the length */
+   text_len = png_text_compress(png_ptr, text, text_len, compression-2,
+      &comp);
+
+   /* make sure we include the compression flag, the compression byte,
+    * and the NULs after the key, lang, and lang_key parts */
+
+   png_write_chunk_start(png_ptr, (png_bytep)png_iTXt,
+          (png_uint_32)(
+        5 /* comp byte, comp flag, terminators for key, lang and lang_key */
+        + key_len
+        + lang_len
+        + lang_key_len
+        + text_len));
+
+   /*
+    * We leave it to the application to meet PNG-1.0 requirements on the
+    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
+    * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
+    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
+    */
+   png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
+
+   /* set the compression flag */
+   if (compression == PNG_ITXT_COMPRESSION_NONE || \
+       compression == PNG_TEXT_COMPRESSION_NONE)
+       cbuf[0] = 0;
+   else /* compression == PNG_ITXT_COMPRESSION_zTXt */
+       cbuf[0] = 1;
+   /* set the compression method */
+   cbuf[1] = 0;
+   png_write_chunk_data(png_ptr, cbuf, 2);
+
+   png_write_chunk_data(png_ptr, (png_bytep)new_lang, lang_len + 1);
+   png_write_chunk_data(png_ptr, (png_bytep)lang_key, lang_key_len+1);
+   png_write_chunk_data(png_ptr, '\0', 1);
+
+   png_write_compressed_data_out(png_ptr, &comp);
+
+   png_write_chunk_end(png_ptr);
+   png_free(png_ptr, new_key);
+   png_free(png_ptr, new_lang);
+}
+#endif
+
+#if defined(PNG_WRITE_oFFs_SUPPORTED)
+/* write the oFFs chunk */
+void /* PRIVATE */
+png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
+   int unit_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_oFFs;
+#endif
+   png_byte buf[9];
+
+   png_debug(1, "in png_write_oFFs\n");
+   if (unit_type >= PNG_OFFSET_LAST)
+      png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
+
+   png_save_int_32(buf, x_offset);
+   png_save_int_32(buf + 4, y_offset);
+   buf[8] = (png_byte)unit_type;
+
+   png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9);
+}
+#endif
+
+#if defined(PNG_WRITE_pCAL_SUPPORTED)
+/* write the pCAL chunk (described in the PNG extensions document) */
+void /* PRIVATE */
+png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
+   png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_pCAL;
+#endif
+   png_size_t purpose_len, units_len, total_len;
+   png_uint_32p params_len;
+   png_byte buf[10];
+   png_charp new_purpose;
+   int i;
+
+   png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams);
+   if (type >= PNG_EQUATION_LAST)
+      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+
+   purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
+   png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len);
+   units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
+   png_debug1(3, "pCAL units length = %d\n", (int)units_len);
+   total_len = purpose_len + units_len + 10;
+
+   params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams
+      *sizeof(png_uint_32)));
+
+   /* Find the length of each parameter, making sure we don't count the
+      null terminator for the last parameter. */
+   for (i = 0; i < nparams; i++)
+   {
+      params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
+      png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]);
+      total_len += (png_size_t)params_len[i];
+   }
+
+   png_debug1(3, "pCAL total length = %d\n", (int)total_len);
+   png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len);
+   png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len);
+   png_save_int_32(buf, X0);
+   png_save_int_32(buf + 4, X1);
+   buf[8] = (png_byte)type;
+   buf[9] = (png_byte)nparams;
+   png_write_chunk_data(png_ptr, buf, (png_size_t)10);
+   png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len);
+
+   png_free(png_ptr, new_purpose);
+
+   for (i = 0; i < nparams; i++)
+   {
+      png_write_chunk_data(png_ptr, (png_bytep)params[i],
+         (png_size_t)params_len[i]);
+   }
+
+   png_free(png_ptr, params_len);
+   png_write_chunk_end(png_ptr);
+}
+#endif
+
+#if defined(PNG_WRITE_sCAL_SUPPORTED)
+/* write the sCAL chunk */
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
+void /* PRIVATE */
+png_write_sCAL(png_structp png_ptr, int unit, double width,double height)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_sCAL;
+#endif
+   png_size_t total_len;
+   char wbuf[32], hbuf[32];
+
+   png_debug(1, "in png_write_sCAL\n");
+
+#if defined(_WIN32_WCE)
+/* sprintf() function is not supported on WindowsCE */
+   {
+      wchar_t wc_buf[32];
+      swprintf(wc_buf, TEXT("%12.12e"), width);
+      WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, wbuf, 32, NULL, NULL);
+      swprintf(wc_buf, TEXT("%12.12e"), height);
+      WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, hbuf, 32, NULL, NULL);
+   }
+#else
+   sprintf(wbuf, "%12.12e", width);
+   sprintf(hbuf, "%12.12e", height);
+#endif
+   total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf);
+
+   png_debug1(3, "sCAL total length = %d\n", (int)total_len);
+   png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len);
+   png_write_chunk_data(png_ptr, (png_bytep)&unit, 1);
+   png_write_chunk_data(png_ptr, (png_bytep)wbuf, png_strlen(wbuf)+1);
+   png_write_chunk_data(png_ptr, (png_bytep)hbuf, png_strlen(hbuf));
+
+   png_write_chunk_end(png_ptr);
+}
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
+   png_charp height)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_sCAL;
+#endif
+   png_size_t total_len;
+   char wbuf[32], hbuf[32];
+
+   png_debug(1, "in png_write_sCAL_s\n");
+
+   png_strcpy(wbuf,(const char *)width);
+   png_strcpy(hbuf,(const char *)height);
+   total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf);
+
+   png_debug1(3, "sCAL total length = %d\n", total_len);
+   png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len);
+   png_write_chunk_data(png_ptr, (png_bytep)&unit, 1);
+   png_write_chunk_data(png_ptr, (png_bytep)wbuf, png_strlen(wbuf)+1);
+   png_write_chunk_data(png_ptr, (png_bytep)hbuf, png_strlen(hbuf));
+
+   png_write_chunk_end(png_ptr);
+}
+#endif
+#endif
+#endif
+
+#if defined(PNG_WRITE_pHYs_SUPPORTED)
+/* write the pHYs chunk */
+void /* PRIVATE */
+png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
+   png_uint_32 y_pixels_per_unit,
+   int unit_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_pHYs;
+#endif
+   png_byte buf[9];
+
+   png_debug(1, "in png_write_pHYs\n");
+   if (unit_type >= PNG_RESOLUTION_LAST)
+      png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
+
+   png_save_uint_32(buf, x_pixels_per_unit);
+   png_save_uint_32(buf + 4, y_pixels_per_unit);
+   buf[8] = (png_byte)unit_type;
+
+   png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9);
+}
+#endif
+
+#if defined(PNG_WRITE_tIME_SUPPORTED)
+/* Write the tIME chunk.  Use either png_convert_from_struct_tm()
+ * or png_convert_from_time_t(), or fill in the structure yourself.
+ */
+void /* PRIVATE */
+png_write_tIME(png_structp png_ptr, png_timep mod_time)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   PNG_tIME;
+#endif
+   png_byte buf[7];
+
+   png_debug(1, "in png_write_tIME\n");
+   if (mod_time->month  > 12 || mod_time->month  < 1 ||
+       mod_time->day    > 31 || mod_time->day    < 1 ||
+       mod_time->hour   > 23 || mod_time->second > 60)
+   {
+      png_warning(png_ptr, "Invalid time specified for tIME chunk");
+      return;
+   }
+
+   png_save_uint_16(buf, mod_time->year);
+   buf[2] = mod_time->month;
+   buf[3] = mod_time->day;
+   buf[4] = mod_time->hour;
+   buf[5] = mod_time->minute;
+   buf[6] = mod_time->second;
+
+   png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7);
+}
+#endif
+
+/* initializes the row writing capability of libpng */
+void /* PRIVATE */
+png_write_start_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+   /* start of interlace block in the y direction */
+   int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+   /* offset to next interlace block in the y direction */
+   int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+   png_size_t buf_size;
+
+   png_debug(1, "in png_write_start_row\n");
+   buf_size = (png_size_t)(((png_ptr->width * png_ptr->usr_channels *
+                            png_ptr->usr_bit_depth + 7) >> 3) + 1);
+
+   /* set up row buffer */
+   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
+   png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
+
+   /* set up filtering buffer, if using this filter */
+   if (png_ptr->do_filter & PNG_FILTER_SUB)
+   {
+      png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
+         (png_ptr->rowbytes + 1));
+      png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
+   }
+
+   /* We only need to keep the previous row if we are using one of these. */
+   if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
+   {
+     /* set up previous row buffer */
+      png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
+      png_memset(png_ptr->prev_row, 0, buf_size);
+
+      if (png_ptr->do_filter & PNG_FILTER_UP)
+      {
+         png_ptr->up_row = (png_bytep )png_malloc(png_ptr,
+            (png_ptr->rowbytes + 1));
+         png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
+      }
+
+      if (png_ptr->do_filter & PNG_FILTER_AVG)
+      {
+         png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
+            (png_ptr->rowbytes + 1));
+         png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
+      }
+
+      if (png_ptr->do_filter & PNG_FILTER_PAETH)
+      {
+         png_ptr->paeth_row = (png_bytep )png_malloc(png_ptr,
+            (png_ptr->rowbytes + 1));
+         png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
+      }
+   }
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+   /* if interlaced, we need to set up width and height of pass */
+   if (png_ptr->interlaced)
+   {
+      if (!(png_ptr->transformations & PNG_INTERLACE))
+      {
+         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
+            png_pass_ystart[0]) / png_pass_yinc[0];
+         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
+            png_pass_start[0]) / png_pass_inc[0];
+      }
+      else
+      {
+         png_ptr->num_rows = png_ptr->height;
+         png_ptr->usr_width = png_ptr->width;
+      }
+   }
+   else
+#endif
+   {
+      png_ptr->num_rows = png_ptr->height;
+      png_ptr->usr_width = png_ptr->width;
+   }
+   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+   png_ptr->zstream.next_out = png_ptr->zbuf;
+}
+
+/* Internal use only.  Called when finished processing a row of data. */
+void /* PRIVATE */
+png_write_finish_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+   /* start of interlace block in the y direction */
+   int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+   /* offset to next interlace block in the y direction */
+   int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+   int ret;
+
+   png_debug(1, "in png_write_finish_row\n");
+   /* next row */
+   png_ptr->row_number++;
+
+   /* see if we are done */
+   if (png_ptr->row_number < png_ptr->num_rows)
+      return;
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+   /* if interlaced, go to next pass */
+   if (png_ptr->interlaced)
+   {
+      png_ptr->row_number = 0;
+      if (png_ptr->transformations & PNG_INTERLACE)
+      {
+         png_ptr->pass++;
+      }
+      else
+      {
+         /* loop until we find a non-zero width or height pass */
+         do
+         {
+            png_ptr->pass++;
+            if (png_ptr->pass >= 7)
+               break;
+            png_ptr->usr_width = (png_ptr->width +
+               png_pass_inc[png_ptr->pass] - 1 -
+               png_pass_start[png_ptr->pass]) /
+               png_pass_inc[png_ptr->pass];
+            png_ptr->num_rows = (png_ptr->height +
+               png_pass_yinc[png_ptr->pass] - 1 -
+               png_pass_ystart[png_ptr->pass]) /
+               png_pass_yinc[png_ptr->pass];
+            if (png_ptr->transformations & PNG_INTERLACE)
+               break;
+         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
+
+      }
+
+      /* reset the row above the image for the next pass */
+      if (png_ptr->pass < 7)
+      {
+         if (png_ptr->prev_row != NULL)
+            png_memset(png_ptr->prev_row, 0,
+               (png_size_t) (((png_uint_32)png_ptr->usr_channels *
+               (png_uint_32)png_ptr->usr_bit_depth *
+               png_ptr->width + 7) >> 3) + 1);
+         return;
+      }
+   }
+#endif
+
+   /* if we get here, we've just written the last row, so we need
+      to flush the compressor */
+   do
+   {
+      /* tell the compressor we are done */
+      ret = deflate(&png_ptr->zstream, Z_FINISH);
+      /* check for an error */
+      if (ret == Z_OK)
+      {
+         /* check to see if we need more room */
+         if (!(png_ptr->zstream.avail_out))
+         {
+            png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
+            png_ptr->zstream.next_out = png_ptr->zbuf;
+            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+         }
+      }
+      else if (ret != Z_STREAM_END)
+      {
+         if (png_ptr->zstream.msg != NULL)
+            png_error(png_ptr, png_ptr->zstream.msg);
+         else
+            png_error(png_ptr, "zlib error");
+      }
+   } while (ret != Z_STREAM_END);
+
+   /* write any extra space */
+   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
+   {
+      png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
+         png_ptr->zstream.avail_out);
+   }
+
+   deflateReset(&png_ptr->zstream);
+}
+
+#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
+/* Pick out the correct pixels for the interlace pass.
+ * The basic idea here is to go through the row with a source
+ * pointer and a destination pointer (sp and dp), and copy the
+ * correct pixels for the pass.  As the row gets compacted,
+ * sp will always be >= dp, so we should never overwrite anything.
+ * See the default: case for the easiest code to understand.
+ */
+void /* PRIVATE */
+png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+   /* start of interlace block */
+   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+   /* offset to next interlace block */
+   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+#endif
+
+   png_debug(1, "in png_do_write_interlace\n");
+   /* we don't have to do anything on the last pass (6) */
+#if defined(PNG_USELESS_TESTS_SUPPORTED)
+   if (row != NULL && row_info != NULL && pass < 6)
+#else
+   if (pass < 6)
+#endif
+   {
+      /* each pixel depth is handled separately */
+      switch (row_info->pixel_depth)
+      {
+         case 1:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int shift;
+            int d;
+            int value;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            dp = row;
+            d = 0;
+            shift = 7;
+            for (i = png_pass_start[pass]; i < row_width;
+               i += png_pass_inc[pass])
+            {
+               sp = row + (png_size_t)(i >> 3);
+               value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
+               d |= (value << shift);
+
+               if (shift == 0)
+               {
+                  shift = 7;
+                  *dp++ = (png_byte)d;
+                  d = 0;
+               }
+               else
+                  shift--;
+
+            }
+            if (shift != 7)
+               *dp = (png_byte)d;
+            break;
+         }
+         case 2:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int shift;
+            int d;
+            int value;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            dp = row;
+            shift = 6;
+            d = 0;
+            for (i = png_pass_start[pass]; i < row_width;
+               i += png_pass_inc[pass])
+            {
+               sp = row + (png_size_t)(i >> 2);
+               value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
+               d |= (value << shift);
+
+               if (shift == 0)
+               {
+                  shift = 6;
+                  *dp++ = (png_byte)d;
+                  d = 0;
+               }
+               else
+                  shift -= 2;
+            }
+            if (shift != 6)
+                   *dp = (png_byte)d;
+            break;
+         }
+         case 4:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            int shift;
+            int d;
+            int value;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+
+            dp = row;
+            shift = 4;
+            d = 0;
+            for (i = png_pass_start[pass]; i < row_width;
+               i += png_pass_inc[pass])
+            {
+               sp = row + (png_size_t)(i >> 1);
+               value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
+               d |= (value << shift);
+
+               if (shift == 0)
+               {
+                  shift = 4;
+                  *dp++ = (png_byte)d;
+                  d = 0;
+               }
+               else
+                  shift -= 4;
+            }
+            if (shift != 4)
+               *dp = (png_byte)d;
+            break;
+         }
+         default:
+         {
+            png_bytep sp;
+            png_bytep dp;
+            png_uint_32 i;
+            png_uint_32 row_width = row_info->width;
+            png_size_t pixel_bytes;
+
+            /* start at the beginning */
+            dp = row;
+            /* find out how many bytes each pixel takes up */
+            pixel_bytes = (row_info->pixel_depth >> 3);
+            /* loop through the row, only looking at the pixels that
+               matter */
+            for (i = png_pass_start[pass]; i < row_width;
+               i += png_pass_inc[pass])
+            {
+               /* find out where the original pixel is */
+               sp = row + (png_size_t)i * pixel_bytes;
+               /* move the pixel */
+               if (dp != sp)
+                  png_memcpy(dp, sp, pixel_bytes);
+               /* next pixel */
+               dp += pixel_bytes;
+            }
+            break;
+         }
+      }
+      /* set new row width */
+      row_info->width = (row_info->width +
+         png_pass_inc[pass] - 1 -
+         png_pass_start[pass]) /
+         png_pass_inc[pass];
+         row_info->rowbytes = ((row_info->width *
+            row_info->pixel_depth + 7) >> 3);
+   }
+}
+#endif
+
+/* This filters the row, chooses which filter to use, if it has not already
+ * been specified by the application, and then writes the row out with the
+ * chosen filter.
+ */
+#define PNG_MAXSUM (~((png_uint_32)0) >> 1)
+#define PNG_HISHIFT 10
+#define PNG_LOMASK ((png_uint_32)0xffffL)
+#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
+void /* PRIVATE */
+png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
+{
+   png_bytep prev_row, best_row, row_buf;
+   png_uint_32 mins, bpp;
+   png_byte filter_to_do = png_ptr->do_filter;
+   png_uint_32 row_bytes = row_info->rowbytes;
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   int num_p_filters = (int)png_ptr->num_prev_filters;
+#endif
+
+   png_debug(1, "in png_write_find_filter\n");
+   /* find out how many bytes offset each pixel is */
+   bpp = (row_info->pixel_depth + 7) / 8;
+
+   prev_row = png_ptr->prev_row;
+   best_row = row_buf = png_ptr->row_buf;
+   mins = PNG_MAXSUM;
+
+   /* The prediction method we use is to find which method provides the
+    * smallest value when summing the absolute values of the distances
+    * from zero, using anything >= 128 as negative numbers.  This is known
+    * as the "minimum sum of absolute differences" heuristic.  Other
+    * heuristics are the "weighted minimum sum of absolute differences"
+    * (experimental and can in theory improve compression), and the "zlib
+    * predictive" method (not implemented yet), which does test compressions
+    * of lines using different filter methods, and then chooses the
+    * (series of) filter(s) that give minimum compressed data size (VERY
+    * computationally expensive).
+    *
+    * GRR 980525:  consider also
+    *   (1) minimum sum of absolute differences from running average (i.e.,
+    *       keep running sum of non-absolute differences & count of bytes)
+    *       [track dispersion, too?  restart average if dispersion too large?]
+    *  (1b) minimum sum of absolute differences from sliding average, probably
+    *       with window size <= deflate window (usually 32K)
+    *   (2) minimum sum of squared differences from zero or running average
+    *       (i.e., ~ root-mean-square approach)
+    */
+
+
+   /* We don't need to test the 'no filter' case if this is the only filter
+    * that has been chosen, as it doesn't actually do anything to the data.
+    */
+   if ((filter_to_do & PNG_FILTER_NONE) &&
+       filter_to_do != PNG_FILTER_NONE)
+   {
+      png_bytep rp;
+      png_uint_32 sum = 0;
+      png_uint_32 i;
+      int v;
+
+      for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
+      {
+         v = *rp;
+         sum += (v < 128) ? v : 256 - v;
+      }
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         png_uint_32 sumhi, sumlo;
+         int j;
+         sumlo = sum & PNG_LOMASK;
+         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
+
+         /* Reduce the sum if we match any of the previous rows */
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
+            {
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         /* Factor in the cost of this filter (this is here for completeness,
+          * but it makes no sense to have a "cost" for the NONE filter, as
+          * it has the minimum possible computational cost - none).
+          */
+         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
+            PNG_COST_SHIFT;
+         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
+            PNG_COST_SHIFT;
+
+         if (sumhi > PNG_HIMASK)
+            sum = PNG_MAXSUM;
+         else
+            sum = (sumhi << PNG_HISHIFT) + sumlo;
+      }
+#endif
+      mins = sum;
+   }
+
+   /* sub filter */
+   if (filter_to_do == PNG_FILTER_SUB)
+   /* it's the only filter so no testing is needed */
+   {
+      png_bytep rp, lp, dp;
+      png_uint_32 i;
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
+           i++, rp++, dp++)
+      {
+         *dp = *rp;
+      }
+      for (lp = row_buf + 1; i < row_bytes;
+         i++, rp++, lp++, dp++)
+      {
+         *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+      }
+      best_row = png_ptr->sub_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_SUB)
+   {
+      png_bytep rp, dp, lp;
+      png_uint_32 sum = 0, lmins = mins;
+      png_uint_32 i;
+      int v;
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      /* We temporarily increase the "minimum sum" by the factor we
+       * would reduce the sum of this filter, so that we can do the
+       * early exit comparison without scaling the sum each time.
+       */
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 lmhi, lmlo;
+         lmlo = lmins & PNG_LOMASK;
+         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
+            {
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+            PNG_COST_SHIFT;
+         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+            PNG_COST_SHIFT;
+
+         if (lmhi > PNG_HIMASK)
+            lmins = PNG_MAXSUM;
+         else
+            lmins = (lmhi << PNG_HISHIFT) + lmlo;
+      }
+#endif
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
+           i++, rp++, dp++)
+      {
+         v = *dp = *rp;
+
+         sum += (v < 128) ? v : 256 - v;
+      }
+      for (lp = row_buf + 1; i < row_info->rowbytes;
+         i++, rp++, lp++, dp++)
+      {
+         v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+
+         if (sum > lmins)  /* We are already worse, don't continue. */
+            break;
+      }
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 sumhi, sumlo;
+         sumlo = sum & PNG_LOMASK;
+         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
+            {
+               sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+            PNG_COST_SHIFT;
+         sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+            PNG_COST_SHIFT;
+
+         if (sumhi > PNG_HIMASK)
+            sum = PNG_MAXSUM;
+         else
+            sum = (sumhi << PNG_HISHIFT) + sumlo;
+      }
+#endif
+
+      if (sum < mins)
+      {
+         mins = sum;
+         best_row = png_ptr->sub_row;
+      }
+   }
+
+   /* up filter */
+   if (filter_to_do == PNG_FILTER_UP)
+   {
+      png_bytep rp, dp, pp;
+      png_uint_32 i;
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
+           pp = prev_row + 1; i < row_bytes;
+           i++, rp++, pp++, dp++)
+      {
+         *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
+      }
+      best_row = png_ptr->up_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_UP)
+   {
+      png_bytep rp, dp, pp;
+      png_uint_32 sum = 0, lmins = mins;
+      png_uint_32 i;
+      int v;
+
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 lmhi, lmlo;
+         lmlo = lmins & PNG_LOMASK;
+         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
+            {
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
+            PNG_COST_SHIFT;
+         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
+            PNG_COST_SHIFT;
+
+         if (lmhi > PNG_HIMASK)
+            lmins = PNG_MAXSUM;
+         else
+            lmins = (lmhi << PNG_HISHIFT) + lmlo;
+      }
+#endif
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
+           pp = prev_row + 1; i < row_bytes; i++)
+      {
+         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+
+         if (sum > lmins)  /* We are already worse, don't continue. */
+            break;
+      }
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 sumhi, sumlo;
+         sumlo = sum & PNG_LOMASK;
+         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
+            {
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
+            PNG_COST_SHIFT;
+         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
+            PNG_COST_SHIFT;
+
+         if (sumhi > PNG_HIMASK)
+            sum = PNG_MAXSUM;
+         else
+            sum = (sumhi << PNG_HISHIFT) + sumlo;
+      }
+#endif
+
+      if (sum < mins)
+      {
+         mins = sum;
+         best_row = png_ptr->up_row;
+      }
+   }
+
+   /* avg filter */
+   if (filter_to_do == PNG_FILTER_AVG)
+   {
+      png_bytep rp, dp, pp, lp;
+      png_uint_32 i;
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
+           pp = prev_row + 1; i < bpp; i++)
+      {
+         *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+      }
+      for (lp = row_buf + 1; i < row_bytes; i++)
+      {
+         *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
+                 & 0xff);
+      }
+      best_row = png_ptr->avg_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_AVG)
+   {
+      png_bytep rp, dp, pp, lp;
+      png_uint_32 sum = 0, lmins = mins;
+      png_uint_32 i;
+      int v;
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 lmhi, lmlo;
+         lmlo = lmins & PNG_LOMASK;
+         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
+            {
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
+            PNG_COST_SHIFT;
+         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
+            PNG_COST_SHIFT;
+
+         if (lmhi > PNG_HIMASK)
+            lmins = PNG_MAXSUM;
+         else
+            lmins = (lmhi << PNG_HISHIFT) + lmlo;
+      }
+#endif
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
+           pp = prev_row + 1; i < bpp; i++)
+      {
+         v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+      }
+      for (lp = row_buf + 1; i < row_bytes; i++)
+      {
+         v = *dp++ =
+          (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+
+         if (sum > lmins)  /* We are already worse, don't continue. */
+            break;
+      }
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 sumhi, sumlo;
+         sumlo = sum & PNG_LOMASK;
+         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
+            {
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
+            PNG_COST_SHIFT;
+         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
+            PNG_COST_SHIFT;
+
+         if (sumhi > PNG_HIMASK)
+            sum = PNG_MAXSUM;
+         else
+            sum = (sumhi << PNG_HISHIFT) + sumlo;
+      }
+#endif
+
+      if (sum < mins)
+      {
+         mins = sum;
+         best_row = png_ptr->avg_row;
+      }
+   }
+
+   /* Paeth filter */
+   if (filter_to_do == PNG_FILTER_PAETH)
+   {
+      png_bytep rp, dp, pp, cp, lp;
+      png_uint_32 i;
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
+           pp = prev_row + 1; i < bpp; i++)
+      {
+         *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+      }
+
+      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
+      {
+         int a, b, c, pa, pb, pc, p;
+
+         b = *pp++;
+         c = *cp++;
+         a = *lp++;
+
+         p = b - c;
+         pc = a - c;
+
+#ifdef PNG_USE_ABS
+         pa = abs(p);
+         pb = abs(pc);
+         pc = abs(p + pc);
+#else
+         pa = p < 0 ? -p : p;
+         pb = pc < 0 ? -pc : pc;
+         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+
+         *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+      }
+      best_row = png_ptr->paeth_row;
+   }
+
+   else if (filter_to_do & PNG_FILTER_PAETH)
+   {
+      png_bytep rp, dp, pp, cp, lp;
+      png_uint_32 sum = 0, lmins = mins;
+      png_uint_32 i;
+      int v;
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 lmhi, lmlo;
+         lmlo = lmins & PNG_LOMASK;
+         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
+            {
+               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+            PNG_COST_SHIFT;
+         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+            PNG_COST_SHIFT;
+
+         if (lmhi > PNG_HIMASK)
+            lmins = PNG_MAXSUM;
+         else
+            lmins = (lmhi << PNG_HISHIFT) + lmlo;
+      }
+#endif
+
+      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
+           pp = prev_row + 1; i < bpp; i++)
+      {
+         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+      }
+
+      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
+      {
+         int a, b, c, pa, pb, pc, p;
+
+         b = *pp++;
+         c = *cp++;
+         a = *lp++;
+
+#ifndef PNG_SLOW_PAETH
+         p = b - c;
+         pc = a - c;
+#ifdef PNG_USE_ABS
+         pa = abs(p);
+         pb = abs(pc);
+         pc = abs(p + pc);
+#else
+         pa = p < 0 ? -p : p;
+         pb = pc < 0 ? -pc : pc;
+         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+#else /* PNG_SLOW_PAETH */
+         p = a + b - c;
+         pa = abs(p - a);
+         pb = abs(p - b);
+         pc = abs(p - c);
+         if (pa <= pb && pa <= pc)
+            p = a;
+         else if (pb <= pc)
+            p = b;
+         else
+            p = c;
+#endif /* PNG_SLOW_PAETH */
+
+         v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+
+         sum += (v < 128) ? v : 256 - v;
+
+         if (sum > lmins)  /* We are already worse, don't continue. */
+            break;
+      }
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+      {
+         int j;
+         png_uint_32 sumhi, sumlo;
+         sumlo = sum & PNG_LOMASK;
+         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+         for (j = 0; j < num_p_filters; j++)
+         {
+            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
+            {
+               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+                  PNG_WEIGHT_SHIFT;
+            }
+         }
+
+         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+            PNG_COST_SHIFT;
+         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+            PNG_COST_SHIFT;
+
+         if (sumhi > PNG_HIMASK)
+            sum = PNG_MAXSUM;
+         else
+            sum = (sumhi << PNG_HISHIFT) + sumlo;
+      }
+#endif
+
+      if (sum < mins)
+      {
+         best_row = png_ptr->paeth_row;
+      }
+   }
+
+   /* Do the actual writing of the filtered row data from the chosen filter. */
+
+   png_write_filtered_row(png_ptr, best_row);
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
+   /* Save the type of filter we picked this time for future calculations */
+   if (png_ptr->num_prev_filters > 0)
+   {
+      int j;
+      for (j = 1; j < num_p_filters; j++)
+      {
+         png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
+      }
+      png_ptr->prev_filters[j] = best_row[0];
+   }
+#endif
+}
+
+
+/* Do the actual writing of a previously filtered row. */
+void /* PRIVATE */
+png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
+{
+   png_debug(1, "in png_write_filtered_row\n");
+   png_debug1(2, "filter = %d\n", filtered_row[0]);
+   /* set up the zlib input buffer */
+
+   png_ptr->zstream.next_in = filtered_row;
+   png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
+   /* repeat until we have compressed all the data */
+   do
+   {
+      int ret; /* return of zlib */
+
+      /* compress the data */
+      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
+      /* check for compression errors */
+      if (ret != Z_OK)
+      {
+         if (png_ptr->zstream.msg != NULL)
+            png_error(png_ptr, png_ptr->zstream.msg);
+         else
+            png_error(png_ptr, "zlib error");
+      }
+
+      /* see if it is time to write another IDAT */
+      if (!(png_ptr->zstream.avail_out))
+      {
+         /* write the IDAT and reset the zlib output buffer */
+         png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
+         png_ptr->zstream.next_out = png_ptr->zbuf;
+         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+      }
+   /* repeat until all data has been compressed */
+   } while (png_ptr->zstream.avail_in);
+
+   /* swap the current and previous rows */
+   if (png_ptr->prev_row != NULL)
+   {
+      png_bytep tptr;
+
+      tptr = png_ptr->prev_row;
+      png_ptr->prev_row = png_ptr->row_buf;
+      png_ptr->row_buf = tptr;
+   }
+
+   /* finish row - updates counters and flushes zlib if last row */
+   png_write_finish_row(png_ptr);
+
+#if defined(PNG_WRITE_FLUSH_SUPPORTED)
+   png_ptr->flush_rows++;
+
+   if (png_ptr->flush_dist > 0 &&
+       png_ptr->flush_rows >= png_ptr->flush_dist)
+   {
+      png_write_flush(png_ptr);
+   }
+#endif
+}
+#endif /* PNG_WRITE_SUPPORTED */
index 15e8bf4..47ecf13 100644 (file)
@@ -6,18 +6,15 @@
 #AUTOHEADER = @AUTOHEADER@ --localdir=$(top_srcdir)/config
 
 CGI_LIB_DIR       = $(top_srcdir)/@CGI_LIB_DIR@
-GD_LIB_DIR        = $(top_srcdir)/@GD_LIB_DIR@
+FREETYPE_LIB_DIR   = $(top_srcdir)/@FREETYPE_LIB_DIR@
+ART_LIB_DIR       = $(top_srcdir)/@ART_LIB_DIR@
 PNG_LIB_DIR       = $(top_srcdir)/@PNG_LIB_DIR@
 ZLIB_LIB_DIR      = $(top_srcdir)/@ZLIB_LIB_DIR@
 
-INCLUDES          = -I$(CGI_LIB_DIR) -I$(GD_LIB_DIR) -I$(PNG_LIB_DIR) -I$(ZLIB_LIB_DIR)
-
-#COMPILE   = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(CFLAGS_EXTRA)
-#LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(CFLAGS_EXTRA)
-#LINK      = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(CFLAGS_EXTRA) $(LDFLAGS) -o $@
+INCLUDES          = -I$(CGI_LIB_DIR) -I$(ART_LIB_DIR) \
+       -I$(PNG_LIB_DIR) -I$(ZLIB_LIB_DIR) -I$(FREETYPE_LIB_DIR)/include
 
 RRD_C_FILES =          \
-       gdpng.c         \
        getopt.c        \
        getopt1.c       \
        gifsize.c       \
@@ -41,6 +38,7 @@ RRD_C_FILES =         \
        rrd_rpncalc.c \
        rrd_tune.c      \
        rrd_update.c    \
+       rrd_gfx.c rrd_gfx.h \
        getopt.h ntconfig.h parsetime.h rrd_format.h rrd_tool.h rrd.h rrd_hw.h rrd_rpncalc.h
 
 # Build two libraries.  One is a public one that gets installed in
@@ -52,7 +50,8 @@ RRD_C_FILES =         \
 
 RRD_LIBS =                             \
        $(CGI_LIB_DIR)/librrd_cgi.la    \
-       $(GD_LIB_DIR)/librrd_gd.la      \
+       $(FREETYPE_LIB_DIR)/librrd_freetype.la  \
+       $(ART_LIB_DIR)/librrd_art.la    \
        $(PNG_LIB_DIR)/librrd_png.la    \
        $(ZLIB_LIB_DIR)/librrd_z.la
 
@@ -63,7 +62,7 @@ librrd_la_SOURCES         = $(RRD_C_FILES)
 librrd_private_la_SOURCES = $(RRD_C_FILES)
 
 librrd_la_LIBADD          = $(RRD_LIBS)
-librrd_la_LDFLAGS         = -version-info 0:0:0
+librrd_la_LDFLAGS         = -version-info 1:2:0
 
 include_HEADERS        = rrd.h
 
index ad08e85..da0f1ba 100644 (file)
@@ -144,7 +144,7 @@ enum ds_param_en {   DS_mrhb_cnt=0,       /* minimum required heartbeat. A
                                           * least every ds_mrhb seconds,
                                           * otherwise it is regarded dead and
                                           * will be set to UNKNOWN */             
-                            DS_min_val,          /* the processed input of a ds must */
+                    DS_min_val,          /* the processed input of a ds must */
                      DS_max_val,      /* be between max_val and min_val
                                           * both can be set to UNKNOWN if you
                                           * do not care. Data outside the limits
@@ -172,7 +172,7 @@ enum cf_en           { CF_AVERAGE=0,     /* data consolidation functions */
                        CF_MINIMUM, 
                        CF_MAXIMUM,
                        CF_LAST,
-                                          CF_HWPREDICT, 
+                      CF_HWPREDICT, 
                                           /* An array of predictions using the seasonal 
                                                * Holt-Winters algorithm. Requires an RRA of type
                                                * CF_SEASONAL for this data source. */
diff --git a/src/rrd_gfx.c b/src/rrd_gfx.c
new file mode 100644 (file)
index 0000000..715d8d2
--- /dev/null
@@ -0,0 +1,459 @@
+/****************************************************************************
+ * RRDtool 1.1.x  Copyright Tobias Oetiker, 1997 - 2002
+ ****************************************************************************
+ * rrd_gfx.c  graphics wrapper for rrdtool
+  **************************************************************************/
+
+/* #define DEBUG */
+
+#ifdef DEBUG
+# define DPRINT(x)    (void)(printf x, printf("\n"))
+#else
+# define DPRINT(x)
+#endif
+
+#include <png.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include "rrd_gfx.h"
+
+/* lines are better drawn on the pixle than between pixles */
+#define LINEOFFSET 0.5
+
+static
+gfx_node_t *gfx_new_node( gfx_canvas_t *canvas,enum gfx_en type){
+  gfx_node_t *node = art_new(gfx_node_t,1);
+  if (node == NULL) return NULL;
+  node->type = type;
+  node->color = 0x0;        /* color of element  0xRRGGBBAA  alpha 0xff is solid*/
+  node->size =0.0;         /* font size, line width */
+  node->path = NULL;        /* path */
+  node->points = 0;
+  node->points_max =0;
+  node->svp = NULL;         /* svp */
+  node->filename = NULL;             /* font or image filename */
+  node->text = NULL;
+  node->x = 0.0;
+  node->y = 0.0;          /* position */
+  node->halign = GFX_H_NULL; /* text alignement */
+  node->valign = GFX_V_NULL; /* text alignement */
+  node->tabwidth = 0.0; 
+  node->next = NULL; 
+  if (canvas->lastnode != NULL){
+      canvas->lastnode->next = node;
+  }
+  if (canvas->firstnode == NULL){
+      canvas->firstnode = node;
+  }  
+  canvas->lastnode = node;
+  return node;
+}
+
+gfx_canvas_t *gfx_new_canvas (void) {
+    gfx_canvas_t *canvas = art_new(gfx_canvas_t,1);
+    canvas->firstnode = NULL;
+    canvas->lastnode = NULL;
+    return canvas;    
+}
+
+/* create a new line */
+gfx_node_t  *gfx_new_line(gfx_canvas_t *canvas, 
+                          double x0, double y0, 
+                          double x1, double y1,
+                          double width, gfx_color_t color){
+
+  gfx_node_t *node;
+  ArtVpath *vec;
+  node = gfx_new_node(canvas,GFX_LINE);
+  if (node == NULL) return NULL;
+  vec = art_new(ArtVpath, 3);
+  if (vec == NULL) return NULL;
+  vec[0].code = ART_MOVETO_OPEN; vec[0].x=x0+LINEOFFSET; vec[0].y=y0+LINEOFFSET;
+  vec[1].code = ART_LINETO; vec[1].x=x1+LINEOFFSET; vec[1].y=y1+LINEOFFSET;
+  vec[2].code = ART_END;
+  
+  node->points = 3;
+  node->points_max = 3;
+  node->color = color;
+  node->size  = width;
+  node->path  = vec;
+  return node;
+}
+
+/* create a new area */
+gfx_node_t   *gfx_new_area   (gfx_canvas_t *canvas, 
+                             double x0, double y0,
+                             double x1, double y1,
+                             double x2, double y2,
+                             gfx_color_t color) {
+
+  gfx_node_t *node;
+  ArtVpath *vec;
+  node = gfx_new_node(canvas,GFX_AREA);
+  if (node == NULL) return NULL;
+  vec = art_new(ArtVpath, 5);
+  if (vec == NULL) return NULL;
+  vec[0].code = ART_MOVETO; vec[0].x=x0; vec[0].y=y0;
+  vec[1].code = ART_LINETO; vec[1].x=x1; vec[1].y=y1;
+  vec[2].code = ART_LINETO; vec[2].x=x2; vec[2].y=y2;
+  vec[3].code = ART_LINETO; vec[3].x=x0; vec[3].y=y0;
+  vec[4].code = ART_END;
+  
+  node->points = 5;
+  node->points_max = 5;
+  node->color = color;
+  node->path  = vec;
+
+  return node;
+}
+
+/* add a point to a line or to an area */
+int           gfx_add_point  (gfx_node_t *node, 
+                             double x, double y){
+  if (node == NULL) return 1;
+  if (node->type == GFX_AREA) {
+    double x0 = node->path[0].x;
+    double y0 = node->path[0].y;
+    node->points -= 2;
+    art_vpath_add_point (&(node->path),
+                         &(node->points),
+                         &(node->points_max),
+                         ART_LINETO,
+                         x,y);
+    art_vpath_add_point (&(node->path),
+                         &(node->points),
+                         &(node->points_max),
+                         ART_LINETO,
+                         x0,y0);
+    art_vpath_add_point (&(node->path),
+                         &(node->points),
+                         &(node->points_max),
+                         ART_END,
+                         0,0);
+  } else if (node->type == GFX_LINE) {
+    node->points -= 1;
+    art_vpath_add_point (&(node->path),
+                         &(node->points),
+                         &(node->points_max),
+                         ART_LINETO,
+                         x+LINEOFFSET,y+LINEOFFSET);
+    art_vpath_add_point (&(node->path),
+                         &(node->points),
+                         &(node->points_max),
+                         ART_END,
+                         0,0);
+    
+  } else {
+    /* can only add point to areas and lines */
+    return 1;
+  }
+  return 0;
+}
+
+
+
+/* create a text node */
+gfx_node_t   *gfx_new_text   (gfx_canvas_t *canvas,  
+                             double x, double y, gfx_color_t color,
+                             char* font, double size,                        
+                             double tabwidth, double angle,
+                             enum gfx_h_align_en h_align,
+                             enum gfx_v_align_en v_align,
+                              char* text){
+   gfx_node_t *node = gfx_new_node(canvas,GFX_TEXT);
+   if (angle != 0.0){
+       /* currently we only support 0 and 270 */
+       angle = 270.0;
+   }
+   
+   node->text = strdup(text);
+   node->size = size;
+   node->filename = strdup(font);
+   node->x = x;
+   node->y = y;
+   node->color = color;
+   node->tabwidth = tabwidth;
+   node->halign = h_align;
+   node->valign = v_align;
+   return node;
+}
+
+double gfx_get_text_width ( double start, char* font, double size,                           
+                           double tabwidth, char* text){
+
+  FT_GlyphSlot  slot;
+  FT_UInt       previous=0;
+  FT_UInt       glyph_index=0;
+  FT_Bool       use_kerning;
+  int           error;
+  FT_Face       face;
+  FT_Library    library=NULL;  
+  double        text_width=0;
+  FT_Init_FreeType( &library );
+  error = FT_New_Face( library, font, 0, &face );
+  if ( error ) return -1;
+  error = FT_Set_Char_Size(face,  size*64,size*64,  100,100);
+  if ( error ) return -1;
+
+  use_kerning = FT_HAS_KERNING(face);
+  slot = face->glyph;
+  for(;*text;text++) { 
+    previous = glyph_index;
+    glyph_index = FT_Get_Char_Index( face, *text);
+    
+    if (use_kerning && previous && glyph_index){
+      FT_Vector  delta;
+      FT_Get_Kerning( face, previous, glyph_index,
+                     0, &delta );
+      text_width += (double)delta.x / 64.0;
+      
+    }
+    error = FT_Load_Glyph( face, glyph_index, 0 );
+    if (! previous) {
+      text_width -= (double)slot->metrics.horiBearingX / 64.0; /* add just char width */       
+    }
+    text_width += (double)slot->metrics.horiAdvance / 64.0;
+  }
+  text_width -= (double)slot->metrics.horiAdvance / 64.0; /* remove last step */
+  text_width += (double)slot->metrics.width / 64.0; /* add just char width */
+  text_width += (double)slot->metrics.horiBearingX / 64.0; /* add just char width */
+  return text_width;
+}
+
+
+
+static int gfx_save_png (art_u8 *buffer, FILE *fp,
+                     long width, long height, long bytes_per_pixel);
+/* render grafics into png image */
+int           gfx_render_png (gfx_canvas_t *canvas, 
+                             art_u32 width, art_u32 height, 
+                             double zoom, 
+                             gfx_color_t background, FILE *fp){
+    
+    
+    FT_Library    library;
+    gfx_node_t *node = canvas->firstnode;    
+    art_u8 red = background >> 24, green = (background >> 16) & 0xff;
+    art_u8 blue = (background >> 8) & 0xff, alpha = ( background & 0xff );
+    unsigned long pys_width = width * zoom;
+    unsigned long pys_height = height * zoom;
+    const int bytes_per_pixel = 3;
+    unsigned long rowstride = pys_width*bytes_per_pixel; /* bytes per pixel */
+    art_u8 *buffer = art_new (art_u8, rowstride*pys_height);
+    art_rgb_run_alpha (buffer, red, green, blue, alpha, pys_width*pys_height);
+    FT_Init_FreeType( &library );
+    while(node){
+        switch (node->type) {
+        case GFX_LINE:
+        case GFX_AREA: {   
+            ArtVpath *vec;
+            double dst[6];     
+            ArtSVP *svp;
+            art_affine_scale(dst,zoom,zoom);
+            vec = art_vpath_affine_transform(node->path,dst);
+            if(node->type == GFX_LINE){
+                svp = art_svp_vpath_stroke ( vec, ART_PATH_STROKE_JOIN_ROUND,
+                                             ART_PATH_STROKE_CAP_ROUND,
+                                             node->size*zoom,1,1);
+            } else {
+                svp = art_svp_from_vpath ( vec );
+            }
+            art_free(vec);
+            art_rgb_svp_alpha (svp ,0,0, pys_width, pys_height,
+                               node->color, buffer, rowstride, NULL);
+            art_free(svp);
+            break;
+        }
+        case GFX_TEXT: {
+            int  error;
+            float text_width=0.0, text_height = 0.0;
+            unsigned char *text;
+            art_u8 fcolor[3],falpha;
+            FT_Face       face;
+            FT_GlyphSlot  slot;
+            FT_UInt       previous=0;
+            FT_UInt       glyph_index=0;
+           FT_Bool       use_kerning;
+
+            float pen_x = 0.0 , pen_y = 0.0;
+            /* double x,y; */
+            long   ix,iy,iz;
+            
+            fcolor[0] = node->color >> 24;
+            fcolor[1] = (node->color >> 16) & 0xff;
+            fcolor[2] = (node->color >> 8) & 0xff;
+            falpha = node->color & 0xff;
+            error = FT_New_Face( library,
+                                 (char *)node->filename,
+                                 0,
+                                 &face );
+            use_kerning = FT_HAS_KERNING(face);
+
+           if ( error ) break;
+            error = FT_Set_Char_Size(face,   /* handle to face object            */
+                                     (long)(node->size*64),
+                                     (long)(node->size*64),
+                                     (long)(100*zoom),
+                                     (long)(100*zoom));
+            pen_x = node->x * zoom;
+            pen_y = node->y * zoom;
+            slot = face->glyph;
+
+            for(text=(unsigned char *)node->text;*text;text++) {       
+                previous = glyph_index;
+                glyph_index = FT_Get_Char_Index( face, *text);
+                
+                if (use_kerning && previous && glyph_index){
+                    FT_Vector  delta;
+                    FT_Get_Kerning( face, previous, glyph_index,
+                                    0, &delta );
+                    text_width += (double)delta.x / 64.0;
+                    
+                }
+                error = FT_Load_Glyph( face, glyph_index, 0 );
+               if (previous == 0){
+                 pen_x -= (double)slot->metrics.horiBearingX / 64.0; /* adjust pos for first char */   
+                 text_width -= (double)slot->metrics.horiBearingX / 64.0; /* add just char width */    
+                }
+               if ( text_height < (double)slot->metrics.horiBearingY / 64.0 ) {
+                 text_height = (double)slot->metrics.horiBearingY / 64.0;
+               }
+                text_width += (double)slot->metrics.horiAdvance / 64.0;
+            }
+            text_width -= (double)slot->metrics.horiAdvance / 64.0; /* remove last step */
+            text_width += (double)slot->metrics.width / 64.0; /* add just char width */
+            text_width += (double)slot->metrics.horiBearingX / 64.0; /* add just char width */
+            
+            switch(node->halign){
+            case GFX_H_RIGHT:  pen_x -= text_width; break;
+            case GFX_H_CENTER: pen_x -= text_width / 2.0; break;          
+            case GFX_H_LEFT: break;          
+            }
+
+            switch(node->valign){
+            case GFX_V_TOP:    pen_y += text_height; break;
+            case GFX_V_CENTER: pen_y += text_height / 2.0; break;          
+            case GFX_V_BOTTOM: break;          
+            }
+
+            glyph_index=0;
+            for(text=(unsigned char *)node->text;*text;text++) {
+                int gr;          
+                previous = glyph_index;
+                glyph_index = FT_Get_Char_Index( face, *text);
+                
+                if (use_kerning && previous && glyph_index){
+                    FT_Vector  delta;
+                    FT_Get_Kerning( face, previous, glyph_index,
+                                    0, &delta );
+                    pen_x += (double)delta.x / 64.0;
+                    
+                }
+                error = FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER );
+                gr = slot->bitmap.num_grays -1;
+                for (iy=0; iy < slot->bitmap.rows; iy++){
+                    long buf_y = iy+(pen_y+0.5)-slot->bitmap_top;
+                    if (buf_y < 0 || buf_y >= pys_height) continue;
+                    buf_y *= rowstride;
+                    for (ix=0;ix < slot->bitmap.width;ix++){
+                        long buf_x = ix + (pen_x + 0.5) + (double)slot->bitmap_left ;
+                        art_u8 font_alpha;
+                        
+                        if (buf_x < 0 || buf_x >= pys_width) continue;
+                        buf_x *=  bytes_per_pixel ;
+                        font_alpha =  *(slot->bitmap.buffer + iy * slot->bitmap.width + ix);
+                        font_alpha =  (art_u8)((double)font_alpha / gr * falpha);
+                        for (iz = 0; iz < 3; iz++){
+                            art_u8 *orig = buffer + buf_y + buf_x + iz;
+                            *orig =  (art_u8)((double)*orig / gr * ( gr - font_alpha) +
+                                              (double)fcolor[iz] / gr * (font_alpha));
+                        }
+                    }
+                }
+                pen_x += (double)slot->metrics.horiAdvance / 64.0;
+            }
+        }
+        }
+        node = node->next;
+    }  
+    gfx_save_png(buffer,fp , pys_width,pys_height,bytes_per_pixel);
+    art_free(buffer);
+    return 0;    
+}
+
+/* free memory used by nodes this will also remove memory required for
+   associated paths and svcs ... but not for text strings */
+int
+gfx_destroy    (gfx_canvas_t *canvas){  
+  gfx_node_t *next,*node = canvas->firstnode;
+  while(node){
+    next = node->next;
+    art_free(node->path);
+    art_free(node->svp);
+    free(node->text);
+    free(node->filename);
+    art_free(node);
+    node = next;
+  }
+  return 0;
+}
+static int gfx_save_png (art_u8 *buffer, FILE *fp,  long width, long height, long bytes_per_pixel){
+  png_structp png_ptr = NULL;
+  png_infop   info_ptr = NULL;
+  int i;
+  png_bytep *row_pointers;
+  int rowstride = width * bytes_per_pixel;
+  png_text text[2];
+  
+  if (fp == NULL)
+    return (1);
+
+  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
+  if (png_ptr == NULL)
+   {
+      return (1);
+   }
+   row_pointers = (png_bytepp)png_malloc(png_ptr,
+                                     height*sizeof(png_bytep));
+
+  info_ptr = png_create_info_struct(png_ptr);
+
+  if (info_ptr == NULL)
+    {
+      png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
+      return (1);
+    }
+
+  if (setjmp(png_jmpbuf(png_ptr)))
+    {
+      /* If we get here, we had a problem writing the file */
+      png_destroy_write_struct(&png_ptr, &info_ptr);
+      return (1);
+    }
+
+  png_init_io(png_ptr, fp);
+  png_set_IHDR (png_ptr, info_ptr,width, height,
+                8, PNG_COLOR_TYPE_RGB,
+                PNG_INTERLACE_NONE,
+                PNG_COMPRESSION_TYPE_DEFAULT,
+                PNG_FILTER_TYPE_DEFAULT);
+
+  text[0].key = "Software";
+  text[0].text = "RRDtool, Tobias Oetiker <tobi@oetike.ch>, http://tobi.oetiker.ch";
+  text[0].compression = PNG_TEXT_COMPRESSION_NONE;
+  png_set_text (png_ptr, info_ptr, text, 1);
+
+  /* Write header data */
+  png_write_info (png_ptr, info_ptr);
+
+  for (i = 0; i < height; i++)
+    row_pointers[i] = (png_bytep) (buffer + i*rowstride);
+
+  png_write_image(png_ptr, row_pointers);
+  png_write_end(png_ptr, info_ptr);
+  png_destroy_write_struct(&png_ptr, &info_ptr);
+  return 1;
+}
diff --git a/src/rrd_gfx.h b/src/rrd_gfx.h
new file mode 100644 (file)
index 0000000..808b7c4
--- /dev/null
@@ -0,0 +1,90 @@
+/****************************************************************************
+ * RRDtool 1.1.x  Copyright Tobias Oetiker, 1997 - 2001
+ ****************************************************************************
+ * rrd_gfx.h generic graphics adapter library
+ ****************************************************************************/
+
+#ifndef  RRD_GFX_H
+#define RRD_GFX_H
+#define LIBART_COMPILATION
+#include <libart.h>
+
+enum gfx_en { GFX_LINE=0,GFX_AREA,GFX_TEXT };
+enum gfx_h_align_en { GFX_H_NULL=0, GFX_H_LEFT, GFX_H_RIGHT, GFX_H_CENTER };
+enum gfx_v_align_en { GFX_V_NULL=0, GFX_V_TOP,  GFX_V_BOTTOM, GFX_V_CENTER };
+typedef unsigned long gfx_color_t;
+
+typedef struct  gfx_node_t {
+  enum gfx_en   type;         /* type of graph element */
+  gfx_color_t   color;        /* color of element  0xRRGGBBAA  alpha 0xff is solid*/
+  double        size;         /* font size, line width */
+  ArtVpath      *path;        /* path */
+  int           points;
+  int           points_max;
+  ArtSVP        *svp;         /* svp */
+  char *filename;             /* font or image filename */
+  char *text;
+  double        x,y;          /* position */
+  enum gfx_h_align_en halign; /* text alignement */
+  enum gfx_v_align_en valign; /* text alignement */
+  double        tabwidth; 
+  struct gfx_node_t  *next; 
+} gfx_node_t;
+
+
+typedef struct gfx_canvas_t 
+{
+    struct gfx_node_t *firstnode;
+    struct gfx_node_t *lastnode;
+} gfx_canvas_t;
+
+
+gfx_canvas_t *gfx_new_canvas (void);
+
+/* create a new line */
+gfx_node_t   *gfx_new_line   (gfx_canvas_t *canvas, 
+                             double x0, double y0, 
+                             double x1, double y1,
+                             double width, gfx_color_t color);
+
+/* create a new area */
+gfx_node_t   *gfx_new_area   (gfx_canvas_t *canvas, 
+                             double x0, double y0,
+                             double x1, double y1,
+                             double x2, double y2,
+                             gfx_color_t  color);
+
+/* add a point to a line or to an area */
+int           gfx_add_point  (gfx_node_t *node, double x, double y);
+
+
+/* create a text node */
+gfx_node_t   *gfx_new_text   (gfx_canvas_t *canvas,  
+                             double x, double y, gfx_color_t color,
+                             char* font, double size,                        
+                             double tabwidth, double angle,
+                             enum gfx_h_align_en h_align,
+                             enum gfx_v_align_en v_align,
+                              char* text);
+
+/* measure width of a text string */
+double gfx_get_text_width ( double start, char* font, double size,                           
+                           double tabwidth, char* text);
+
+
+
+/* turn graph into a png image */
+int       gfx_render_png (gfx_canvas_t *canvas,
+                              art_u32 width, art_u32 height,
+                              double zoom,
+                              gfx_color_t background, FILE *fo);
+                                                                                          
+                                                                                         
+/* free memory used by nodes this will also remove memory required for
+   node chain and associated material */
+int           gfx_destroy    (gfx_canvas_t *canvas); 
+
+#endif
+
+
+
index fd48b7a..8900872 100644 (file)
@@ -8,9 +8,6 @@
 #include "rrd_tool.h"
 #endif
 
-#include <gd.h>
-#include <gdlucidan10.h>
-#include <gdlucidab12.h>
 #include <sys/stat.h>
 #ifdef WIN32
 #include <io.h>
 #include "rrd_graph.h"
 #include "rrd_graph_helper.h"
 
-#define SmallFont gdLucidaNormal10
-#define LargeFont gdLucidaBold12
+/* some constant definitions */
 
-/* #define DEBUG */
 
-#ifdef DEBUG
-# define DPRINT(x)    (void)(printf x, printf("\n"))
-#else
-# define DPRINT(x)
+#ifndef RRD_DEFAULT_FONT
+#define RRD_DEFAULT_FONT "/usr/openwin/lib/X11/fonts/TrueType/Arial.ttf" 
+/* #define RRD_DEFAULT_FONT "/usr/share/fonts/truetype/Arial.ttf" */
 #endif
 
+
+text_prop_t text_prop[] = {   
+     { 10.0, RRD_DEFAULT_FONT }, /* default */
+     { 12.0, RRD_DEFAULT_FONT }, /* title */
+     { 8.0,  RRD_DEFAULT_FONT },  /* axis */
+     { 10.0, RRD_DEFAULT_FONT },  /* unit */
+     { 10.0, RRD_DEFAULT_FONT }  /* legend */
+};
+
 xlab_t xlab[] = {
     {0,        TMT_SECOND,30, TMT_MINUTE,5,  TMT_MINUTE,5,         0,"%H:%M"},
     {2,        TMT_MINUTE,1,  TMT_MINUTE,5,  TMT_MINUTE,5,         0,"%H:%M"},
@@ -81,24 +84,28 @@ ylab_t ylab[]= {
     {0.0,   {0,0,0,0}}};
 
 
-
-col_trip_t graph_col[] = { /* default colors */
-    {255,255,255,-1},   /* canvas */
-    {245,245,245,-1},   /* background */
-    {200,200,200,-1},   /* shade A    */
-    {150,150,150,-1},   /* shade B    */
-    {140,140,140,-1},      /* grid */
-    {130,30,30,-1},      /* major grid */
-    {0,0,0,-1},         /* font */     
-    {0,0,0,-1},         /* frame */
-    {255,0,0,-1}       /*arrow*/
+gfx_color_t graph_col[] =   /* default colors */
+{    0xFFFFFFFF,   /* canvas     */
+     0xF0F0F0FF,   /* background */
+     0xD0D0D0FF,   /* shade A    */
+     0xA0A0A0FF,   /* shade B    */
+     0x909090FF,   /* grid       */
+     0xE05050FF,   /* major grid */
+     0x000000FF,   /* font       */ 
+     0x000000FF,   /* frame      */
+     0xFF0000FF  /* arrow      */
 };
 
 
-/* translate time values into x coordinates */   
-/*#define xtr(x) (int)((double)im->xorigin \
-               + ((double) im->xsize / (double)(im->end - im->start) ) \
-               * ((double)(x) - im->start)+0.5) */
+/* #define DEBUG */
+
+#ifdef DEBUG
+# define DPRINT(x)    (void)(printf x, printf("\n"))
+#else
+# define DPRINT(x)
+#endif
+
+
 /* initialize with xtr(im,0); */
 int
 xtr(image_desc_t *im,time_t mytime){
@@ -112,10 +119,6 @@ xtr(image_desc_t *im,time_t mytime){
 }
 
 /* translate data values into y coordinates */
-
-/* #define ytr(x) (int)((double)im->yorigin \
-               - ((double) im->ysize / (im->maxval - im->minval) ) \
-               * ((double)(x) - im->minval)+0.5) */
 int
 ytr(image_desc_t *im, double value){
     static double pixie;
@@ -164,12 +167,10 @@ enum gf_en gf_conv(char *string){
     conv_if(COMMENT,GF_COMMENT)
     conv_if(HRULE,GF_HRULE)
     conv_if(VRULE,GF_VRULE)
-    conv_if(LINE1,GF_LINE1)
-    conv_if(LINE2,GF_LINE2)
-    conv_if(LINE3,GF_LINE3)
+    conv_if(LINE,GF_LINE)
     conv_if(AREA,GF_AREA)
     conv_if(STACK,GF_STACK)
-       conv_if(TICK,GF_TICK)
+    conv_if(TICK,GF_TICK)
     conv_if(DEF,GF_DEF)
     conv_if(CDEF,GF_CDEF)
     conv_if(VDEF,GF_VDEF)
@@ -212,6 +213,17 @@ enum grc_en grc_conv(char *string){
     return -1; 
 }
 
+enum text_prop_en text_prop_conv(char *string){
+      
+    conv_if(DEFAULT,TEXT_PROP_DEFAULT)
+    conv_if(TITLE,TEXT_PROP_TITLE)
+    conv_if(AXIS,TEXT_PROP_AXIS)
+    conv_if(UNIT,TEXT_PROP_UNIT)
+    conv_if(LEGEND,TEXT_PROP_LEGEND)
+    return -1;
+}
+
+
 #undef conv_if
 
 
@@ -867,9 +879,7 @@ data_proc( image_desc_t *im ){
 
     /* memory for the processed data */
     for(i=0;i<im->gdes_c;i++){
-      if((im->gdes[i].gf==GF_LINE1) ||
-        (im->gdes[i].gf==GF_LINE2) ||
-        (im->gdes[i].gf==GF_LINE3) ||
+      if((im->gdes[i].gf==GF_LINE) ||
         (im->gdes[i].gf==GF_AREA) ||
         (im->gdes[i].gf==GF_TICK) ||
         (im->gdes[i].gf==GF_STACK)){
@@ -890,9 +900,7 @@ data_proc( image_desc_t *im ){
        for(ii=0;ii<im->gdes_c;ii++){
          double value;
            switch(im->gdes[ii].gf){
-           case GF_LINE1:
-           case GF_LINE2:
-           case GF_LINE3:
+           case GF_LINE:
            case GF_AREA:
                case GF_TICK:
                paintval = 0.0;
@@ -1060,53 +1068,6 @@ find_next_time(
          
 }
 
-void gator( gdImagePtr gif, int x, int y){ 
-
-/* this function puts the name of the author and the tool into the
-   graph. Remove if you must, but please note, that it is here,
-   because I would like people who look at rrdtool generated graphs to
-   see what was used to do it. No obviously you can also add a credit
-   line to your webpage or printed document, this is fine with me. But
-   as I have no control over this, I added the little tag in here. 
-*/
-
-/* the fact that the text of what gets put into the graph is not
-   visible in the function, has lead some to think this is for
-   obfuscation reasons. While this is a nice side effect (I addmit),
-   it is not the prime reason. The prime reason is, that the font
-   used, is so small, that I had to hand edit the characters to ensure
-   readability. I could thus not use the normal gd functions to write,
-   but had to embed a slightly compressed bitmap version into the code. 
-*/
-
-    int li[]={0,0,1, 0,4,5, 0,8,9, 0,12,14, 0,17,17, 0,21,21, 
-             0,24,24, 0,34,34, 0,40,42, 0,45,45, 0,48,49, 0,52,54, 
-             0,61,61, 0,64,66, 0,68,70, 0,72,74, 0,76,76, 0,78,78, 
-             0,80,82, 0,84,85, 
-             1,0,0, 1,2,2, 1,4,4, 1,6,6, 1,8,8, 1,10,10, 
-             1,13,13, 1,16,16, 1,18,18, 1,20,20, 1,22,22, 1,24,24, 
-             1,34,34, 1,41,41, 1,44,44, 1,46,46, 1,48,48, 1,50,50, 
-             1,53,53, 1,60,60, 1,62,62, 1,64,64, 1,69,69, 1,73,73, 
-             1,76,76, 1,78,78, 1,80,80, 1,84,84, 1,86,86, 
-             2,0,1, 2,4,5, 2,8,8, 2,10,10, 2,13,13, 2,16,16, 
-             2,18,18, 2,20,20, 2,22,22, 2,24,24, 2,33,33, 2,41,41, 
-             2,44,44, 2,46,46, 2,48,49, 2,53,53, 2,60,60, 2,62,62, 
-             2,64,65, 2,69,69, 2,73,73, 2,76,77, 2,80,81, 2,84,85,           
-             3,0,0, 3,2,2, 3,4,4, 3,6,6, 3,8,8, 3,10,10, 
-             3,13,13, 3,16,16, 3,18,18, 3,20,20, 3,22,22, 3,24,24, 
-             3,32,32, 3,41,41, 3,44,44, 3,46,46, 3,48,48, 3,50,50, 
-             3,53,53, 3,60,60, 3,62,62, 3,64,64, 3,69,69, 3,73,73, 
-             3,76,76, 3,78,78, 3,80,80, 3,84,84, 3,86,86, 
-             4,0,0, 4,2,2, 4,4,4, 4,6,6, 4,8,9, 4,13,13, 
-             4,17,17, 4,21,21, 4,24,26, 4,32,32, 4,41,41, 4,45,45, 
-             4,48,49, 4,52,54, 4,61,61, 4,64,66, 4,69,69, 4,72,74, 
-             4,76,76, 4,78,78, 4,80,82, 4,84,84}; 
-    int i,ii; 
-    for(i=0; i<DIM(li); i=i+3)
-       for(ii=y+li[i+1]; ii<=y+li[i+2];ii++)
-         gdImageSetPixel(gif,x-li[i],ii,graph_col[GRC_GRID].i); 
-}
-
 
 /* calculate values required for PRINT and GPRINT functions */
 
@@ -1245,9 +1206,7 @@ print_calc(image_desc_t *im, char ***prdata)
            }
            break;
         case GF_COMMENT:
-       case GF_LINE1:
-       case GF_LINE2:
-       case GF_LINE3:
+       case GF_LINE:
        case GF_AREA:
        case GF_TICK:
        case GF_STACK:
@@ -1270,9 +1229,9 @@ int
 leg_place(image_desc_t *im)
 {
     /* graph labels */
-    int   interleg = SmallFont->w*2;
-    int   box = SmallFont->h*1.2;
-    int   border = SmallFont->w*2;
+    int   interleg = im->text_prop[TEXT_PROP_LEGEND].size*2.0;
+    int   box =im->text_prop[TEXT_PROP_LEGEND].size*1.5;
+    int   border = im->text_prop[TEXT_PROP_LEGEND].size*2.0;
     int   fill=0, fill_last;
     int   leg_c = 0;
     int   leg_x = border, leg_y = im->ygif;
@@ -1319,7 +1278,10 @@ leg_place(image_desc_t *im)
                im->gdes[i].gf != GF_COMMENT) { 
                fill += box;       
            }
-           fill += leg_cc * SmallFont->w;
+          fill += gfx_get_text_width(fill+border,im->text_prop[TEXT_PROP_LEGEND].font,
+                                     im->text_prop[TEXT_PROP_LEGEND].size,
+                                     im->tabwidth,
+                                     im->gdes[i].legend);
            leg_c++;
        } else {
           legspace[i]=0;
@@ -1351,7 +1313,6 @@ leg_place(image_desc_t *im)
            leg_x = border;
            if (leg_c >= 2 && prt_fctn == 'j') {
                glue = (im->xgif - fill - 2* border) / (leg_c-1);
-               /* if (glue > 2 * SmallFont->w) glue = 0; */
            } else {
                glue = 0;
            }
@@ -1361,18 +1322,21 @@ leg_place(image_desc_t *im)
            for(ii=mark;ii<=i;ii++){
                if(im->gdes[ii].legend[0]=='\0')
                    continue;
-               im->gdes[ii].legloc.x = leg_x;
-               im->gdes[ii].legloc.y = leg_y;
-               leg_x =  leg_x 
-                   + strlen(im->gdes[ii].legend)*SmallFont->w 
-                   + legspace[ii]
-                   + glue;
+               im->gdes[ii].leg_x = leg_x;
+               im->gdes[ii].leg_y = leg_y;
+               leg_x += 
+                gfx_get_text_width(leg_x,im->text_prop[TEXT_PROP_LEGEND].font,
+                                     im->text_prop[TEXT_PROP_LEGEND].size,
+                                     im->tabwidth,
+                                     im->gdes[i].legend) 
+                  + legspace[ii]
+                  + glue;
                if (im->gdes[ii].gf != GF_GPRINT && 
                    im->gdes[ii].gf != GF_COMMENT) 
                    leg_x += box;          
            }       
-           leg_y = leg_y + SmallFont->h*1.2;
-           if (prt_fctn == 's') leg_y -= SmallFont->h *0.5;
+           leg_y = leg_y + im->text_prop[TEXT_PROP_LEGEND].size*1.2;
+           if (prt_fctn == 's') leg_y -=  im->text_prop[TEXT_PROP_LEGEND].size*1.2;       
            fill = 0;
            leg_c = 0;
            mark = ii;
@@ -1393,7 +1357,7 @@ leg_place(image_desc_t *im)
 
 
 int
-horizontal_grid(gdImagePtr gif, image_desc_t   *im)
+horizontal_grid(gfx_canvas_t *canvas, image_desc_t   *im)
 {
     double   range;
     double   scaledrange;
@@ -1402,9 +1366,8 @@ horizontal_grid(gdImagePtr gif, image_desc_t   *im)
     double   gridstep;
     double   scaledstep;
     char     graph_label[100];
-    gdPoint  polyPoints[4];
+    double   x0,x1,y0,y1;
     int      labfact,gridind;
-    int      styleMinor[2],styleMajor[2];
     int      decimals, fractionals;
     char     labfmt[64];
 
@@ -1419,12 +1382,6 @@ horizontal_grid(gdImagePtr gif, image_desc_t   *im)
                return 0;
        }
 
-    styleMinor[0] = graph_col[GRC_GRID].i;
-    styleMinor[1] = gdTransparent;
-
-    styleMajor[0] = graph_col[GRC_MGRID].i;
-    styleMajor[1] = gdTransparent;
-
     /* find grid spaceing */
     pixel=1;
     if(isnan(im->ygridstep)){
@@ -1467,10 +1424,10 @@ horizontal_grid(gdImagePtr gif, image_desc_t   *im)
            }
            
            for(i=0; i<4;i++) {
-               if (pixel * ylab[gridind].lfac[i] >=  2 * SmallFont->h) {
-                   labfact =  ylab[gridind].lfac[i];
-                   break;
-               }                         
+              if (pixel * ylab[gridind].lfac[i] >=  2 * im->text_prop[TEXT_PROP_AXIS].size) {
+                 labfact =  ylab[gridind].lfac[i];
+                 break;
+              }                          
            } 
            
            gridstep = ylab[gridind].grid * im->magfact;
@@ -1480,15 +1437,16 @@ horizontal_grid(gdImagePtr gif, image_desc_t   *im)
        labfact = im->ylabfact;
     }
     
-    polyPoints[0].x=im->xorigin;
-    polyPoints[1].x=im->xorigin+im->xsize;
+   x0=im->xorigin;
+   x1=im->xorigin+im->xsize;
+   
     sgrid = (int)( im->minval / gridstep - 1);
     egrid = (int)( im->maxval / gridstep + 1);
     scaledstep = gridstep/im->magfact;
     for (i = sgrid; i <= egrid; i++){
-       polyPoints[0].y=ytr(im,gridstep*i);
-       if ( polyPoints[0].y >= im->yorigin-im->ysize
-            && polyPoints[0].y <= im->yorigin) {
+       y0=ytr(im,gridstep*i);
+       if ( y0 >= im->yorigin-im->ysize
+                && y0 <= im->yorigin){       
            if(i % labfact == 0){               
                if (i==0 || im->symbol == ' ') {
                    if(scaledstep < 1){
@@ -1509,48 +1467,39 @@ horizontal_grid(gdImagePtr gif, image_desc_t   *im)
                    }
                }
 
-               gdImageString(gif, SmallFont,
-                              (polyPoints[0].x - (strlen(graph_label) * 
-                                                  SmallFont->w)-7), 
-                              polyPoints[0].y - SmallFont->h/2+1,
-                              (unsigned char *)graph_label, graph_col[GRC_FONT].i);
-               
-               gdImageSetStyle(gif, styleMajor, 2);
-
-               gdImageLine(gif, polyPoints[0].x-2,polyPoints[0].y,
-                           polyPoints[0].x+2,polyPoints[0].y,graph_col[GRC_MGRID].i);
-               gdImageLine(gif, polyPoints[1].x-2,polyPoints[0].y,
-                           polyPoints[1].x+2,polyPoints[0].y,graph_col[GRC_MGRID].i);              
+              gfx_new_text ( canvas,
+                             x0-im->text_prop[TEXT_PROP_AXIS].size/1.5, y0,
+                             im->graph_col[GRC_FONT],
+                             im->text_prop[TEXT_PROP_AXIS].font,
+                             im->text_prop[TEXT_PROP_AXIS].size,
+                             im->tabwidth, 0.0, GFX_H_RIGHT, GFX_V_CENTER,
+                             graph_label );
+              gfx_new_line ( canvas,
+                             x0-2,y0,
+                             x1+2,y0,
+                             MGRIDWIDTH, im->graph_col[GRC_MGRID] );          
+              
            } else {            
-               gdImageSetStyle(gif, styleMinor, 2);
-               gdImageLine(gif, polyPoints[0].x-1,polyPoints[0].y,
-                           polyPoints[0].x+1,polyPoints[0].y,graph_col[GRC_GRID].i);
-               gdImageLine(gif, polyPoints[1].x-1,polyPoints[0].y,
-                           polyPoints[1].x+1,polyPoints[0].y,graph_col[GRC_GRID].i);               
+              gfx_new_line ( canvas,
+                             x0-1,y0,
+                             x1+1,y0,
+                             GRIDWIDTH, im->graph_col[GRC_GRID] );            
+              
            }       
-           gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
-                       polyPoints[1].x,polyPoints[0].y,gdStyled);
        }       
     } 
-/*    if(im->minval * im->maxval < 0){
-      polyPoints[0].y=ytr(0);
-      gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
-      polyPoints[1].x,polyPoints[0].y,graph_col[GRC_MGRID].i);
-      } */
-
     return 1;
 }
 
 /* logaritmic horizontal grid */
 int
-horizontal_log_grid(gdImagePtr gif, image_desc_t   *im)
+horizontal_log_grid(gfx_canvas_t *canvas, image_desc_t   *im)   
 {
     double   pixpex;
     int      ii,i;
     int      minoridx=0, majoridx=0;
     char     graph_label[100];
-    gdPoint  polyPoints[4];
-    int      styleMinor[2],styleMajor[2];
+    double   x0,x1,y0,y1;   
     double   value, pixperstep, minstep;
 
     /* find grid spaceing */
@@ -1570,17 +1519,11 @@ horizontal_log_grid(gdImagePtr gif, image_desc_t   *im)
        }
        pixperstep = pixpex * minstep;
        if(pixperstep > 5){minoridx = i;}
-       if(pixperstep > 2 * SmallFont->h){majoridx = i;}
+       if(pixperstep > 2 *  im->text_prop[TEXT_PROP_LEGEND].size){majoridx = i;}
     }
    
-    styleMinor[0] = graph_col[GRC_GRID].i;
-    styleMinor[1] = gdTransparent;
-
-    styleMajor[0] = graph_col[GRC_MGRID].i;
-    styleMajor[1] = gdTransparent;
-
-    polyPoints[0].x=im->xorigin;
-    polyPoints[1].x=im->xorigin+im->xsize;
+   x0=im->xorigin;
+   x1=im->xorigin+im->xsize;
     /* paint minor grid */
     for (value = pow((double)10, log10(im->minval) 
                          - fmod(log10(im->minval),log10(yloglab[minoridx][0])));
@@ -1589,16 +1532,12 @@ horizontal_log_grid(gdImagePtr gif, image_desc_t   *im)
        if (value < im->minval) continue;
        i=0;    
        while(yloglab[minoridx][++i] > 0){          
-           polyPoints[0].y = ytr(im,value * yloglab[minoridx][i]);
-           if (polyPoints[0].y <= im->yorigin - im->ysize) break;
-           gdImageSetStyle(gif, styleMinor, 2);
-           gdImageLine(gif, polyPoints[0].x-1,polyPoints[0].y,
-                       polyPoints[0].x+1,polyPoints[0].y,graph_col[GRC_GRID].i);
-           gdImageLine(gif, polyPoints[1].x-1,polyPoints[0].y,
-                       polyPoints[1].x+1,polyPoints[0].y,graph_col[GRC_GRID].i);           
-
-           gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
-                       polyPoints[1].x,polyPoints[0].y,gdStyled);
+          y0 = ytr(im,value * yloglab[minoridx][i]);
+          if (y0 <= im->yorigin - im->ysize) break;
+          gfx_new_line ( canvas,
+                         x0-1,y0,
+                         x1+1,y0,
+                         GRIDWIDTH, im->graph_col[GRC_GRID] );
        }
     }
 
@@ -1610,22 +1549,21 @@ horizontal_log_grid(gdImagePtr gif, image_desc_t   *im)
        if (value < im->minval) continue;
        i=0;    
        while(yloglab[majoridx][++i] > 0){          
-           polyPoints[0].y = ytr(im,value * yloglab[majoridx][i]);         
-           if (polyPoints[0].y <= im->yorigin - im->ysize) break;
-           gdImageSetStyle(gif, styleMajor, 2);
-           gdImageLine(gif, polyPoints[0].x-2,polyPoints[0].y,
-                       polyPoints[0].x+2,polyPoints[0].y,graph_col[GRC_MGRID].i);
-           gdImageLine(gif, polyPoints[1].x-2,polyPoints[0].y,
-                       polyPoints[1].x+2,polyPoints[0].y,graph_col[GRC_MGRID].i);                  
-           
-           gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
-                       polyPoints[1].x,polyPoints[0].y,gdStyled);
-           sprintf(graph_label,"%3.0e",value * yloglab[majoridx][i]);
-           gdImageString(gif, SmallFont,
-                         (polyPoints[0].x - (strlen(graph_label) * 
-                                             SmallFont->w)-7), 
-                         polyPoints[0].y - SmallFont->h/2+1,
-                         (unsigned char *)graph_label, graph_col[GRC_FONT].i); 
+          y0 = ytr(im,value * yloglab[majoridx][i]);    
+          if (y0 <= im->yorigin - im->ysize) break;
+          gfx_new_line ( canvas,
+                         x0-2,y0,
+                         x1+2,y0,
+                         MGRIDWIDTH, im->graph_col[GRC_MGRID] );
+          
+          sprintf(graph_label,"%3.0e",value * yloglab[majoridx][i]);
+          gfx_new_text ( canvas,
+                         x0-im->text_prop[TEXT_PROP_AXIS].size/1.5, y0,
+                         im->graph_col[GRC_FONT],
+                         im->text_prop[TEXT_PROP_AXIS].font,
+                         im->text_prop[TEXT_PROP_AXIS].size,
+                         im->tabwidth,0.0, GFX_H_RIGHT, GFX_V_CENTER,
+                         graph_label );
        } 
     }
        return 1;
@@ -1634,19 +1572,16 @@ horizontal_log_grid(gdImagePtr gif, image_desc_t   *im)
 
 void
 vertical_grid(
-    gdImagePtr     gif,
+    gfx_canvas_t   *canvas,
     image_desc_t   *im )
 {   
     int xlab_sel;              /* which sort of label and grid ? */
     time_t ti, tilab;
     long factor;
     char graph_label[100];
-    gdPoint polyPoints[4];      /* points for filled graph and more*/
-
-    /* style for grid lines */
-    int     styleDotted[4];
+    double x0,y0,y1; /* points for filled graph and more*/
+   
 
-    
     /* the type of time grid is determined by finding
        the number of seconds per pixel in the graph */
     
@@ -1667,8 +1602,9 @@ vertical_grid(
     }
     
     /* y coords are the same for every line ... */
-    polyPoints[0].y = im->yorigin;
-    polyPoints[1].y = im->yorigin-im->ysize;
+    y0 = im->yorigin;
+    y1 = im->yorigin-im->ysize;
+   
 
     /* paint the minor grid */
     for(ti = find_first_time(im->start,
@@ -1679,18 +1615,9 @@ vertical_grid(
        ){
        /* are we inside the graph ? */
        if (ti < im->start || ti > im->end) continue;
-       polyPoints[0].x = xtr(im,ti);
-       styleDotted[0] = graph_col[GRC_GRID].i;
-       styleDotted[1] = gdTransparent;
-
-       gdImageSetStyle(gif, styleDotted, 2);
-
-       gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
-                   polyPoints[0].x,polyPoints[1].y,gdStyled);
-       gdImageLine(gif, polyPoints[0].x,polyPoints[0].y-1,
-                   polyPoints[0].x,polyPoints[0].y+1,graph_col[GRC_GRID].i);
-       gdImageLine(gif, polyPoints[0].x,polyPoints[1].y-1,
-                   polyPoints[0].x,polyPoints[1].y+1,graph_col[GRC_GRID].i);
+       x0 = xtr(im,ti);       
+       gfx_new_line(canvas,x0,y0+1, x0,y1-1,GRIDWIDTH, im->graph_col[GRC_GRID]);
+       
     }
 
     /* paint the major grid */
@@ -1702,17 +1629,9 @@ vertical_grid(
        ){
        /* are we inside the graph ? */
        if (ti < im->start || ti > im->end) continue;
-       polyPoints[0].x = xtr(im,ti);
-       styleDotted[0] = graph_col[GRC_MGRID].i;
-       styleDotted[1] = gdTransparent;
-       gdImageSetStyle(gif, styleDotted, 2);
-
-       gdImageLine(gif, polyPoints[0].x,polyPoints[0].y,
-                   polyPoints[0].x,polyPoints[1].y,gdStyled);
-       gdImageLine(gif, polyPoints[0].x,polyPoints[0].y-2,
-                   polyPoints[0].x,polyPoints[0].y+2,graph_col[GRC_MGRID].i);
-       gdImageLine(gif, polyPoints[0].x,polyPoints[1].y-2,
-                   polyPoints[0].x,polyPoints[1].y+2,graph_col[GRC_MGRID].i);
+       x0 = xtr(im,ti);
+       gfx_new_line(canvas,x0,y0+2, x0,y1-2,MGRIDWIDTH, im->graph_col[GRC_MGRID]);
+       
     }
     /* paint the labels below the graph */
     for(ti = find_first_time(im->start,
@@ -1721,7 +1640,6 @@ vertical_grid(
        ti <= im->end; 
        ti = find_next_time(ti,im->xlab_user.labtm,im->xlab_user.labst)
        ){
-       int gr_pos,width;
         tilab= ti + im->xlab_user.precis/2; /* correct time for the label */
 
 #if HAVE_STRFTIME
@@ -1729,13 +1647,14 @@ vertical_grid(
 #else
 # error "your libc has no strftime I guess we'll abort the exercise here."
 #endif
-       width=strlen(graph_label) *  SmallFont->w;
-       gr_pos=xtr(im,tilab) - width/2;
-       if (gr_pos  >= im->xorigin 
-           && gr_pos + width <= im->xorigin+im->xsize) 
-           gdImageString(gif, SmallFont,
-                         gr_pos,  polyPoints[0].y+4,
-                         (unsigned char *)graph_label, graph_col[GRC_FONT].i);
+       gfx_new_text ( canvas,
+                     xtr(im,tilab), y0+im->text_prop[TEXT_PROP_AXIS].size/1.5,
+                     im->graph_col[GRC_FONT],
+                     im->text_prop[TEXT_PROP_AXIS].font,
+                     im->text_prop[TEXT_PROP_AXIS].size,
+                     im->tabwidth, 0.0, GFX_H_CENTER, GFX_V_TOP,
+                     graph_label );
+       
     }
 
 }
@@ -1743,193 +1662,154 @@ vertical_grid(
 
 void 
 axis_paint(
-    image_desc_t   *im,
-    gdImagePtr     gif
-    )
+   image_desc_t   *im,
+   gfx_canvas_t   *canvas
+          )
 {   
     /* draw x and y axis */
-    gdImageLine(gif, im->xorigin+im->xsize,im->yorigin,
-               im->xorigin+im->xsize,im->yorigin-im->ysize,
-               graph_col[GRC_GRID].i);
-    
-    gdImageLine(gif, im->xorigin,im->yorigin-im->ysize,
-               im->xorigin+im->xsize,im->yorigin-im->ysize,
-               graph_col[GRC_GRID].i);
-
-    gdImageLine(gif, im->xorigin-4,im->yorigin,
-               im->xorigin+im->xsize+4,im->yorigin,
-               graph_col[GRC_FONT].i);
-
-    gdImageLine(gif, im->xorigin,im->yorigin,
-               im->xorigin,im->yorigin-im->ysize,
-               graph_col[GRC_GRID].i);
+    gfx_new_line ( canvas, im->xorigin+im->xsize,im->yorigin,
+                     im->xorigin+im->xsize,im->yorigin-im->ysize,
+                     GRIDWIDTH, im->graph_col[GRC_GRID]);
+       
+       gfx_new_line ( canvas, im->xorigin,im->yorigin-im->ysize,
+                        im->xorigin+im->xsize,im->yorigin-im->ysize,
+                        GRIDWIDTH, im->graph_col[GRC_GRID]);
+   
+       gfx_new_line ( canvas, im->xorigin-4,im->yorigin,
+                        im->xorigin+im->xsize+4,im->yorigin,
+                        MGRIDWIDTH, im->graph_col[GRC_GRID]);
+   
+       gfx_new_line ( canvas, im->xorigin,im->yorigin+4,
+                        im->xorigin,im->yorigin-im->ysize-4,
+                        MGRIDWIDTH, im->graph_col[GRC_GRID]);
+   
     
     /* arrow for X axis direction */
-    gdImageLine(gif, im->xorigin+im->xsize+4, im->yorigin-3, im->xorigin+im->xsize+4, im->yorigin+3,graph_col[GRC_ARROW].i);
-    gdImageLine(gif, im->xorigin+im->xsize+4, im->yorigin-3, im->xorigin+im->xsize+9, im->yorigin,graph_col[GRC_ARROW].i);
-    gdImageLine(gif, im->xorigin+im->xsize+4, im->yorigin+3, im->xorigin+im->xsize+9, im->yorigin,graph_col[GRC_ARROW].i);
-
-    /*    gdImageLine(gif, im->xorigin+im->xsize-1, im->yorigin-3, im->xorigin+im->xsize-1, im->yorigin+3,graph_col[GRC_MGRID].i);
-    gdImageLine(gif, im->xorigin+im->xsize, im->yorigin-2, im->xorigin+im->xsize, im->yorigin+2,graph_col[GRC_MGRID].i);
-    gdImageLine(gif, im->xorigin+im->xsize+1, im->yorigin-2, im->xorigin+im->xsize+1, im->yorigin+2,graph_col[GRC_MGRID].i);
-    gdImageLine(gif, im->xorigin+im->xsize+2, im->yorigin-2, im->xorigin+im->xsize+2, im->yorigin+2,graph_col[GRC_MGRID].i);
-    gdImageLine(gif, im->xorigin+im->xsize+3, im->yorigin-1, im->xorigin+im->xsize+3, im->yorigin+1,graph_col[GRC_MGRID].i);
-    gdImageLine(gif, im->xorigin+im->xsize+4, im->yorigin-1, im->xorigin+im->xsize+4, im->yorigin+1,graph_col[GRC_MGRID].i);
-    gdImageLine(gif, im->xorigin+im->xsize+5, im->yorigin, im->xorigin+im->xsize+5, im->yorigin,graph_col[GRC_MGRID].i); */
-
-
-
+    gfx_new_area ( canvas, 
+                  im->xorigin+im->xsize+4,  im->yorigin-3,
+                  im->xorigin+im->xsize+4,  im->yorigin+3,
+                  im->xorigin+im->xsize+9,  im->yorigin,  
+                  im->graph_col[GRC_ARROW]);
+   
+   
+   
 }
 
 void
 grid_paint(
     image_desc_t   *im,
-    gdImagePtr     gif
+    gfx_canvas_t   *canvas
+          
     )
 {   
     long i;
     int boxH=8, boxV=8;
     int res=0;
-    gdPoint polyPoints[4];      /* points for filled graph and more*/
+    double x0,x1,x2,x3,y0,y1,y2,y3; /* points for filled graph and more*/
+    gfx_node_t *node;
+    
 
     /* draw 3d border */
-    gdImageLine(gif,0,0,im->xgif-1,0,graph_col[GRC_SHADEA].i);
-    gdImageLine(gif,1,1,im->xgif-2,1,graph_col[GRC_SHADEA].i);
-    gdImageLine(gif,0,0,0,im->ygif-1,graph_col[GRC_SHADEA].i);
-    gdImageLine(gif,1,1,1,im->ygif-2,graph_col[GRC_SHADEA].i);
-    gdImageLine(gif,im->xgif-1,0,im->xgif-1,im->ygif-1,graph_col[GRC_SHADEB].i);
-    gdImageLine(gif,0,im->ygif-1,im->xgif-1,im->ygif-1,graph_col[GRC_SHADEB].i);
-    gdImageLine(gif,im->xgif-2,1,im->xgif-2,im->ygif-2,graph_col[GRC_SHADEB].i);
-    gdImageLine(gif,1,im->ygif-2,im->xgif-2,im->ygif-2,graph_col[GRC_SHADEB].i);
-
-
+    node = gfx_new_area (canvas, 0,im->ygif, 0,0, im->xgif, 0,im->graph_col[GRC_SHADEA]);
+    gfx_add_point( node , im->xgif - 2, 2 );
+    gfx_add_point( node , 2,2 );
+    gfx_add_point( node , 2,im->ygif-2 );
+    gfx_add_point( node , 0,im->ygif );
+   
+    node =  gfx_new_area (canvas, 0,im->ygif, im->xgif,im->ygif, im->xgif,0,im->graph_col[GRC_SHADEB]);
+    gfx_add_point( node , im->xgif - 2, 2 );
+    gfx_add_point( node , im->xgif-2,im->ygif-2 );
+    gfx_add_point( node , 2,im->ygif-2 );
+    gfx_add_point( node , 0,im->ygif );
+   
+   
     if (im->draw_x_grid == 1 )
-      vertical_grid(gif, im);
+      vertical_grid(canvas, im);
     
     if (im->draw_y_grid == 1){
        if(im->logarithmic){
-               res = horizontal_log_grid(gif,im);
+               res = horizontal_log_grid(canvas,im);
        } else {
-               res = horizontal_grid(gif,im);
+               res = horizontal_grid(canvas,im);
        }
 
        /* dont draw horizontal grid if there is no min and max val */
        if (! res ) {
          char *nodata = "No Data found";
-         gdImageString(gif, LargeFont,
-                       im->xgif/2 
-                       - (strlen(nodata)*LargeFont->w)/2,
-                       (2*im->yorigin-im->ysize) / 2,
-                       (unsigned char *)nodata, graph_col[GRC_FONT].i);
+          gfx_new_text(canvas,im->xgif/2, (2*im->yorigin-im->ysize) / 2,
+                       im->graph_col[GRC_FONT],
+                       im->text_prop[TEXT_PROP_AXIS].font,
+                       im->text_prop[TEXT_PROP_AXIS].size,
+                       im->tabwidth, 0.0, GFX_H_CENTER, GFX_V_CENTER,
+                       nodata );          
        }
     }
 
     /* yaxis description */
-    gdImageStringUp(gif, SmallFont,
-                   7,
-                   (im->yorigin - im->ysize/2
-                    +(strlen(im->ylegend)*SmallFont->w)/2 ),
-                   (unsigned char *)im->ylegend, graph_col[GRC_FONT].i);
-    
-
+    gfx_new_text( canvas,
+                 7, (im->yorigin - im->ysize/2),
+                 im->graph_col[GRC_FONT],
+                 im->text_prop[TEXT_PROP_AXIS].font,
+                 im->text_prop[TEXT_PROP_AXIS].size, im->tabwidth, 270.0,
+                 GFX_H_CENTER, GFX_V_CENTER,
+                 im->ylegend);
+   
     /* graph title */
-    gdImageString(gif, LargeFont,
-                   im->xgif/2 
-                   - (strlen(im->title)*LargeFont->w)/2,
-                 8,
-                   (unsigned char *)im->title, graph_col[GRC_FONT].i);
-    
-    /* graph labels */
-    if( !(im->extra_flags & NOLEGEND) ) {
+    gfx_new_text( canvas,
+                 im->xgif/2, im->text_prop[TEXT_PROP_TITLE].size*1.5,
+                 im->graph_col[GRC_FONT],
+                 im->text_prop[TEXT_PROP_TITLE].font,
+                 im->text_prop[TEXT_PROP_TITLE].size, im->tabwidth, 0.0,
+                 GFX_H_CENTER, GFX_V_CENTER,
+                 im->title);
+
+   /* graph labels */
+   if( !(im->extra_flags & NOLEGEND) ) {
       for(i=0;i<im->gdes_c;i++){
-       if(im->gdes[i].legend[0] =='\0')
-           continue;
-       
-       if(im->gdes[i].gf != GF_GPRINT && im->gdes[i].gf != GF_COMMENT){
+        if(im->gdes[i].legend[0] =='\0')
+          continue;
+        
+        if(im->gdes[i].gf != GF_GPRINT && im->gdes[i].gf != GF_COMMENT){
+           x0 = im->gdes[i].leg_x;
+           y0 = im->gdes[i].leg_y+1.0;
+           x1 = x0+boxH;
+           x2 = x0+boxH;
+           x3 = x0;
+           y1 = y0;
+           y2 = y0+boxV;
+           y3 = y0+boxV;
+           node = gfx_new_area(canvas, x0,y0,x1,y1,x2,y2 ,im->gdes[i].col);
+           gfx_add_point ( node, x3, y3 );
+           gfx_add_point ( node, x0, y0 );
+           node = gfx_new_line(canvas, x0,y0,x1,y1 ,GRIDWIDTH, im->graph_col[GRC_FRAME]);
+           gfx_add_point ( node, x2, y2 );
+           gfx_add_point ( node, x3, y3 );
+           gfx_add_point ( node, x0, y0 );
            
-           polyPoints[0].x = im->gdes[i].legloc.x;
-           polyPoints[0].y = im->gdes[i].legloc.y+1;
-           polyPoints[1].x = polyPoints[0].x+boxH;
-           polyPoints[2].x = polyPoints[0].x+boxH;
-           polyPoints[3].x = polyPoints[0].x;
-           polyPoints[1].y = polyPoints[0].y;
-           polyPoints[2].y = polyPoints[0].y+boxV;
-           polyPoints[3].y = polyPoints[0].y+boxV;
-           gdImageFilledPolygon(gif,polyPoints,4,im->gdes[i].col.i);
-           gdImagePolygon(gif,polyPoints,4,graph_col[GRC_FRAME].i);
-       
-           gdImageString(gif, SmallFont,
-                         polyPoints[0].x+boxH+6, 
-                         polyPoints[0].y-1,
-                         (unsigned char *)im->gdes[i].legend,
-                         graph_col[GRC_FONT].i);
-       } else {
-           polyPoints[0].x = im->gdes[i].legloc.x;
-           polyPoints[0].y = im->gdes[i].legloc.y;
+           gfx_new_text ( canvas, x0+boxH+6,  (y0+y2) / 2.0,
+                          im->graph_col[GRC_FONT],
+                          im->text_prop[TEXT_PROP_AXIS].font,
+                          im->text_prop[TEXT_PROP_AXIS].size,
+                          im->tabwidth,0.0, GFX_H_LEFT, GFX_V_CENTER,
+                          im->gdes[i].legend );
            
-           gdImageString(gif, SmallFont,
-                         polyPoints[0].x, 
-                         polyPoints[0].y,
-                         (unsigned char *)im->gdes[i].legend,
-                         graph_col[GRC_FONT].i);
-       }
+        } else {
+           x0 = im->gdes[i].leg_x;
+           y0 = im->gdes[i].leg_y;
+               
+           gfx_new_text ( canvas, x0,  (y0+y2) / 2.0,
+                          im->graph_col[GRC_FONT],
+                          im->text_prop[TEXT_PROP_AXIS].font,
+                          im->text_prop[TEXT_PROP_AXIS].size,
+                          im->tabwidth,0.0, GFX_H_LEFT, GFX_V_BOTTOM,
+                          im->gdes[i].legend );
+           
+        }
       }
-    }
-    
-    
-    gator(gif, (int) im->xgif-5, 5);
-
+   }
 }
 
 
-gdImagePtr
-MkLineBrush(image_desc_t *im,long cosel, enum gf_en typsel){
-  gdImagePtr brush;
-  int pen;
-  switch (typsel){
-  case GF_LINE1:
-    brush=gdImageCreate(1,1);
-    break;
-  case GF_LINE2:
-    brush=gdImageCreate(2,2);
-    break;
-  case GF_LINE3:
-    brush=gdImageCreate(3,3);
-    break;
-  default:
-    return NULL;
-  }
-
-  gdImageColorTransparent(brush, 
-                         gdImageColorAllocate(brush, 0, 0, 0));
-
-  pen = gdImageColorAllocate(brush, 
-                            im->gdes[cosel].col.red,
-                            im->gdes[cosel].col.green,
-                            im->gdes[cosel].col.blue);
-    
-  switch (typsel){
-  case GF_LINE1:
-    gdImageSetPixel(brush,0,0,pen);
-    break;
-  case GF_LINE2:
-    gdImageSetPixel(brush,0,0,pen);
-    gdImageSetPixel(brush,0,1,pen);
-    gdImageSetPixel(brush,1,0,pen);
-    gdImageSetPixel(brush,1,1,pen);
-    break;
-  case GF_LINE3:
-    gdImageSetPixel(brush,1,0,pen);
-    gdImageSetPixel(brush,0,1,pen);
-    gdImageSetPixel(brush,1,1,pen);
-    gdImageSetPixel(brush,2,1,pen);
-    gdImageSetPixel(brush,1,2,pen);
-    break;
-  default:
-    return NULL;
-  }
-  return brush;
-}
 /*****************************************************
  * lazy check make sure we rely need to create this graph
  *****************************************************/
@@ -1961,295 +1841,288 @@ int lazy_check(image_desc_t *im){
     return size;
 }
 
+
 /* draw that picture thing ... */
 int
 graph_paint(image_desc_t *im, char ***calcpr)
 {
-    int i,ii;
-    int lazy =     lazy_check(im);
-    FILE  *fo;
-    
-    /* gif stuff */
-    gdImagePtr gif,brush;
-
-    double areazero = 0.0;
-    enum gf_en stack_gf = GF_PRINT;
-    graph_desc_t *lastgdes = NULL;    
-    gdPoint canvas[4], back[4];         /* points for canvas*/
-
-    /* if we are lazy and there is nothing to PRINT ... quit now */
-    if (lazy && im->prt_c==0) return 0;
-    
-    /* pull the data from the rrd files ... */
-    
-    if(data_fetch(im)==-1)
-       return -1;
-
-    /* evaluate VDEF and CDEF operations ... */
-    if(data_calc(im)==-1)
-       return -1;
-
-    /* calculate and PRINT and GPRINT definitions. We have to do it at
-     * this point because it will affect the length of the legends
-     * if there are no graph elements we stop here ... 
-     * if we are lazy, try to quit ... 
-     */
-    i=print_calc(im,calcpr);
-    if(i<0) return -1;
-    if(i==0 || lazy) return 0;
-
-    /* get actual drawing data and find min and max values*/
-    if(data_proc(im)==-1)
-       return -1;
-
-    if(!im->logarithmic){si_unit(im);}        /* identify si magnitude Kilo, Mega Giga ? */
-
-    if(!im->rigid && ! im->logarithmic)
-       expand_range(im);   /* make sure the upper and lower limit are
-                          sensible values */
-
-    /* init xtr and ytr */
-    /* determine the actual size of the gif to draw. The size given
-       on the cmdline is the graph area. But we need more as we have
-       draw labels and other things outside the graph area */
-
-
-    im->xorigin = 10 + 9 * SmallFont->w+SmallFont->h;
-    xtr(im,0); 
-
-    im->yorigin = 14 + im->ysize;
-    ytr(im,DNAN);
-
-    if(im->title[0] != '\0')
-       im->yorigin += (LargeFont->h+4);
-
-    im->xgif=20+im->xsize + im->xorigin;
-    im->ygif= im->yorigin+2*SmallFont->h;
-    
-    /* determine where to place the legends onto the graphics.
-       and set im->ygif to match space requirements for text */
-    if(leg_place(im)==-1)
-     return -1;
-
-    gif=gdImageCreate(im->xgif,im->ygif);
-
-    gdImageInterlace(gif, im->interlaced);
-    
-    /* allocate colors for the screen elements */
-    for(i=0;i<DIM(graph_col);i++)
-       /* check for user override values */
-       if(im->graph_col[i].red != -1)
-           graph_col[i].i = 
-               gdImageColorAllocate( gif,
-                                     im->graph_col[i].red, 
-                                     im->graph_col[i].green, 
-                                     im->graph_col[i].blue);
-       else
-           graph_col[i].i = 
-               gdImageColorAllocate( gif,
-                                     graph_col[i].red, 
-                                     graph_col[i].green, 
-                                     graph_col[i].blue);
-       
-    
-    /* allocate colors for the graph */
-    for(i=0;i<im->gdes_c;i++)
-       /* only for elements which have a color defined */
-       if (im->gdes[i].col.red != -1)
-           im->gdes[i].col.i = 
-               gdImageColorAllocate(gif,
-                                    im->gdes[i].col.red,
-                                    im->gdes[i].col.green,
-                                    im->gdes[i].col.blue);
-    
-    
-    /* the actual graph is created by going through the individual
-       graph elements and then drawing them */
-    
-    back[0].x = 0;
-    back[0].y = 0;
-    back[1].x = back[0].x+im->xgif;
-    back[1].y = back[0].y;
-    back[2].x = back[1].x;
-    back[2].y = back[0].y+im->ygif;
-    back[3].x = back[0].x;
-    back[3].y = back[2].y;
-
-    gdImageFilledPolygon(gif,back,4,graph_col[GRC_BACK].i);
-
-    canvas[0].x = im->xorigin;
-    canvas[0].y = im->yorigin;
-    canvas[1].x = canvas[0].x+im->xsize;
-    canvas[1].y = canvas[0].y;
-    canvas[2].x = canvas[1].x;
-    canvas[2].y = canvas[0].y-im->ysize;
-    canvas[3].x = canvas[0].x;
-    canvas[3].y = canvas[2].y;
-
-    gdImageFilledPolygon(gif,canvas,4,graph_col[GRC_CANVAS].i);
-
-    if (im->minval > 0.0)
-       areazero = im->minval;
-    if (im->maxval < 0.0)
-       areazero = im->maxval;
-
-    axis_paint(im,gif);
-
-    for(i=0;i<im->gdes_c;i++){ 
-        
-       switch(im->gdes[i].gf){
-       case GF_CDEF:
-       case GF_VDEF:
-       case GF_DEF:
-       case GF_PRINT:
-       case GF_GPRINT:
-       case GF_COMMENT:
-       case GF_HRULE:
-       case GF_VRULE:
-               break;
-       case GF_TICK:
-               for (ii = 0; ii < im->xsize; ii++)
-               {
-                  if (!isnan(im->gdes[i].p_data[ii]) && 
-                          im->gdes[i].p_data[ii] > 0.0)
-                  { 
-                         /* generate a tick */
-                         gdImageLine(gif, im -> xorigin + ii, 
-                                im -> yorigin - (im -> gdes[i].yrule * im -> ysize),
-                                im -> xorigin + ii, 
-                                im -> yorigin,
-                                im -> gdes[i].col.i);
-                  }
-               }
-               break;
-       case GF_LINE1:
-       case GF_LINE2:
-       case GF_LINE3:
-       case GF_AREA:
-           stack_gf = im->gdes[i].gf;
-       case GF_STACK:      
-           /* fix data points at oo and -oo */
-           for(ii=0;ii<im->xsize;ii++){
-               if (isinf(im->gdes[i].p_data[ii])){
-                   if (im->gdes[i].p_data[ii] > 0) {
-                       im->gdes[i].p_data[ii] = im->maxval ;
-                   } else {
-                       im->gdes[i].p_data[ii] = im->minval ;
-                   }               
-               
-               }
-           }
+  int i,ii;
+  int lazy =     lazy_check(im);
+  FILE  *fo;
+  gfx_canvas_t *canvas;
+  gfx_node_t *node;
+  
+  double areazero = 0.0;
+  enum gf_en stack_gf = GF_PRINT;
+  graph_desc_t *lastgdes = NULL;    
+  
+  /* if we are lazy and there is nothing to PRINT ... quit now */
+  if (lazy && im->prt_c==0) return 0;
+  
+  /* pull the data from the rrd files ... */
+  
+  if(data_fetch(im)==-1)
+    return -1;
+  
+  /* evaluate VDEF and CDEF operations ... */
+  if(data_calc(im)==-1)
+    return -1;
+  
+  /* calculate and PRINT and GPRINT definitions. We have to do it at
+   * this point because it will affect the length of the legends
+   * if there are no graph elements we stop here ... 
+   * if we are lazy, try to quit ... 
+   */
+  i=print_calc(im,calcpr);
+  if(i<0) return -1;
+  if(i==0 || lazy) return 0;
+  
+  /* get actual drawing data and find min and max values*/
+  if(data_proc(im)==-1)
+    return -1;
+  
+  if(!im->logarithmic){si_unit(im);}        /* identify si magnitude Kilo, Mega Giga ? */
+  
+  if(!im->rigid && ! im->logarithmic)
+    expand_range(im);   /* make sure the upper and lower limit are
+                           sensible values */
+  
+  /* init xtr and ytr */
+  /* determine the actual size of the gif to draw. The size given
+     on the cmdline is the graph area. But we need more as we have
+     draw labels and other things outside the graph area */
+  
+  
+  im->xorigin = 10 + 9 *  im->text_prop[TEXT_PROP_LEGEND].size;
+
+  xtr(im,0); 
+  
+  im->yorigin = 10 + im->ysize;
+
+  ytr(im,DNAN);
+  
+  if(im->title[0] != '\0')
+    im->yorigin += im->text_prop[TEXT_PROP_TITLE].size*3+4;
+  
+  im->xgif=20+im->xsize + im->xorigin;
+  im->ygif= im->yorigin+2* im->text_prop[TEXT_PROP_LEGEND].size;
+  
+  /* determine where to place the legends onto the graphics.
+     and set im->ygif to match space requirements for text */
+  if(leg_place(im)==-1)
+    return -1;
 
-           if (im->gdes[i].col.i != -1){               
-              /* GF_LINE and frined */
-              if(stack_gf == GF_LINE1 || stack_gf == GF_LINE2 || stack_gf == GF_LINE3 ){
-                  brush = MkLineBrush(im,i,stack_gf);
-                  gdImageSetBrush(gif, brush);
-                  for(ii=1;ii<im->xsize;ii++){
-                      if (isnan(im->gdes[i].p_data[ii-1]) ||
-                          isnan(im->gdes[i].p_data[ii]))
-                            continue;
-                      gdImageLine(gif,
-                                    ii+im->xorigin-1,ytr(im,im->gdes[i].p_data[ii-1]),
+  canvas=gfx_new_canvas();
+
+  /* the actual graph is created by going through the individual
+     graph elements and then drawing them */
+  
+  node=gfx_new_area ( canvas,
+                      0, 0,
+                      im->xgif, 0,
+                      im->xgif, im->ygif,
+                      im->graph_col[GRC_BACK]);
+
+  gfx_add_point(node,0, im->ygif);
+
+  node=gfx_new_area ( canvas,
+                      im->xorigin,             im->yorigin, 
+                      im->xorigin + im->xsize, im->yorigin,
+                      im->xorigin + im->xsize, im->yorigin-im->ysize,
+                      im->graph_col[GRC_CANVAS]);
+  
+  gfx_add_point(node,im->xorigin, im->yorigin - im->ysize);
+
+  
+  if (im->minval > 0.0)
+    areazero = im->minval;
+  if (im->maxval < 0.0)
+    areazero = im->maxval;
+  
+  axis_paint(im,canvas);
+
+
+  for(i=0;i<im->gdes_c;i++){    
+    switch(im->gdes[i].gf){
+    case GF_CDEF:
+    case GF_VDEF:
+    case GF_DEF:
+    case GF_PRINT:
+    case GF_GPRINT:
+    case GF_COMMENT:
+    case GF_HRULE:
+    case GF_VRULE:
+      break;
+    case GF_TICK:
+      for (ii = 0; ii < im->xsize; ii++)
+        {
+          if (!isnan(im->gdes[i].p_data[ii]) && 
+              im->gdes[i].p_data[ii] > 0.0)
+            { 
+              /* generate a tick */
+              gfx_new_line(canvas, im -> xorigin + ii, 
+                           im -> yorigin - (im -> gdes[i].yrule * im -> ysize),
+                           im -> xorigin + ii, 
+                           im -> yorigin,
+                           1.0,
+                           im -> gdes[i].col );
+            }
+        }
+      break;
+    case GF_LINE:
+    case GF_AREA:
+      stack_gf = im->gdes[i].gf;
+    case GF_STACK:          
+      /* fix data points at oo and -oo */
+      for(ii=0;ii<im->xsize;ii++){
+        if (isinf(im->gdes[i].p_data[ii])){
+          if (im->gdes[i].p_data[ii] > 0) {
+            im->gdes[i].p_data[ii] = im->maxval ;
+          } else {
+            im->gdes[i].p_data[ii] = im->minval ;
+          }                 
+          
+        }
+      } /* for */
+      
+      if (im->gdes[i].col != 0x0){               
+        /* GF_LINE and friend */
+        if(stack_gf == GF_LINE ){
+          node = NULL;
+          for(ii=1;ii<im->xsize;ii++){
+            if ( ! isnan(im->gdes[i].p_data[ii-1])
+                 && ! isnan(im->gdes[i].p_data[ii])){
+              if (node == NULL){
+                node = gfx_new_line(canvas,
+                                    ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii-1]),
                                     ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
-                                    gdBrushed);
-                        
-                    }
-                    gdImageDestroy(brush);
+                                    im->gdes[i].linewidth,
+                                    im->gdes[i].col);
+              } else {
+                gfx_add_point(node,ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]));
+              }
+            } else {
+              node = NULL;
+            }
+          }
+        } else {
+          int area_start=-1;
+          node = NULL;
+          for(ii=1;ii<im->xsize;ii++){
+            /* open an area */
+            if ( ! isnan(im->gdes[i].p_data[ii-1])
+                 && ! isnan(im->gdes[i].p_data[ii])){
+              if (node == NULL){
+                float ybase = 0.0;
+                if (im->gdes[i].gf == GF_STACK) {
+                  ybase = ytr(im,lastgdes->p_data[ii-1]);
+                } else {
+                  ybase =  ytr(im,areazero);
                 }
-                else 
-                    /* GF_AREA STACK type*/
-                    if (im->gdes[i].gf == GF_STACK )
-                        for(ii=0;ii<im->xsize;ii++){
-                           if(isnan(im->gdes[i].p_data[ii])){
-                               im->gdes[i].p_data[ii] = lastgdes->p_data[ii];
-                               continue;
-                           }
-                           
-                           if (lastgdes->p_data[ii] == im->gdes[i].p_data[ii]){
-                               continue;
-                           }
-                           gdImageLine(gif,
-                                       ii+im->xorigin,ytr(im,lastgdes->p_data[ii]),
-                                       ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
-                                       im->gdes[i].col.i);
-                       }
-              
-                   else /* simple GF_AREA */
-                       for(ii=0;ii<im->xsize;ii++){
-                            if (isnan(im->gdes[i].p_data[ii])) {
-                               im->gdes[i].p_data[ii] = 0;
-                                continue;
-                           }
-                            gdImageLine(gif,
-                                        ii+im->xorigin,ytr(im,areazero),
-                                        ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
-                                        im->gdes[i].col.i);
-                        }
-          }
-          lastgdes = &(im->gdes[i]);              
-          break;
-       }
-    }
+                area_start = ii-1;
+                node = gfx_new_area(canvas,
+                                    ii-1+im->xorigin,ybase,
+                                    ii-1+im->xorigin,ytr(im,im->gdes[i].p_data[ii-1]),
+                                    ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]),
+                                    im->gdes[i].col
+                                    );
+              } else {
+                gfx_add_point(node,ii+im->xorigin,ytr(im,im->gdes[i].p_data[ii]));
+              }
+            }
+
+            if ( node != NULL && (ii+1==im->xsize || isnan(im->gdes[i].p_data[ii]) )){
+              /* GF_AREA STACK type*/
+              if (im->gdes[i].gf == GF_STACK ) {
+                int iii;
+                for (iii=ii-1;iii>area_start;iii--){
+                  gfx_add_point(node,iii+im->xorigin,ytr(im,lastgdes->p_data[iii]));
+                }
+              } else {
+                gfx_add_point(node,ii+im->xorigin,ytr(im,areazero));
+              };
+              node=NULL;
+            };
+          }             
+        } /* else GF_LINE */
+      } /* if color != 0x0 */
+      /* make sure we do not run into trouble when stacking on NaN */
+      for(ii=0;ii<im->xsize;ii++){
+        if (isnan(im->gdes[i].p_data[ii])) {
+          double ybase = 0.0;
+          if (lastgdes) {
+            ybase = ytr(im,lastgdes->p_data[ii-1]);
+          };
+          if (isnan(ybase) || !lastgdes ){
+            ybase =  ytr(im,areazero);
+          }
+          im->gdes[i].p_data[ii] = ybase;
+        }
+      } 
+      lastgdes = &(im->gdes[i]);                         
+      break;
+    } /* switch */
+  }
+  grid_paint(im,canvas);
+  
+  /* the RULES are the last thing to paint ... */
+  for(i=0;i<im->gdes_c;i++){    
     
-    grid_paint(im,gif);
-
-    /* the RULES are the last thing to paint ... */
-    for(i=0;i<im->gdes_c;i++){ 
-        
-       switch(im->gdes[i].gf){
-       case GF_HRULE:
-           if(isnan(im->gdes[i].yrule)) { /* fetch variable */
-               im->gdes[i].yrule = im->gdes[im->gdes[i].vidx].vf.val;
-           };
-           if(im->gdes[i].yrule >= im->minval
-              && im->gdes[i].yrule <= im->maxval)
-             gdImageLine(gif,
-                         im->xorigin,ytr(im,im->gdes[i].yrule),
-                         im->xorigin+im->xsize,ytr(im,im->gdes[i].yrule),
-                         im->gdes[i].col.i); 
-           break;
-       case GF_VRULE:
-           if(im->gdes[i].xrule == 0) { /* fetch variable */
-               im->gdes[i].xrule = im->gdes[im->gdes[i].vidx].vf.when;
-           };
-           if(im->gdes[i].xrule >= im->start
-                       && im->gdes[i].xrule <= im->end)
-               gdImageLine(gif,
-                       xtr(im,im->gdes[i].xrule),im->yorigin,
-                       xtr(im,im->gdes[i].xrule),im->yorigin-im->ysize,
-                       im->gdes[i].col.i); 
-           break;
-       default:
-           break;
-       }
+    switch(im->gdes[i].gf){
+    case GF_HRULE:
+      printf("DEBUG: HRULE at %f\n",im->gdes[i].yrule);
+      if(isnan(im->gdes[i].yrule)) { /* fetch variable */
+        im->gdes[i].yrule = im->gdes[im->gdes[i].vidx].vf.val;
+      };
+      if(im->gdes[i].yrule >= im->minval
+         && im->gdes[i].yrule <= im->maxval)
+        gfx_new_line(canvas,
+                     im->xorigin,ytr(im,im->gdes[i].yrule),
+                     im->xorigin+im->xsize,ytr(im,im->gdes[i].yrule),
+                     1.0,im->gdes[i].col); 
+      break;
+    case GF_VRULE:
+      if(im->gdes[i].xrule == 0) { /* fetch variable */
+        im->gdes[i].xrule = im->gdes[im->gdes[i].vidx].vf.when;
+      };
+      if(im->gdes[i].xrule >= im->start
+         && im->gdes[i].xrule <= im->end)
+        gfx_new_line(canvas,
+                     xtr(im,im->gdes[i].xrule),im->yorigin,
+                     xtr(im,im->gdes[i].xrule),im->yorigin-im->ysize,
+                     1.0,im->gdes[i].col); 
+      break;
+    default:
+      break;
     }
+  }
 
-    if (strcmp(im->graphfile,"-")==0) {
+  
+  if (strcmp(im->graphfile,"-")==0) {
 #ifdef WIN32
-        /* Change translation mode for stdout to BINARY */
-        _setmode( _fileno( stdout ), O_BINARY );
+    /* Change translation mode for stdout to BINARY */
+    _setmode( _fileno( stdout ), O_BINARY );
 #endif
-        fo = stdout;
-    } else {
-       if ((fo = fopen(im->graphfile,"wb")) == NULL) {
-           rrd_set_error("Opening '%s' for write: %s",im->graphfile, strerror(errno));
-           return (-1);
-       }
-    }
-    switch (im->imgformat) {
-    case IF_GIF:
-       gdImageGif(gif, fo);    
-       break;
-    case IF_PNG:
-       gdImagePng(gif, fo);    
-       break;
+    fo = stdout;
+  } else {
+    if ((fo = fopen(im->graphfile,"wb")) == NULL) {
+      rrd_set_error("Opening '%s' for write: %s",im->graphfile,
+                    strerror(errno));
+      return (-1);
     }
-    if (strcmp(im->graphfile,"-") != 0)
-       fclose(fo);
-    gdImageDestroy(gif);
-
-    return 0;
+  }
+  switch (im->imgformat) {
+  case IF_GIF:
+    break;
+  case IF_PNG:
+    gfx_render_png (canvas,im->xgif,im->ygif,im->zoom,0x0,fo);
+    break;
+  }
+  if (strcmp(im->graphfile,"-") != 0)
+    fclose(fo);
+   
+  gfx_destroy(canvas);
+  return 0;
 }
 
 
@@ -2283,8 +2156,7 @@ gdes_alloc(image_desc_t *im){
     im->gdes[im->gdes_c-1].data_first=0;
     im->gdes[im->gdes_c-1].p_data=NULL;
     im->gdes[im->gdes_c-1].rpnp=NULL;
-    im->gdes[im->gdes_c-1].col.red = -1;
-    im->gdes[im->gdes_c-1].col.i=-1;
+    im->gdes[im->gdes_c-1].col = 0x0;
     im->gdes[im->gdes_c-1].legend[0]='\0';
     im->gdes[im->gdes_c-1].rrd[0]='\0';
     im->gdes[im->gdes_c-1].ds=-1;    
@@ -2377,7 +2249,7 @@ rrd_graph(int argc, char **argv, char ***prdata, int *xsize, int *ysize)
            filename--;
        }
 
-       sprintf((*prdata)[0],im.imginfo,filename,im.xgif,im.ygif);
+       sprintf((*prdata)[0],im.imginfo,filename,(long)(im.zoom*im.xgif),(long)(im.zoom*im.ygif));
     }
     im_free(&im);
     return 0;
@@ -2412,10 +2284,16 @@ rrd_graph_init(image_desc_t *im)
     im->prt_c = 0;
     im->gdes_c = 0;
     im->gdes = NULL;
+    im->zoom = 1.0;
     im->imgformat = IF_GIF; /* we default to GIF output */
 
     for(i=0;i<DIM(graph_col);i++)
-       im->graph_col[i].red=-1;
+        im->graph_col[i]=graph_col[i];
+
+    for(i=0;i<DIM(text_prop);i++){        
+      im->text_prop[i].size = text_prop[i].size;
+      im->text_prop[i].font = text_prop[i].font;
+    }
 }
 
 void
@@ -2427,7 +2305,7 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
     time_t             start_tmp=0,end_tmp=0;
     long               long_tmp;
     struct time_value  start_tv, end_tv;
-    unsigned int       col_red,col_green,col_blue;
+    gfx_color_t         color;
 
     parsetime("end-24h", &start_tv);
     parsetime("now", &end_tv);
@@ -2449,10 +2327,12 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
            {"base",       required_argument, 0,  'b'},
            {"logarithmic",no_argument,       0,  'o'},
            {"color",      required_argument, 0,  'c'},
+            {"font",       required_argument, 0,  'n'},
            {"title",      required_argument, 0,  't'},
            {"imginfo",    required_argument, 0,  'f'},
            {"imgformat",  required_argument, 0,  'a'},
            {"lazy",       no_argument,       0,  'z'},
+            {"zoom",       required_argument, 0,  'm'},
            {"no-legend",  no_argument,       0,  'g'},
            {"alt-y-grid", no_argument,       0,   257 },
            {"alt-autoscale", no_argument,    0,   258 },
@@ -2465,7 +2345,7 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
 
 
        opt = getopt_long(argc, argv, 
-                         "s:e:x:y:v:w:h:iu:l:rb:oc:t:f:a:z:g",
+                         "s:e:x:y:v:w:h:iu:l:rb:oc:n:m:t:f:a:z:g",
                          long_options, &option_index);
 
        if (opt == EOF)
@@ -2615,23 +2495,50 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im)
            if (isnan(im->minval))
                im->minval=1;
            break;
-       case 'c':
-           if(sscanf(optarg,
-                     "%10[A-Z]#%2x%2x%2x",
-                     col_nam,&col_red,&col_green,&col_blue) == 4){
-               int ci;
-               if((ci=grc_conv(col_nam)) != -1){
-                   im->graph_col[ci].red=col_red;
-                   im->graph_col[ci].green=col_green;
-                   im->graph_col[ci].blue=col_blue;
-               }  else {
-                 rrd_set_error("invalid color name '%s'",col_nam);
-               }
-           } else {
-               rrd_set_error("invalid color def format");
+        case 'c':
+            if(sscanf(optarg,
+                      "%10[A-Z]#%8x",
+                      col_nam,&color) == 2){
+                int ci;
+                if((ci=grc_conv(col_nam)) != -1){
+                    im->graph_col[ci]=color;
+                }  else {
+                  rrd_set_error("invalid color name '%s'",col_nam);
+                }
+            } else {
+                rrd_set_error("invalid color def format");
+                return -1;
+            }
+            break;        
+        case 'n':{
+          char *prop = "";
+          double size = 1;
+          char *font = "dummy";
+
+          if(sscanf(optarg,
+                    "%10[A-Z]:%lf:%s",
+                    prop,&size,font) == 3){
+            int sindex;
+            if((sindex=text_prop_conv(prop)) != -1){
+              im->text_prop[sindex].size=size;              
+              im->text_prop[sindex].font=font;
+              
+            }  else {
+              rrd_set_error("invalid color name '%s'",col_nam);
+            }
+          } else {
+            rrd_set_error("invalid text property format");
+            return;
+          }
+          break;          
+        }
+        case 'm':
+           im->zoom= atof(optarg);
+           if (im->zoom <= 0.0) {
+               rrd_set_error("zoom factor must be > 0");
                return;
            }
-           break;        
+          break;
        case 't':
            strncpy(im->title,optarg,150);
            im->title[150]='\0';
@@ -2690,6 +2597,7 @@ rrd_graph_script(int argc, char *argv[], image_desc_t *im)
        char            *line;
        char            funcname[10],vname[MAX_VNAME_LEN+1],sep[1];
        double          d;
+       double          linewidth;
        int             j,k,l,m;
 
        /* Each command is one element from *argv[], we call this "line".
@@ -2709,17 +2617,23 @@ rrd_graph_script(int argc, char *argv[], image_desc_t *im)
        ** function:string                              for COMMENT
        */
        argstart=0;
+
        sscanf(line, "%10[A-Z0-9]:%n", funcname,&argstart);
        if (argstart==0) {
            rrd_set_error("Cannot parse function in line: %s",line);
            im_free(im);
            return;
        }
-       if ((gdp->gf=gf_conv(funcname))==-1) {
-           rrd_set_error("'%s' is not a valid function name",funcname);
-           im_free(im);
-           return;
-       }
+        if(sscanf(funcname,"LINE%lf",&linewidth)){
+                im->gdes[im->gdes_c-1].gf = GF_LINE;
+                im->gdes[im->gdes_c-1].linewidth = linewidth;
+        } else {
+         if ((gdp->gf=gf_conv(funcname))==-1) {
+             rrd_set_error("'%s' is not a valid function name",funcname);
+             im_free(im);
+             return;
+         }
+        }
 
        /* If the error string is set, we exit at the end of the switch */
        switch (gdp->gf) {
@@ -2757,9 +2671,7 @@ rrd_graph_script(int argc, char *argv[], image_desc_t *im)
                    rrd_set_error("STACK must follow another graphing element");
                    break;
                }
-           case GF_LINE1:
-           case GF_LINE2:
-           case GF_LINE3:
+           case GF_LINE:
            case GF_AREA:
            case GF_TICK:
                j=k=0;
@@ -2922,7 +2834,7 @@ rrd_graph_color(image_desc_t *im, char *var, char *err, int optional)
     } else {
        int n=0;
        char *rest;
-       unsigned int R,G,B,A;
+       gfx_color_t    col;
 
        rest=strstr(color,":");
        if (rest!=NULL)
@@ -2932,22 +2844,18 @@ rrd_graph_color(image_desc_t *im, char *var, char *err, int optional)
 
        switch (n) {
            case 7:
-               sscanf(color,"#%2x%2x%2x%n",&R,&G,&B,&n);
-               A=255;
+               sscanf(color,"#%6x%n",&col,&n);
+                col = (col << 8) + 0xff /* shift left by 8 */;
                if (n!=7) rrd_set_error("Color problem in %s",err);
                break;
            case 9:
-               sscanf(color,"#%2x%2x%2x%2x%n",&R,&G,&B,&A,&n);
+               sscanf(color,"#%8x%n",&col,&n);
                if (n==9) break;
            default:
                rrd_set_error("Color problem in %s",err);
        }
        if (rrd_test_error()) return 0;
-       gdp->col.red   = R;
-       gdp->col.green = G;
-       gdp->col.blue  = B;
-/*     gdp->col.alpha = A;     */
-if (n==9) printf("WARNING: alpha channel not yet supported\n");
+       gdp->col = col;
        return n;
     }
 }
index 2833dbd..2854ed6 100644 (file)
@@ -1,5 +1,6 @@
 #include "rrd_tool.h"
 #include "rrd_rpncalc.h"
+#include "rrd_gfx.h"
 
 #define MAX_VNAME_LEN 29
 #define DEF_NAM_FMT "%29[_A-Za-z0-9]"
@@ -16,9 +17,11 @@ enum tmt_en {TMT_SECOND=0,TMT_MINUTE,TMT_HOUR,TMT_DAY,
 enum grc_en {GRC_CANVAS=0,GRC_BACK,GRC_SHADEA,GRC_SHADEB,
             GRC_GRID,GRC_MGRID,GRC_FONT,GRC_FRAME,GRC_ARROW,__GRC_END__};
 
+#define MGRIDWIDTH 0.6
+#define GRIDWIDTH  0.4
 
-enum gf_en {GF_PRINT=0,GF_GPRINT,GF_COMMENT,GF_HRULE,GF_VRULE,GF_LINE1,
-           GF_LINE2,GF_LINE3,GF_AREA,GF_STACK,GF_TICK,
+enum gf_en {GF_PRINT=0,GF_GPRINT,GF_COMMENT,GF_HRULE,GF_VRULE,GF_LINE,
+           GF_AREA,GF_STACK,GF_TICK,
            GF_DEF, GF_CDEF, GF_VDEF};
 
 enum if_en {IF_GIF=0,IF_PNG=1};
@@ -32,6 +35,19 @@ enum vdef_op_en {
                ,VDEF_FIRST     /* first non-unknown value and time */
                ,VDEF_LAST      /* last  non-unknown value and time */
                };
+enum text_prop_en { TEXT_PROP_DEFAULT=0,   /* default settings */
+                   TEXT_PROP_TITLE,       /* properties for the title */
+                   TEXT_PROP_AXIS,        /* for the numbers next to the axis */
+                   TEXT_PROP_UNIT,        /* for the vertical unit description */
+                   TEXT_PROP_LEGEND,      /* fot the legend below the graph */
+                   TEXT_PROP_LAST };
+
+typedef struct text_prop_t {
+  double       size;
+  char *       font;
+} text_prop_t;
+
+
 typedef struct vdef_t {
     enum vdef_op_en    op;
     double             param;  /* parameter for function, if applicable */
@@ -39,14 +55,6 @@ typedef struct vdef_t {
     time_t             when;   /* timestamp, if applicable */
 } vdef_t;
 
-typedef struct col_trip_t {
-    int red; /* red = -1 is no color */
-    int green;
-    int blue;
-    int i; /* color index assigned in gif image i=-1 is unasigned*/
-} col_trip_t;
-
-
 typedef struct xlab_t {
     long         minsec;       /* minimum sec per pix */
     enum tmt_en  gridtm;       /* grid interval in what ?*/
@@ -59,41 +67,6 @@ typedef struct xlab_t {
     char         *stst;        /* strftime string*/
 } xlab_t;
 
-#if 0
-xlab_t xlab[] = {
-    {0,        TMT_SECOND,30, TMT_MINUTE,5,  TMT_MINUTE,5,         0,"%H:%M"},
-    {2,        TMT_MINUTE,1,  TMT_MINUTE,5,  TMT_MINUTE,5,         0,"%H:%M"},
-    {5,        TMT_MINUTE,2,  TMT_MINUTE,10, TMT_MINUTE,10,        0,"%H:%M"},
-    {10,       TMT_MINUTE,5,  TMT_MINUTE,20, TMT_MINUTE,20,        0,"%H:%M"},
-    {30,       TMT_MINUTE,10, TMT_HOUR,1,    TMT_HOUR,1,           0,"%H:%M"},
-    {60,       TMT_MINUTE,30, TMT_HOUR,2,    TMT_HOUR,2,           0,"%H:%M"},
-    {180,      TMT_HOUR,1,    TMT_HOUR,6,    TMT_HOUR,6,           0,"%H:%M"},
-    /*{300,      TMT_HOUR,3,    TMT_HOUR,12,   TMT_HOUR,12,    12*3600,"%a %p"},  this looks silly*/
-    {600,      TMT_HOUR,6,    TMT_DAY,1,     TMT_DAY,1,      24*3600,"%a"},
-    {1800,     TMT_HOUR,12,   TMT_DAY,1,     TMT_DAY,2,      24*3600,"%a"},
-    {3600,     TMT_DAY,1,     TMT_WEEK,1,     TMT_WEEK,1,    7*24*3600,"Week %W"},
-    {3*3600,   TMT_WEEK,1,      TMT_MONTH,1,     TMT_WEEK,2,    7*24*3600,"Week %W"},
-    {6*3600,   TMT_MONTH,1,   TMT_MONTH,1,   TMT_MONTH,1, 30*24*3600,"%b"},
-    {48*3600,  TMT_MONTH,1,   TMT_MONTH,3,   TMT_MONTH,3, 30*24*3600,"%b"},
-    {10*24*3600, TMT_YEAR,1,  TMT_YEAR,1,    TMT_YEAR,1, 365*24*3600,"%y"},
-    {-1,TMT_MONTH,0,TMT_MONTH,0,TMT_MONTH,0,0,""}
-};
-
-/* sensible logarithmic y label intervals ...
-   the first element of each row defines the possible starting points on the
-   y axis ... the other specify the */
-
-double yloglab[][12]= {{ 1e9, 1,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0 },
-                      {  1e3, 1,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0 },
-                      {  1e1, 1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
-                      /* {  1e1, 1,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0 }, */
-                      {  1e1, 1,  2.5,  5,  7.5,  0,  0,  0,  0,  0,  0,  0 },
-                      {  1e1, 1,  2,  4,  6,  8,  0,  0,  0,  0,  0,  0 },
-                      {  1e1, 1,  2,  3,  4,  5,  6,  7,  8,  9,  0,  0 },
-                      {  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }};
-
-#endif
-
 /* sensible y label intervals ...*/
 
 typedef struct ylab_t {
@@ -101,37 +74,6 @@ typedef struct ylab_t {
     int      lfac[4]; /* associated label spacing*/
 } ylab_t;
 
-#if 0
-ylab_t ylab[]= {
-    {0.1, {1,2, 5,10}},
-    {0.2, {1,5,10,20}},
-    {0.5, {1,2, 4,10}},
-    {1.0,   {1,2, 5,10}},
-    {2.0,   {1,5,10,20}},
-    {5.0,   {1,2, 4,10}},
-    {10.0,  {1,2, 5,10}},
-    {20.0,  {1,5,10,20}},
-    {50.0,  {1,2, 4,10}},
-    {100.0, {1,2, 5,10}},
-    {200.0, {1,5,10,20}},
-    {500.0, {1,2, 4,10}},
-    {0.0,   {0,0,0,0}}};
-
-
-
-col_trip_t graph_col[] = { /* default colors */
-    {255,255,255,-1},   /* canvas */
-    {245,245,245,-1},   /* background */
-    {200,200,200,-1},   /* shade A    */
-    {150,150,150,-1},   /* shade B    */
-    {140,140,140,-1},      /* grid */
-    {130,30,30,-1},      /* major grid */
-    {0,0,0,-1},         /* font */     
-    {0,0,0,-1},         /* frame */
-    {255,0,0,-1}       /*arrow*/
-};
-
-#endif
 
 /* this structure describes the elements which can make up a graph.
    because they are quite diverse, not all elements will use all the
@@ -150,10 +92,10 @@ typedef  struct graph_desc_t {
     char           ds_nam[DS_NAM_SIZE]; /* data source name */
     long           ds;         /* data source number */
     enum cf_en     cf;         /* consolidation function */
-    col_trip_t     col;        /* graph color */
-    char           format[FMT_LEG_LEN+5]; /* format for PRINT AND GPRINT */
-    char           legend[FMT_LEG_LEN+5]; /* legend*/
-    gdPoint        legloc;     /* location of legend */   
+    gfx_color_t    col;        /* graph color */
+    char  format[FMT_LEG_LEN+5]; /* format for PRINT AND GPRINT */
+    char  legend[FMT_LEG_LEN+5]; /* legend*/
+    double         leg_x,leg_y;  /* location of legend */   
     double         yrule;      /* value for y rule line and for VDEF */
     time_t         xrule;      /* time for x rule line and for VDEF */
     vdef_t         vf;         /* instruction for VDEF function */
@@ -167,7 +109,7 @@ typedef  struct graph_desc_t {
     char           **ds_namv; /* name of datasources  in the fetch. */
     rrd_value_t    *data; /* the raw data drawn from the rrd */
     rrd_value_t    *p_data; /* processed data, xsize elments */
-
+    double         linewidth;  /* linewideth */
 } graph_desc_t;
 
 typedef struct image_desc_t {
@@ -176,7 +118,9 @@ typedef struct image_desc_t {
 
     char           graphfile[MAXPATH]; /* filename for graphic */
     long           xsize,ysize;    /* graph area size in pixels */
-    col_trip_t     graph_col[__GRC_END__]; /* real colors for the graph */   
+    double         zoom;           /* zoom for graph */
+    gfx_color_t    graph_col[__GRC_END__]; /* real colors for the graph */   
+    text_prop_t    text_prop[TEXT_PROP_LAST]; /* text properties */
     char           ylegend[200];   /* legend along the yaxis */
     char           title[200];     /* title for graph */
     int            draw_x_grid;      /* no x-grid at all */
@@ -186,18 +130,18 @@ typedef struct image_desc_t {
 
     double         ygridstep;      /* user defined step for y grid */
     int            ylabfact;       /* every how many y grid shall a label be written ? */
-
+    double         tabwidth;       /* tabwdith */
     time_t         start,end;      /* what time does the graph cover */
-    unsigned long           step;           /* any preference for the default step ? */
+    unsigned long  step;           /* any preference for the default step ? */
     rrd_value_t    minval,maxval;  /* extreme values in the data */
     int            rigid;          /* do not expand range even with 
                                      values outside */
-    char*          imginfo;         /* construct an <IMG ... tag and return 
+    char*          imginfo;        /* construct an <IMG ... tag and return 
                                      as first retval */
     int            lazy;           /* only update the gif if there is reasonable
                                      probablility that the existing one is out of date */
     int            logarithmic;    /* scale the yaxis logarithmic */
-    enum if_en     imgformat;         /* image format */
+    enum if_en     imgformat;      /* image format */
     
     /* status information */
            
@@ -224,6 +168,7 @@ enum gf_en gf_conv(char *);
 enum if_en if_conv(char *);
 enum tmt_en tmt_conv(char *);
 enum grc_en grc_conv(char *);
+enum grc_en text_prop_conv(char *);
 int im_free(image_desc_t *);
 void auto_scale( image_desc_t *,  double *, char **, double *);
 void si_unit( image_desc_t *);
@@ -237,15 +182,13 @@ int data_calc( image_desc_t *);
 int data_proc( image_desc_t *);
 time_t find_first_time( time_t,  enum tmt_en,  long);
 time_t find_next_time( time_t,  enum tmt_en,  long);
-void gator( gdImagePtr, int, int);
 int print_calc(image_desc_t *, char ***);
 int leg_place(image_desc_t *);
-int horizontal_grid(gdImagePtr, image_desc_t *);
-int horizontal_log_grid(gdImagePtr, image_desc_t *);
-void vertical_grid( gdImagePtr, image_desc_t *);
-void axis_paint( image_desc_t *, gdImagePtr);
-void grid_paint( image_desc_t *, gdImagePtr);
-gdImagePtr MkLineBrush(image_desc_t *,long, enum gf_en);
+int horizontal_grid(gfx_canvas_t *,image_desc_t *);
+int horizontal_log_grid(gfx_canvas_t *, image_desc_t *);
+void vertical_grid(gfx_canvas_t *, image_desc_t *);
+void axis_paint( image_desc_t *, gfx_canvas_t *);
+void grid_paint( image_desc_t *, gfx_canvas_t *);
 int lazy_check(image_desc_t *);
 int graph_paint(image_desc_t *, char ***);
 int gdes_alloc(image_desc_t *);
index d1be8be..1ee3a6d 100644 (file)
@@ -74,22 +74,24 @@ void PrintUsage(char *cmd)
           "\t\t[-u|--upper-limit value] [-z|--lazy]\n"
           "\t\t[-l|--lower-limit value] [-r|--rigid]\n"
            "\t\t[-g|--no-legend]\n"
+          "\t\t[--font FONTTAG:size:font]\n"
+           "\t\t[--zoom factor]\n"       
           "\t\t[--alt-autoscale]\n"
           "\t\t[--alt-autoscale-max]\n"
           "\t\t[--units-exponent value]\n"        
           "\t\t[--step seconds]\n"        
           "\t\t[-f|--imginfo printfstr]\n"
           "\t\t[-a|--imgformat GIF|PNG]\n"
-          "\t\t[-c|--color COLORTAG#rrggbb] [-t|--title string]\n"
+          "\t\t[-c|--color COLORTAG#rrggbb[aa]] [-t|--title string]\n"
           "\t\t[DEF:vname=rrd:ds-name:CF]\n"
           "\t\t[CDEF:vname=rpn-expression]\n"
           "\t\t[PRINT:vname:CF:format]\n"
           "\t\t[GPRINT:vname:CF:format]\n"
-          "\t\t[HRULE:value#rrggbb[:legend]]\n"
-          "\t\t[VRULE:value#rrggbb[:legend]]\n"
-          "\t\t[LINE{1|2|3}:vname[#rrggbb[:legend]]]\n"
-          "\t\t[AREA:vname[#rrggbb[:legend]]]\n"
-          "\t\t[STACK:vname[#rrggbb[:legend]]]\n\n";
+          "\t\t[HRULE:value#rrggbb[aa][:legend]]\n"
+          "\t\t[VRULE:value#rrggbb[aa][:legend]]\n"
+          "\t\t[LINE{1|2|3}:vname[#rrggbb[aa][:legend]]]\n"
+          "\t\t[AREA:vname[#rrggbb[aa][:legend]]]\n"
+          "\t\t[STACK:vname[#rrggbb[aa][:legend]]]\n\n";
 
     char help_tune[] =
           " * tune -  Modify some basic properties of an RRD\n\n"
index 40e5480..426cef8 100644 (file)
@@ -118,13 +118,11 @@ typedef struct info_t {
 info_t *rrd_info(int, char **);
 
 /* HELPER FUNCTIONS */
+
 int GifSize(FILE *, long *, long *);
 int PngSize(FILE *, long *, long *);
 int PngSize(FILE *, long *, long *);
 
-#include <gd.h>
-void gdImagePng(gdImagePtr im, FILE *out);
-
 int rrd_create_fn(char *file_name, rrd_t *rrd);
 int rrd_fetch_fn(char *filename, enum cf_en cf_idx,
                 time_t *start,time_t *end,