From be9bb3fb3ccb08a68ee152b85b61d04469d76473 Mon Sep 17 00:00:00 2001 From: Jason Filby Date: Wed, 2 May 2001 12:21:38 +0000 Subject: [PATCH] Freetype 2 svn path=/trunk/; revision=1854 --- reactos/subsys/win32k/freetype/CHANGES | 904 ++ reactos/subsys/win32k/freetype/ahangles.c | 137 + reactos/subsys/win32k/freetype/ahangles.h | 63 + reactos/subsys/win32k/freetype/ahglobal.c | 402 + reactos/subsys/win32k/freetype/ahglobal.h | 52 + reactos/subsys/win32k/freetype/ahglyph.c | 1299 +++ reactos/subsys/win32k/freetype/ahglyph.h | 93 + reactos/subsys/win32k/freetype/ahhint.c | 1398 +++ reactos/subsys/win32k/freetype/ahhint.h | 72 + reactos/subsys/win32k/freetype/ahloader.h | 124 + reactos/subsys/win32k/freetype/ahmodule.c | 127 + reactos/subsys/win32k/freetype/ahmodule.h | 32 + reactos/subsys/win32k/freetype/ahoptim.c | 889 ++ reactos/subsys/win32k/freetype/ahoptim.h | 136 + reactos/subsys/win32k/freetype/ahtypes.h | 492 ++ reactos/subsys/win32k/freetype/autohint.c | 45 + .../win32k/freetype/builds/ansi/ansi.mk | 134 + .../subsys/win32k/freetype/builds/detect.mk | 130 + .../win32k/freetype/builds/dos/detect.mk | 87 + .../win32k/freetype/builds/dos/dos-gcc.mk | 134 + .../subsys/win32k/freetype/builds/freetype.mk | 279 + .../win32k/freetype/builds/mac/ftlib.prj | Bin 0 -> 603 bytes .../subsys/win32k/freetype/builds/mac/readme | 11 + .../subsys/win32k/freetype/builds/modules.mk | 75 + .../win32k/freetype/builds/os2/detect.mk | 62 + .../win32k/freetype/builds/os2/os2-dev.mk | 137 + .../win32k/freetype/builds/os2/os2-gcc.mk | 135 + .../win32k/freetype/builds/unix/aclocal.m4 | 430 + .../win32k/freetype/builds/unix/config.guess | 1273 +++ .../win32k/freetype/builds/unix/config.sub | 1319 +++ .../win32k/freetype/builds/unix/configure | 2514 ++++++ .../win32k/freetype/builds/unix/configure.in | 74 + .../win32k/freetype/builds/unix/detect.mk | 59 + .../win32k/freetype/builds/unix/ftconfig.in | 172 + .../win32k/freetype/builds/unix/ftsystem.c | 306 + .../win32k/freetype/builds/unix/install-sh | 250 + .../win32k/freetype/builds/unix/ltconfig | 3078 +++++++ .../win32k/freetype/builds/unix/ltmain.sh | 4012 +++++++++ .../win32k/freetype/builds/unix/mkinstalldirs | 40 + .../win32k/freetype/builds/unix/unix.in | 216 + .../win32k/freetype/builds/win32/detect.mk | 90 + .../win32k/freetype/builds/win32/w32-dev.mk | 140 + .../win32k/freetype/builds/win32/w32-gcc.mk | 138 + .../win32k/freetype/builds/win32/w32-icc.mk | 122 + .../win32k/freetype/builds/win32/w32-lcc.mk | 130 + .../win32k/freetype/builds/win32/w32-vcc.mk | 129 + reactos/subsys/win32k/freetype/cff.c | 42 + reactos/subsys/win32k/freetype/cidafm.c | 293 + reactos/subsys/win32k/freetype/cidafm.h | 78 + reactos/subsys/win32k/freetype/cidgload.c | 1558 ++++ reactos/subsys/win32k/freetype/cidgload.h | 198 + reactos/subsys/win32k/freetype/cidload.c | 537 ++ reactos/subsys/win32k/freetype/cidload.h | 70 + reactos/subsys/win32k/freetype/cidobjs.c | 380 + reactos/subsys/win32k/freetype/cidobjs.h | 141 + reactos/subsys/win32k/freetype/cidparse.c | 1024 +++ reactos/subsys/win32k/freetype/cidparse.h | 353 + reactos/subsys/win32k/freetype/cidriver.c | 259 + reactos/subsys/win32k/freetype/cidriver.h | 29 + reactos/subsys/win32k/freetype/cidtokens.h | 99 + reactos/subsys/win32k/freetype/ctype.c | 703 ++ reactos/subsys/win32k/freetype/docs/build | 264 + .../freetype/docs/design/build-system.html | 910 ++ .../freetype/docs/design/demo-programs.png | 1 + .../freetype/docs/design/drivers-list.png | 1 + .../win32k/freetype/docs/design/index.html | 791 ++ .../freetype/docs/design/io-frames.html | 343 + .../docs/design/library-compilation.png | 1 + .../win32k/freetype/docs/design/logo1.png | 1 + .../freetype/docs/design/objects_diagram.png | 1 + .../freetype/docs/design/objects_diagram2.png | 1 + .../docs/design/platform-detection.png | 1 + .../docs/design/system-interface.html | 258 + .../subsys/win32k/freetype/docs/docmaker.py | 516 ++ .../win32k/freetype/docs/freetype2.html | 352 + .../subsys/win32k/freetype/docs/ft2faq.html | 502 ++ .../subsys/win32k/freetype/docs/glnames.py | 1706 ++++ .../win32k/freetype/docs/glyphs/Image1.png | 1 + .../win32k/freetype/docs/glyphs/Image2.png | 1 + .../win32k/freetype/docs/glyphs/Image3.png | 1 + .../win32k/freetype/docs/glyphs/Image4.png | 1 + .../win32k/freetype/docs/glyphs/bbox1.png | 1 + .../win32k/freetype/docs/glyphs/bbox2.png | 1 + .../freetype/docs/glyphs/body_comparison.png | 1 + .../freetype/docs/glyphs/bravo_kerned.png | 1 + .../freetype/docs/glyphs/bravo_unkerned.png | 1 + .../win32k/freetype/docs/glyphs/clipping.png | 1 + .../win32k/freetype/docs/glyphs/down_flow.png | 1 + .../win32k/freetype/docs/glyphs/grid_1.png | 1 + .../win32k/freetype/docs/glyphs/index.html | 1626 ++++ .../freetype/docs/glyphs/points_conic.png | 1 + .../freetype/docs/glyphs/points_conic2.png | 1 + .../freetype/docs/glyphs/points_cubic.png | 1 + .../freetype/docs/glyphs/points_segment.png | 1 + .../win32k/freetype/docs/glyphs/twlewis1.png | 1 + .../win32k/freetype/docs/glyphs/twlewis2.png | 1 + .../win32k/freetype/docs/glyphs/up_flow.png | 1 + .../win32k/freetype/docs/tutorial/index.html | 871 ++ .../win32k/freetype/docs/tutorial/step1.html | 956 +++ .../win32k/freetype/docs/tutorial/step2.html | 1399 +++ reactos/subsys/win32k/freetype/ftbase.c | 44 + reactos/subsys/win32k/freetype/ftcalc.c | 773 ++ reactos/subsys/win32k/freetype/ftdebug.c | 124 + reactos/subsys/win32k/freetype/ftextend.c | 332 + reactos/subsys/win32k/freetype/ftglyph.c | 1184 +++ reactos/subsys/win32k/freetype/ftgrays.c | 1969 +++++ reactos/subsys/win32k/freetype/ftgrays.h | 52 + reactos/subsys/win32k/freetype/ftinit.c | 155 + reactos/subsys/win32k/freetype/ftlist.c | 301 + reactos/subsys/win32k/freetype/ftmm.c | 176 + reactos/subsys/win32k/freetype/ftnames.c | 70 + reactos/subsys/win32k/freetype/ftobjs.c | 3246 +++++++ reactos/subsys/win32k/freetype/ftoutln.c | 842 ++ reactos/subsys/win32k/freetype/ftraster.c | 3300 +++++++ reactos/subsys/win32k/freetype/ftraster.h | 50 + reactos/subsys/win32k/freetype/ftrend1.c | 275 + reactos/subsys/win32k/freetype/ftrend1.h | 37 + reactos/subsys/win32k/freetype/ftsmooth.c | 223 + reactos/subsys/win32k/freetype/ftsmooth.h | 35 + reactos/subsys/win32k/freetype/ftstream.c | 818 ++ reactos/subsys/win32k/freetype/ftsystem.c | 313 + .../include/freetype/config/ftconfig.h | 187 + .../include/freetype/config/ftmodule.h | 10 + .../include/freetype/config/ftoption.h | 395 + .../freetype/include/freetype/freetype.h | 2286 +++++ .../win32k/freetype/include/freetype/ftbbox.h | 72 + .../freetype/include/freetype/fterrors.h | 166 + .../freetype/include/freetype/ftglyph.h | 422 + .../freetype/include/freetype/ftimage.h | 1003 +++ .../win32k/freetype/include/freetype/ftmm.h | 175 + .../freetype/include/freetype/ftmodule.h | 274 + .../freetype/include/freetype/ftnames.h | 52 + .../freetype/include/freetype/ftoutln.h | 344 + .../freetype/include/freetype/ftrender.h | 191 + .../freetype/include/freetype/ftsystem.h | 101 + .../freetype/include/freetype/fttypes.h | 400 + .../include/freetype/internal/autohint.h | 195 + .../include/freetype/internal/ftcalc.h | 123 + .../include/freetype/internal/ftdebug.h | 225 + .../include/freetype/internal/ftdriver.h | 182 + .../include/freetype/internal/ftextend.h | 178 + .../include/freetype/internal/ftlist.h | 113 + .../include/freetype/internal/ftmemory.h | 127 + .../include/freetype/internal/ftobjs.h | 532 ++ .../include/freetype/internal/ftstream.h | 361 + .../include/freetype/internal/psnames.h | 220 + .../freetype/include/freetype/internal/sfnt.h | 492 ++ .../include/freetype/internal/t1errors.h | 67 + .../include/freetype/internal/t1types.h | 188 + .../include/freetype/internal/t2errors.h | 121 + .../include/freetype/internal/t2types.h | 218 + .../include/freetype/internal/tterrors.h | 121 + .../include/freetype/internal/tttypes.h | 1582 ++++ .../freetype/include/freetype/t1tables.h | 235 + .../freetype/include/freetype/ttnameid.h | 698 ++ .../freetype/include/freetype/tttables.h | 583 ++ .../win32k/freetype/include/freetype/tttags.h | 66 + reactos/subsys/win32k/freetype/license.txt | 164 + reactos/subsys/win32k/freetype/obj/README | 1 + reactos/subsys/win32k/freetype/psmodule.c | 322 + reactos/subsys/win32k/freetype/psmodule.h | 29 + reactos/subsys/win32k/freetype/psnames.c | 24 + reactos/subsys/win32k/freetype/pstables.h | 2942 +++++++ reactos/subsys/win32k/freetype/raster1.c | 37 + reactos/subsys/win32k/freetype/sfdriver.c | 225 + reactos/subsys/win32k/freetype/sfdriver.h | 29 + reactos/subsys/win32k/freetype/sfnt.c | 59 + reactos/subsys/win32k/freetype/sfobjs.c | 561 ++ reactos/subsys/win32k/freetype/sfobjs.h | 57 + reactos/subsys/win32k/freetype/smooth.c | 37 + .../freetype/src/autohint/CatharonLicense.txt | 123 + .../win32k/freetype/src/autohint/ahangles.c | 137 + .../win32k/freetype/src/autohint/ahangles.h | 63 + .../win32k/freetype/src/autohint/ahglobal.c | 402 + .../win32k/freetype/src/autohint/ahglobal.h | 52 + .../win32k/freetype/src/autohint/ahglyph.c | 1299 +++ .../win32k/freetype/src/autohint/ahglyph.h | 93 + .../win32k/freetype/src/autohint/ahhint.c | 1398 +++ .../win32k/freetype/src/autohint/ahhint.h | 72 + .../win32k/freetype/src/autohint/ahloader.h | 124 + .../win32k/freetype/src/autohint/ahmodule.c | 127 + .../win32k/freetype/src/autohint/ahmodule.h | 32 + .../win32k/freetype/src/autohint/ahoptim.c | 889 ++ .../win32k/freetype/src/autohint/ahoptim.h | 136 + .../win32k/freetype/src/autohint/ahtypes.h | 492 ++ .../win32k/freetype/src/autohint/autohint.c | 43 + .../win32k/freetype/src/autohint/mather.py | 78 + .../win32k/freetype/src/autohint/module.mk | 7 + .../win32k/freetype/src/autohint/rules.mk | 77 + .../subsys/win32k/freetype/src/base/ftbase.c | 42 + .../subsys/win32k/freetype/src/base/ftcalc.c | 773 ++ .../subsys/win32k/freetype/src/base/ftdebug.c | 124 + .../win32k/freetype/src/base/ftextend.c | 332 + .../subsys/win32k/freetype/src/base/ftglyph.c | 1184 +++ .../subsys/win32k/freetype/src/base/ftinit.c | 155 + .../subsys/win32k/freetype/src/base/ftlist.c | 301 + .../subsys/win32k/freetype/src/base/ftmm.c | 176 + .../subsys/win32k/freetype/src/base/ftnames.c | 70 + .../subsys/win32k/freetype/src/base/ftobjs.c | 3246 +++++++ .../subsys/win32k/freetype/src/base/ftoutln.c | 842 ++ .../win32k/freetype/src/base/ftstream.c | 818 ++ .../win32k/freetype/src/base/ftsystem.c | 299 + .../subsys/win32k/freetype/src/base/rules.mk | 83 + reactos/subsys/win32k/freetype/src/cff/cff.c | 40 + .../subsys/win32k/freetype/src/cff/module.mk | 7 + .../subsys/win32k/freetype/src/cff/rules.mk | 69 + .../subsys/win32k/freetype/src/cff/t2driver.c | 377 + .../subsys/win32k/freetype/src/cff/t2driver.h | 30 + .../subsys/win32k/freetype/src/cff/t2gload.c | 2045 +++++ .../subsys/win32k/freetype/src/cff/t2gload.h | 213 + .../subsys/win32k/freetype/src/cff/t2load.c | 757 ++ .../subsys/win32k/freetype/src/cff/t2load.h | 69 + .../subsys/win32k/freetype/src/cff/t2objs.c | 600 ++ .../subsys/win32k/freetype/src/cff/t2objs.h | 148 + .../subsys/win32k/freetype/src/cff/t2parse.c | 641 ++ .../subsys/win32k/freetype/src/cff/t2parse.h | 70 + .../subsys/win32k/freetype/src/cff/t2tokens.h | 96 + .../subsys/win32k/freetype/src/cid/cidafm.c | 293 + .../subsys/win32k/freetype/src/cid/cidafm.h | 78 + .../subsys/win32k/freetype/src/cid/cidgload.c | 1558 ++++ .../subsys/win32k/freetype/src/cid/cidgload.h | 198 + .../subsys/win32k/freetype/src/cid/cidload.c | 537 ++ .../subsys/win32k/freetype/src/cid/cidload.h | 70 + .../subsys/win32k/freetype/src/cid/cidobjs.c | 380 + .../subsys/win32k/freetype/src/cid/cidobjs.h | 141 + .../subsys/win32k/freetype/src/cid/cidparse.c | 1024 +++ .../subsys/win32k/freetype/src/cid/cidparse.h | 353 + .../subsys/win32k/freetype/src/cid/cidriver.c | 259 + .../subsys/win32k/freetype/src/cid/cidriver.h | 29 + .../win32k/freetype/src/cid/cidtokens.h | 99 + .../subsys/win32k/freetype/src/cid/module.mk | 6 + .../subsys/win32k/freetype/src/cid/rules.mk | 69 + .../subsys/win32k/freetype/src/cid/type1cid.c | 40 + .../win32k/freetype/src/macfond/fonddrvr.c | 616 ++ .../win32k/freetype/src/otlayout/oltypes.c | 614 ++ .../win32k/freetype/src/otlayout/oltypes.h | 310 + .../win32k/freetype/src/psnames/module.mk | 7 + .../win32k/freetype/src/psnames/psmodule.c | 320 + .../win32k/freetype/src/psnames/psmodule.h | 29 + .../win32k/freetype/src/psnames/psnames.c | 24 + .../win32k/freetype/src/psnames/pstables.h | 2942 +++++++ .../win32k/freetype/src/psnames/rules.mk | 70 + .../win32k/freetype/src/raster1/ftraster.c | 3300 +++++++ .../win32k/freetype/src/raster1/ftraster.h | 50 + .../win32k/freetype/src/raster1/ftrend1.c | 275 + .../win32k/freetype/src/raster1/ftrend1.h | 37 + .../win32k/freetype/src/raster1/module.mk | 7 + .../win32k/freetype/src/raster1/raster1.c | 35 + .../win32k/freetype/src/raster1/rules.mk | 69 + .../subsys/win32k/freetype/src/sfnt/module.mk | 7 + .../subsys/win32k/freetype/src/sfnt/rules.mk | 73 + .../win32k/freetype/src/sfnt/sfdriver.c | 225 + .../win32k/freetype/src/sfnt/sfdriver.h | 29 + .../subsys/win32k/freetype/src/sfnt/sfnt.c | 57 + .../subsys/win32k/freetype/src/sfnt/sfobjs.c | 561 ++ .../subsys/win32k/freetype/src/sfnt/sfobjs.h | 57 + .../subsys/win32k/freetype/src/sfnt/ttcmap.c | 550 ++ .../subsys/win32k/freetype/src/sfnt/ttcmap.h | 45 + .../subsys/win32k/freetype/src/sfnt/ttload.c | 1676 ++++ .../subsys/win32k/freetype/src/sfnt/ttload.h | 132 + .../subsys/win32k/freetype/src/sfnt/ttpost.c | 536 ++ .../subsys/win32k/freetype/src/sfnt/ttpost.h | 52 + .../subsys/win32k/freetype/src/sfnt/ttsbit.c | 1444 ++++ .../subsys/win32k/freetype/src/sfnt/ttsbit.h | 65 + .../win32k/freetype/src/smooth/ftgrays.c | 1969 +++++ .../win32k/freetype/src/smooth/ftgrays.h | 52 + .../win32k/freetype/src/smooth/ftsmooth.c | 220 + .../win32k/freetype/src/smooth/ftsmooth.h | 35 + .../win32k/freetype/src/smooth/module.mk | 7 + .../win32k/freetype/src/smooth/rules.mk | 69 + .../win32k/freetype/src/smooth/smooth.c | 35 + .../win32k/freetype/src/truetype/module.mk | 7 + .../win32k/freetype/src/truetype/rules.mk | 70 + .../win32k/freetype/src/truetype/truetype.c | 47 + .../win32k/freetype/src/truetype/ttdriver.c | 511 ++ .../win32k/freetype/src/truetype/ttdriver.h | 31 + .../win32k/freetype/src/truetype/ttgload.c | 1477 ++++ .../win32k/freetype/src/truetype/ttgload.h | 69 + .../win32k/freetype/src/truetype/ttinterp.c | 7544 +++++++++++++++++ .../win32k/freetype/src/truetype/ttinterp.h | 278 + .../win32k/freetype/src/truetype/ttobjs.c | 734 ++ .../win32k/freetype/src/truetype/ttobjs.h | 412 + .../win32k/freetype/src/truetype/ttpload.c | 273 + .../win32k/freetype/src/truetype/ttpload.h | 51 + .../win32k/freetype/src/type1/module.mk0 | 6 + .../win32k/freetype/src/type1/rules.mk0 | 74 + .../subsys/win32k/freetype/src/type1/t1afm.c | 293 + .../subsys/win32k/freetype/src/type1/t1afm.h | 70 + .../win32k/freetype/src/type1/t1driver.c | 381 + .../win32k/freetype/src/type1/t1driver.h | 30 + .../win32k/freetype/src/type1/t1gload.c | 1823 ++++ .../win32k/freetype/src/type1/t1gload.h | 326 + .../win32k/freetype/src/type1/t1hinter.c | 1347 +++ .../win32k/freetype/src/type1/t1hinter.h | 273 + .../subsys/win32k/freetype/src/type1/t1load.c | 1594 ++++ .../subsys/win32k/freetype/src/type1/t1load.h | 57 + .../subsys/win32k/freetype/src/type1/t1objs.c | 544 ++ .../subsys/win32k/freetype/src/type1/t1objs.h | 172 + .../win32k/freetype/src/type1/t1parse.c | 761 ++ .../win32k/freetype/src/type1/t1parse.h | 261 + .../win32k/freetype/src/type1/t1tokens.c | 1101 +++ .../win32k/freetype/src/type1/t1tokens.h | 258 + .../subsys/win32k/freetype/src/type1/type1.c | 59 + .../win32k/freetype/src/type1z/Readme.txt | 10 + .../win32k/freetype/src/type1z/module.mk | 7 + .../win32k/freetype/src/type1z/rules.mk | 72 + .../win32k/freetype/src/type1z/type1z.c | 49 + .../subsys/win32k/freetype/src/type1z/z1afm.c | 293 + .../subsys/win32k/freetype/src/type1z/z1afm.h | 79 + .../win32k/freetype/src/type1z/z1driver.c | 340 + .../win32k/freetype/src/type1z/z1driver.h | 29 + .../win32k/freetype/src/type1z/z1gload.c | 1482 ++++ .../win32k/freetype/src/type1z/z1gload.h | 187 + .../win32k/freetype/src/type1z/z1load.c | 1725 ++++ .../win32k/freetype/src/type1z/z1load.h | 93 + .../win32k/freetype/src/type1z/z1objs.c | 398 + .../win32k/freetype/src/type1z/z1objs.h | 161 + .../win32k/freetype/src/type1z/z1parse.c | 1398 +++ .../win32k/freetype/src/type1z/z1parse.h | 363 + .../win32k/freetype/src/type1z/z1tokens.h | 132 + .../win32k/freetype/src/winfonts/module.mk | 6 + .../win32k/freetype/src/winfonts/rules.mk | 64 + .../win32k/freetype/src/winfonts/winfnt.c | 623 ++ .../win32k/freetype/src/winfonts/winfnt.h | 150 + reactos/subsys/win32k/freetype/t1afm.c | 293 + reactos/subsys/win32k/freetype/t1afm.h | 70 + reactos/subsys/win32k/freetype/t1driver.c | 381 + reactos/subsys/win32k/freetype/t1driver.h | 30 + reactos/subsys/win32k/freetype/t1gload.c | 1823 ++++ reactos/subsys/win32k/freetype/t1gload.h | 326 + reactos/subsys/win32k/freetype/t1hinter.c | 1347 +++ reactos/subsys/win32k/freetype/t1hinter.h | 273 + reactos/subsys/win32k/freetype/t1load.c | 1594 ++++ reactos/subsys/win32k/freetype/t1load.h | 57 + reactos/subsys/win32k/freetype/t1objs.c | 544 ++ reactos/subsys/win32k/freetype/t1objs.h | 172 + reactos/subsys/win32k/freetype/t1parse.c | 761 ++ reactos/subsys/win32k/freetype/t1parse.h | 261 + reactos/subsys/win32k/freetype/t1tokens.c | 1101 +++ reactos/subsys/win32k/freetype/t1tokens.h | 258 + reactos/subsys/win32k/freetype/t2driver.c | 377 + reactos/subsys/win32k/freetype/t2driver.h | 30 + reactos/subsys/win32k/freetype/t2gload.c | 2045 +++++ reactos/subsys/win32k/freetype/t2gload.h | 213 + reactos/subsys/win32k/freetype/t2load.c | 757 ++ reactos/subsys/win32k/freetype/t2load.h | 69 + reactos/subsys/win32k/freetype/t2objs.c | 600 ++ reactos/subsys/win32k/freetype/t2objs.h | 148 + reactos/subsys/win32k/freetype/t2parse.c | 641 ++ reactos/subsys/win32k/freetype/t2parse.h | 70 + reactos/subsys/win32k/freetype/t2tokens.h | 96 + reactos/subsys/win32k/freetype/truetype.c | 49 + reactos/subsys/win32k/freetype/ttcmap.c | 550 ++ reactos/subsys/win32k/freetype/ttcmap.h | 45 + reactos/subsys/win32k/freetype/ttdriver.c | 511 ++ reactos/subsys/win32k/freetype/ttdriver.h | 31 + reactos/subsys/win32k/freetype/ttgload.c | 1477 ++++ reactos/subsys/win32k/freetype/ttgload.h | 69 + reactos/subsys/win32k/freetype/ttinterp.c | 7544 +++++++++++++++++ reactos/subsys/win32k/freetype/ttinterp.h | 278 + reactos/subsys/win32k/freetype/ttload.c | 1676 ++++ reactos/subsys/win32k/freetype/ttload.h | 132 + reactos/subsys/win32k/freetype/ttobjs.c | 734 ++ reactos/subsys/win32k/freetype/ttobjs.h | 412 + reactos/subsys/win32k/freetype/ttpload.c | 273 + reactos/subsys/win32k/freetype/ttpload.h | 51 + reactos/subsys/win32k/freetype/ttpost.c | 536 ++ reactos/subsys/win32k/freetype/ttpost.h | 52 + reactos/subsys/win32k/freetype/ttsbit.c | 1444 ++++ reactos/subsys/win32k/freetype/ttsbit.h | 65 + reactos/subsys/win32k/freetype/type1.c | 61 + reactos/subsys/win32k/freetype/type1cid.c | 42 + reactos/subsys/win32k/freetype/type1z.c | 51 + reactos/subsys/win32k/freetype/winfnt.c | 625 ++ reactos/subsys/win32k/freetype/winfnt.h | 150 + reactos/subsys/win32k/freetype/z1afm.c | 293 + reactos/subsys/win32k/freetype/z1afm.h | 79 + reactos/subsys/win32k/freetype/z1driver.c | 340 + reactos/subsys/win32k/freetype/z1driver.h | 29 + reactos/subsys/win32k/freetype/z1gload.c | 1482 ++++ reactos/subsys/win32k/freetype/z1gload.h | 187 + reactos/subsys/win32k/freetype/z1load.c | 1725 ++++ reactos/subsys/win32k/freetype/z1load.h | 93 + reactos/subsys/win32k/freetype/z1objs.c | 398 + reactos/subsys/win32k/freetype/z1objs.h | 161 + reactos/subsys/win32k/freetype/z1parse.c | 1398 +++ reactos/subsys/win32k/freetype/z1parse.h | 363 + reactos/subsys/win32k/freetype/z1tokens.h | 132 + 388 files changed, 177192 insertions(+) create mode 100644 reactos/subsys/win32k/freetype/CHANGES create mode 100644 reactos/subsys/win32k/freetype/ahangles.c create mode 100644 reactos/subsys/win32k/freetype/ahangles.h create mode 100644 reactos/subsys/win32k/freetype/ahglobal.c create mode 100644 reactos/subsys/win32k/freetype/ahglobal.h create mode 100644 reactos/subsys/win32k/freetype/ahglyph.c create mode 100644 reactos/subsys/win32k/freetype/ahglyph.h create mode 100644 reactos/subsys/win32k/freetype/ahhint.c create mode 100644 reactos/subsys/win32k/freetype/ahhint.h create mode 100644 reactos/subsys/win32k/freetype/ahloader.h create mode 100644 reactos/subsys/win32k/freetype/ahmodule.c create mode 100644 reactos/subsys/win32k/freetype/ahmodule.h create mode 100644 reactos/subsys/win32k/freetype/ahoptim.c create mode 100644 reactos/subsys/win32k/freetype/ahoptim.h create mode 100644 reactos/subsys/win32k/freetype/ahtypes.h create mode 100644 reactos/subsys/win32k/freetype/autohint.c create mode 100644 reactos/subsys/win32k/freetype/builds/ansi/ansi.mk create mode 100644 reactos/subsys/win32k/freetype/builds/detect.mk create mode 100644 reactos/subsys/win32k/freetype/builds/dos/detect.mk create mode 100644 reactos/subsys/win32k/freetype/builds/dos/dos-gcc.mk create mode 100644 reactos/subsys/win32k/freetype/builds/freetype.mk create mode 100644 reactos/subsys/win32k/freetype/builds/mac/ftlib.prj create mode 100644 reactos/subsys/win32k/freetype/builds/mac/readme create mode 100644 reactos/subsys/win32k/freetype/builds/modules.mk create mode 100644 reactos/subsys/win32k/freetype/builds/os2/detect.mk create mode 100644 reactos/subsys/win32k/freetype/builds/os2/os2-dev.mk create mode 100644 reactos/subsys/win32k/freetype/builds/os2/os2-gcc.mk create mode 100644 reactos/subsys/win32k/freetype/builds/unix/aclocal.m4 create mode 100644 reactos/subsys/win32k/freetype/builds/unix/config.guess create mode 100644 reactos/subsys/win32k/freetype/builds/unix/config.sub create mode 100644 reactos/subsys/win32k/freetype/builds/unix/configure create mode 100644 reactos/subsys/win32k/freetype/builds/unix/configure.in create mode 100644 reactos/subsys/win32k/freetype/builds/unix/detect.mk create mode 100644 reactos/subsys/win32k/freetype/builds/unix/ftconfig.in create mode 100644 reactos/subsys/win32k/freetype/builds/unix/ftsystem.c create mode 100644 reactos/subsys/win32k/freetype/builds/unix/install-sh create mode 100644 reactos/subsys/win32k/freetype/builds/unix/ltconfig create mode 100644 reactos/subsys/win32k/freetype/builds/unix/ltmain.sh create mode 100644 reactos/subsys/win32k/freetype/builds/unix/mkinstalldirs create mode 100644 reactos/subsys/win32k/freetype/builds/unix/unix.in create mode 100644 reactos/subsys/win32k/freetype/builds/win32/detect.mk create mode 100644 reactos/subsys/win32k/freetype/builds/win32/w32-dev.mk create mode 100644 reactos/subsys/win32k/freetype/builds/win32/w32-gcc.mk create mode 100644 reactos/subsys/win32k/freetype/builds/win32/w32-icc.mk create mode 100644 reactos/subsys/win32k/freetype/builds/win32/w32-lcc.mk create mode 100644 reactos/subsys/win32k/freetype/builds/win32/w32-vcc.mk create mode 100644 reactos/subsys/win32k/freetype/cff.c create mode 100644 reactos/subsys/win32k/freetype/cidafm.c create mode 100644 reactos/subsys/win32k/freetype/cidafm.h create mode 100644 reactos/subsys/win32k/freetype/cidgload.c create mode 100644 reactos/subsys/win32k/freetype/cidgload.h create mode 100644 reactos/subsys/win32k/freetype/cidload.c create mode 100644 reactos/subsys/win32k/freetype/cidload.h create mode 100644 reactos/subsys/win32k/freetype/cidobjs.c create mode 100644 reactos/subsys/win32k/freetype/cidobjs.h create mode 100644 reactos/subsys/win32k/freetype/cidparse.c create mode 100644 reactos/subsys/win32k/freetype/cidparse.h create mode 100644 reactos/subsys/win32k/freetype/cidriver.c create mode 100644 reactos/subsys/win32k/freetype/cidriver.h create mode 100644 reactos/subsys/win32k/freetype/cidtokens.h create mode 100644 reactos/subsys/win32k/freetype/ctype.c create mode 100644 reactos/subsys/win32k/freetype/docs/build create mode 100644 reactos/subsys/win32k/freetype/docs/design/build-system.html create mode 100644 reactos/subsys/win32k/freetype/docs/design/demo-programs.png create mode 100644 reactos/subsys/win32k/freetype/docs/design/drivers-list.png create mode 100644 reactos/subsys/win32k/freetype/docs/design/index.html create mode 100644 reactos/subsys/win32k/freetype/docs/design/io-frames.html create mode 100644 reactos/subsys/win32k/freetype/docs/design/library-compilation.png create mode 100644 reactos/subsys/win32k/freetype/docs/design/logo1.png create mode 100644 reactos/subsys/win32k/freetype/docs/design/objects_diagram.png create mode 100644 reactos/subsys/win32k/freetype/docs/design/objects_diagram2.png create mode 100644 reactos/subsys/win32k/freetype/docs/design/platform-detection.png create mode 100644 reactos/subsys/win32k/freetype/docs/design/system-interface.html create mode 100644 reactos/subsys/win32k/freetype/docs/docmaker.py create mode 100644 reactos/subsys/win32k/freetype/docs/freetype2.html create mode 100644 reactos/subsys/win32k/freetype/docs/ft2faq.html create mode 100644 reactos/subsys/win32k/freetype/docs/glnames.py create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/Image1.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/Image2.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/Image3.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/Image4.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/bbox1.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/bbox2.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/body_comparison.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/bravo_kerned.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/bravo_unkerned.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/clipping.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/down_flow.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/grid_1.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/index.html create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/points_conic.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/points_conic2.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/points_cubic.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/points_segment.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/twlewis1.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/twlewis2.png create mode 100644 reactos/subsys/win32k/freetype/docs/glyphs/up_flow.png create mode 100644 reactos/subsys/win32k/freetype/docs/tutorial/index.html create mode 100644 reactos/subsys/win32k/freetype/docs/tutorial/step1.html create mode 100644 reactos/subsys/win32k/freetype/docs/tutorial/step2.html create mode 100644 reactos/subsys/win32k/freetype/ftbase.c create mode 100644 reactos/subsys/win32k/freetype/ftcalc.c create mode 100644 reactos/subsys/win32k/freetype/ftdebug.c create mode 100644 reactos/subsys/win32k/freetype/ftextend.c create mode 100644 reactos/subsys/win32k/freetype/ftglyph.c create mode 100644 reactos/subsys/win32k/freetype/ftgrays.c create mode 100644 reactos/subsys/win32k/freetype/ftgrays.h create mode 100644 reactos/subsys/win32k/freetype/ftinit.c create mode 100644 reactos/subsys/win32k/freetype/ftlist.c create mode 100644 reactos/subsys/win32k/freetype/ftmm.c create mode 100644 reactos/subsys/win32k/freetype/ftnames.c create mode 100644 reactos/subsys/win32k/freetype/ftobjs.c create mode 100644 reactos/subsys/win32k/freetype/ftoutln.c create mode 100644 reactos/subsys/win32k/freetype/ftraster.c create mode 100644 reactos/subsys/win32k/freetype/ftraster.h create mode 100644 reactos/subsys/win32k/freetype/ftrend1.c create mode 100644 reactos/subsys/win32k/freetype/ftrend1.h create mode 100644 reactos/subsys/win32k/freetype/ftsmooth.c create mode 100644 reactos/subsys/win32k/freetype/ftsmooth.h create mode 100644 reactos/subsys/win32k/freetype/ftstream.c create mode 100644 reactos/subsys/win32k/freetype/ftsystem.c create mode 100644 reactos/subsys/win32k/freetype/include/freetype/config/ftconfig.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/config/ftmodule.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/config/ftoption.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/freetype.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/ftbbox.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/fterrors.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/ftglyph.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/ftimage.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/ftmm.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/ftmodule.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/ftnames.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/ftoutln.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/ftrender.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/ftsystem.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/fttypes.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/autohint.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/ftcalc.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/ftdebug.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/ftdriver.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/ftextend.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/ftlist.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/ftmemory.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/ftobjs.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/ftstream.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/psnames.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/sfnt.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/t1errors.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/t1types.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/t2errors.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/t2types.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/tterrors.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/internal/tttypes.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/t1tables.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/ttnameid.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/tttables.h create mode 100644 reactos/subsys/win32k/freetype/include/freetype/tttags.h create mode 100644 reactos/subsys/win32k/freetype/license.txt create mode 100644 reactos/subsys/win32k/freetype/obj/README create mode 100644 reactos/subsys/win32k/freetype/psmodule.c create mode 100644 reactos/subsys/win32k/freetype/psmodule.h create mode 100644 reactos/subsys/win32k/freetype/psnames.c create mode 100644 reactos/subsys/win32k/freetype/pstables.h create mode 100644 reactos/subsys/win32k/freetype/raster1.c create mode 100644 reactos/subsys/win32k/freetype/sfdriver.c create mode 100644 reactos/subsys/win32k/freetype/sfdriver.h create mode 100644 reactos/subsys/win32k/freetype/sfnt.c create mode 100644 reactos/subsys/win32k/freetype/sfobjs.c create mode 100644 reactos/subsys/win32k/freetype/sfobjs.h create mode 100644 reactos/subsys/win32k/freetype/smooth.c create mode 100644 reactos/subsys/win32k/freetype/src/autohint/CatharonLicense.txt create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahangles.c create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahangles.h create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahglobal.c create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahglobal.h create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahglyph.c create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahglyph.h create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahhint.c create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahhint.h create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahloader.h create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahmodule.c create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahmodule.h create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahoptim.c create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahoptim.h create mode 100644 reactos/subsys/win32k/freetype/src/autohint/ahtypes.h create mode 100644 reactos/subsys/win32k/freetype/src/autohint/autohint.c create mode 100644 reactos/subsys/win32k/freetype/src/autohint/mather.py create mode 100644 reactos/subsys/win32k/freetype/src/autohint/module.mk create mode 100644 reactos/subsys/win32k/freetype/src/autohint/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/base/ftbase.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftcalc.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftdebug.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftextend.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftglyph.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftinit.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftlist.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftmm.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftnames.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftobjs.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftoutln.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftstream.c create mode 100644 reactos/subsys/win32k/freetype/src/base/ftsystem.c create mode 100644 reactos/subsys/win32k/freetype/src/base/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/cff/cff.c create mode 100644 reactos/subsys/win32k/freetype/src/cff/module.mk create mode 100644 reactos/subsys/win32k/freetype/src/cff/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2driver.c create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2driver.h create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2gload.c create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2gload.h create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2load.c create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2load.h create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2objs.c create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2objs.h create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2parse.c create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2parse.h create mode 100644 reactos/subsys/win32k/freetype/src/cff/t2tokens.h create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidafm.c create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidafm.h create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidgload.c create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidgload.h create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidload.c create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidload.h create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidobjs.c create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidobjs.h create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidparse.c create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidparse.h create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidriver.c create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidriver.h create mode 100644 reactos/subsys/win32k/freetype/src/cid/cidtokens.h create mode 100644 reactos/subsys/win32k/freetype/src/cid/module.mk create mode 100644 reactos/subsys/win32k/freetype/src/cid/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/cid/type1cid.c create mode 100644 reactos/subsys/win32k/freetype/src/macfond/fonddrvr.c create mode 100644 reactos/subsys/win32k/freetype/src/otlayout/oltypes.c create mode 100644 reactos/subsys/win32k/freetype/src/otlayout/oltypes.h create mode 100644 reactos/subsys/win32k/freetype/src/psnames/module.mk create mode 100644 reactos/subsys/win32k/freetype/src/psnames/psmodule.c create mode 100644 reactos/subsys/win32k/freetype/src/psnames/psmodule.h create mode 100644 reactos/subsys/win32k/freetype/src/psnames/psnames.c create mode 100644 reactos/subsys/win32k/freetype/src/psnames/pstables.h create mode 100644 reactos/subsys/win32k/freetype/src/psnames/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/raster1/ftraster.c create mode 100644 reactos/subsys/win32k/freetype/src/raster1/ftraster.h create mode 100644 reactos/subsys/win32k/freetype/src/raster1/ftrend1.c create mode 100644 reactos/subsys/win32k/freetype/src/raster1/ftrend1.h create mode 100644 reactos/subsys/win32k/freetype/src/raster1/module.mk create mode 100644 reactos/subsys/win32k/freetype/src/raster1/raster1.c create mode 100644 reactos/subsys/win32k/freetype/src/raster1/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/module.mk create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/sfdriver.c create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/sfdriver.h create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/sfnt.c create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/sfobjs.c create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/sfobjs.h create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/ttcmap.c create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/ttcmap.h create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/ttload.c create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/ttload.h create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/ttpost.c create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/ttpost.h create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/ttsbit.c create mode 100644 reactos/subsys/win32k/freetype/src/sfnt/ttsbit.h create mode 100644 reactos/subsys/win32k/freetype/src/smooth/ftgrays.c create mode 100644 reactos/subsys/win32k/freetype/src/smooth/ftgrays.h create mode 100644 reactos/subsys/win32k/freetype/src/smooth/ftsmooth.c create mode 100644 reactos/subsys/win32k/freetype/src/smooth/ftsmooth.h create mode 100644 reactos/subsys/win32k/freetype/src/smooth/module.mk create mode 100644 reactos/subsys/win32k/freetype/src/smooth/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/smooth/smooth.c create mode 100644 reactos/subsys/win32k/freetype/src/truetype/module.mk create mode 100644 reactos/subsys/win32k/freetype/src/truetype/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/truetype/truetype.c create mode 100644 reactos/subsys/win32k/freetype/src/truetype/ttdriver.c create mode 100644 reactos/subsys/win32k/freetype/src/truetype/ttdriver.h create mode 100644 reactos/subsys/win32k/freetype/src/truetype/ttgload.c create mode 100644 reactos/subsys/win32k/freetype/src/truetype/ttgload.h create mode 100644 reactos/subsys/win32k/freetype/src/truetype/ttinterp.c create mode 100644 reactos/subsys/win32k/freetype/src/truetype/ttinterp.h create mode 100644 reactos/subsys/win32k/freetype/src/truetype/ttobjs.c create mode 100644 reactos/subsys/win32k/freetype/src/truetype/ttobjs.h create mode 100644 reactos/subsys/win32k/freetype/src/truetype/ttpload.c create mode 100644 reactos/subsys/win32k/freetype/src/truetype/ttpload.h create mode 100644 reactos/subsys/win32k/freetype/src/type1/module.mk0 create mode 100644 reactos/subsys/win32k/freetype/src/type1/rules.mk0 create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1afm.c create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1afm.h create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1driver.c create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1driver.h create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1gload.c create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1gload.h create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1hinter.c create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1hinter.h create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1load.c create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1load.h create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1objs.c create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1objs.h create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1parse.c create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1parse.h create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1tokens.c create mode 100644 reactos/subsys/win32k/freetype/src/type1/t1tokens.h create mode 100644 reactos/subsys/win32k/freetype/src/type1/type1.c create mode 100644 reactos/subsys/win32k/freetype/src/type1z/Readme.txt create mode 100644 reactos/subsys/win32k/freetype/src/type1z/module.mk create mode 100644 reactos/subsys/win32k/freetype/src/type1z/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/type1z/type1z.c create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1afm.c create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1afm.h create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1driver.c create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1driver.h create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1gload.c create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1gload.h create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1load.c create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1load.h create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1objs.c create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1objs.h create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1parse.c create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1parse.h create mode 100644 reactos/subsys/win32k/freetype/src/type1z/z1tokens.h create mode 100644 reactos/subsys/win32k/freetype/src/winfonts/module.mk create mode 100644 reactos/subsys/win32k/freetype/src/winfonts/rules.mk create mode 100644 reactos/subsys/win32k/freetype/src/winfonts/winfnt.c create mode 100644 reactos/subsys/win32k/freetype/src/winfonts/winfnt.h create mode 100644 reactos/subsys/win32k/freetype/t1afm.c create mode 100644 reactos/subsys/win32k/freetype/t1afm.h create mode 100644 reactos/subsys/win32k/freetype/t1driver.c create mode 100644 reactos/subsys/win32k/freetype/t1driver.h create mode 100644 reactos/subsys/win32k/freetype/t1gload.c create mode 100644 reactos/subsys/win32k/freetype/t1gload.h create mode 100644 reactos/subsys/win32k/freetype/t1hinter.c create mode 100644 reactos/subsys/win32k/freetype/t1hinter.h create mode 100644 reactos/subsys/win32k/freetype/t1load.c create mode 100644 reactos/subsys/win32k/freetype/t1load.h create mode 100644 reactos/subsys/win32k/freetype/t1objs.c create mode 100644 reactos/subsys/win32k/freetype/t1objs.h create mode 100644 reactos/subsys/win32k/freetype/t1parse.c create mode 100644 reactos/subsys/win32k/freetype/t1parse.h create mode 100644 reactos/subsys/win32k/freetype/t1tokens.c create mode 100644 reactos/subsys/win32k/freetype/t1tokens.h create mode 100644 reactos/subsys/win32k/freetype/t2driver.c create mode 100644 reactos/subsys/win32k/freetype/t2driver.h create mode 100644 reactos/subsys/win32k/freetype/t2gload.c create mode 100644 reactos/subsys/win32k/freetype/t2gload.h create mode 100644 reactos/subsys/win32k/freetype/t2load.c create mode 100644 reactos/subsys/win32k/freetype/t2load.h create mode 100644 reactos/subsys/win32k/freetype/t2objs.c create mode 100644 reactos/subsys/win32k/freetype/t2objs.h create mode 100644 reactos/subsys/win32k/freetype/t2parse.c create mode 100644 reactos/subsys/win32k/freetype/t2parse.h create mode 100644 reactos/subsys/win32k/freetype/t2tokens.h create mode 100644 reactos/subsys/win32k/freetype/truetype.c create mode 100644 reactos/subsys/win32k/freetype/ttcmap.c create mode 100644 reactos/subsys/win32k/freetype/ttcmap.h create mode 100644 reactos/subsys/win32k/freetype/ttdriver.c create mode 100644 reactos/subsys/win32k/freetype/ttdriver.h create mode 100644 reactos/subsys/win32k/freetype/ttgload.c create mode 100644 reactos/subsys/win32k/freetype/ttgload.h create mode 100644 reactos/subsys/win32k/freetype/ttinterp.c create mode 100644 reactos/subsys/win32k/freetype/ttinterp.h create mode 100644 reactos/subsys/win32k/freetype/ttload.c create mode 100644 reactos/subsys/win32k/freetype/ttload.h create mode 100644 reactos/subsys/win32k/freetype/ttobjs.c create mode 100644 reactos/subsys/win32k/freetype/ttobjs.h create mode 100644 reactos/subsys/win32k/freetype/ttpload.c create mode 100644 reactos/subsys/win32k/freetype/ttpload.h create mode 100644 reactos/subsys/win32k/freetype/ttpost.c create mode 100644 reactos/subsys/win32k/freetype/ttpost.h create mode 100644 reactos/subsys/win32k/freetype/ttsbit.c create mode 100644 reactos/subsys/win32k/freetype/ttsbit.h create mode 100644 reactos/subsys/win32k/freetype/type1.c create mode 100644 reactos/subsys/win32k/freetype/type1cid.c create mode 100644 reactos/subsys/win32k/freetype/type1z.c create mode 100644 reactos/subsys/win32k/freetype/winfnt.c create mode 100644 reactos/subsys/win32k/freetype/winfnt.h create mode 100644 reactos/subsys/win32k/freetype/z1afm.c create mode 100644 reactos/subsys/win32k/freetype/z1afm.h create mode 100644 reactos/subsys/win32k/freetype/z1driver.c create mode 100644 reactos/subsys/win32k/freetype/z1driver.h create mode 100644 reactos/subsys/win32k/freetype/z1gload.c create mode 100644 reactos/subsys/win32k/freetype/z1gload.h create mode 100644 reactos/subsys/win32k/freetype/z1load.c create mode 100644 reactos/subsys/win32k/freetype/z1load.h create mode 100644 reactos/subsys/win32k/freetype/z1objs.c create mode 100644 reactos/subsys/win32k/freetype/z1objs.h create mode 100644 reactos/subsys/win32k/freetype/z1parse.c create mode 100644 reactos/subsys/win32k/freetype/z1parse.h create mode 100644 reactos/subsys/win32k/freetype/z1tokens.h diff --git a/reactos/subsys/win32k/freetype/CHANGES b/reactos/subsys/win32k/freetype/CHANGES new file mode 100644 index 00000000000..d9d5816cb05 --- /dev/null +++ b/reactos/subsys/win32k/freetype/CHANGES @@ -0,0 +1,904 @@ +LATEST CHANGES + + - deactivated the trueType bytecode interpreter by default + + - deactivated the "src/type1" font driver. Now "src/type1z" is + used by default.. + + - updates to the build system. We now compile the library correctly + under Unix system through "configure" which is automatically called + on the first "make" invocation. + + - added the auto-hinting module !!. Fixing some bugs here and there.. + + - found some bugs in the composite loader (seac) of the Type1-based + font drivers.. + + - renamed the directory "freetype2/config" to "freetype2/builds" and + updated all relevant files.. + + - found a memory leak in the "type1" driver + + - incorporated Tom's patches to support flex operators correctly + in OpenType/CFF fonts.. Now all I need is to support pure CFF + and CEF fonts to be done with this driver.. :-) + + - added the Windows FNT/FON driver in "src/winfonts". For now, + it always "simulates" a Unicode charmap, so it shouldn't be + considered completed right now.. + + It's there to be more a proof of concept than anything else + anyway. The driver is a single C source file, that compiles + to 3 Kb of code.. + + I'm still working on the PCF/BDF drivers.. but I'm too lazy + to finish them now.. + + + - CHANGES TO THE HIGH-LEVEL API + + o FT_Get_Kerning has a new parameter that allows you to select + the coordinates of the kerning vector ( font units, scaled, + scaled + grid-fitted ). + + o the outline functions are now in and not + part of anymore + + o now contains declarations for + FT_New_Library, FT_Done_Library, FT_Add_Default_Modules + + o the so-called convenience functions have moved from "ftoutln.c" + to "ftglyph.c", and are thus available with this optional component + of the library. They are declared in now.. + + o anti-aliased rendering is now the default for FT_Render_Glyph + (i.e. corresponds to render_mode == 0 == ft_render_mode_normal). + To generate a monochrome bitmap, use ft_render_mode_mono, or the + FT_LOAD_MONOCHROME flag in FT_Load_Glyph/FT_Load_Char. + + FT_LOAD_ANTI_ALIAS is still defined, but values to 0. + + o now include , + solving a few headaches :-) + + o the type FT_GlyphSlotRec has now a "library" field. + + + + - CHANGES TO THE "ftglyph.h" API + + This API has been severely modified in order to make it simpler, + clearer, and more efficient. It certainly now looks like a real + "glyph factory" object, and allows client applications to manage + (i.e. transform, bbox and render) glyph images without ever knowing + their original format. + + - added support for CID-keyed fonts to the CFF driver. + maybe support for pure CFF + CEF fonts should come in ?? + + + - cleaned up source code in order to avoid two functions with the + same name. Also changed the names of the files in "type1z" from + "t1XXXX" to "z1XXXX" in order to avoid any conflicts. + + "make multi" now works well :-) + + Also removed the use of "cidafm" for now, even if the source files + are still there. This functionality will certainly go into a specific + module.. + + + + - ADDED SUPPORT FOR THE AUTO-HINTER + + It works :-) I have a demo program which simply is a copy of "ftview" + that does a FT_Add_Module( library, &autohinter_module_class ) after + library initialisation, and Type 1 & OpenType/CFF fonts are now hinted. + + CID fonts are not hinted, as they include no charmap and the auto-hinter + doesn't include "generic" global metrics computations yet.. + + Now, I need to release this thing to the FreeType 2 source.. + + + + + + - CHANGES TO THE RENDERER MODULES + + the monochrome and smooth renderers are now in two distinct directories, + namely "src/raster1" and "src/smooth". Note that the old "src/renderer" + is now gone.. + + I ditched the 5-gray-levels renderers. Basically, it involved a simple + #define toggle in 'src/raster1/ftraster.c' + + FT_Render_Glyph, FT_Outline_Render & FT_Outline_Get_Bitmap now select + the best renderer available, depending on render mode. If the current + renderer for a given glyph image format isn't capable of supporting + the render mode, another one will be found in the library's list. + + This means that client applications do not need to switch or set the + renderers themselves (as in the latest change), they'll get what they + want automatically... At last.. + + Changed the demo programs accordingly.. + + + + - MAJOR INTERNAL REDESIGN: + + A lot of internal modifications have been performed lately on the + source in order to provide the following enhancements: + + - more generic module support: + + The FT_Module type is now defined to represent a handle to a given + module. The file contains the FT_Module_Class + definition, as well as the module-loading public API + + The FT_Driver type is still defined, and still represents a pointer + to a font driver. Note that FT_Add_Driver is replaced by FT_Add_Module, + FT_Get_Driver by FT_Get_Module, etc.. + + + - support for generic glyph image types: + + The FT_Renderer type is a pointer to a module used to perform various + operations on glyph image. + + Each renderer is capable of handling images in a single format + (e.g. ft_glyph_format_outline). Its functions are used to: + + - transform an glyph image + - render a glyph image into a bitmap + - return the control box (dimensions) of a given glyph image + + + The scan converters "ftraster.c" and "ftgrays.c" have been moved + to the new directory "src/renderer", and are used to provide two + default renderer modules. + + One corresponds to the "standard" scan-converter, the other to the + "smooth" one. + + The current renderer can be set through the new function + FT_Set_Renderer. + + The old raster-related function FT_Set_Raster, FT_Get_Raster and + FT_Set_Raster_Mode have now disappeared, in favor of the new: + + FT_Get_Renderer + FT_Set_Renderer + + see the file for more details.. + + These changes were necessary to properly support different scalable + formats in the future, like bi-color glyphs, etc.. + + + - glyph loader object: + + A new internal object, called a 'glyph loader' has been introduced + in the base layer. It is used by all scalable format font drivers + to load glyphs and composites. + + This object has been created to reduce the code size of each driver, + as each one of them basically re-implemented its functionality. + + See and the FT_GlyphLoader type for + more information.. + + + + - FT_GlyphSlot had new fields: + + In order to support extended features (see below), the FT_GlyphSlot + structure has a few new fields: + + linearHoriAdvance: this field gives the linearly scaled (i.e. + scaled but unhinted) advance width for the glyph, + expressed as a 16.16 fixed pixel value. This + is useful to perform WYSIWYG text. + + linearVertAdvance: this field gives the linearly scaled advance + height for the glyph (relevant in vertical glyph + layouts only). This is useful to perform + WYSIWYG text. + + Note that the two above field replace the removed "metrics2" field + in the glyph slot. + + advance: this field is a vector that gives the transformed + advance for the glyph. By default, it corresponds + to the advance width, unless FT_LOAD_VERTICAL_LAYOUT + was specified when calling FT_Load_Glyph or FT_Load_Char + + bitmap_left: this field gives the distance in integer pixels from + the current pen position to the left-most pixel of + a glyph image WHEN IT IS A BITMAP. It is only valid + when the "format" field is set to + "ft_glyph_format_bitmap", for example, after calling + the new function FT_Render_Glyph. + + bitmap_top: this field gives the distance in integer pixels from + the current pen position (located on the baseline) to + the top-most pixel of the glyph image WHEN IT IS A + BITMAP. Positive values correspond to upwards Y. + + loader: this is a new private field for the glyph slot. Client + applications should not touch it.. + + + - support for transforms and direct rendering in FT_Load_Glyph: + + Most of the functionality found in has been + moved to the core library. Hence, the following: + + - a transform can be specified for a face through FT_Set_Transform. + this transform is applied by FT_Load_Glyph to scalable glyph images + (i.e. NOT TO BITMAPS) before the function returns, unless the + bit flag FT_LOAD_IGNORE_TRANSFORM was set in the load flags.. + + + - once a glyph image has been loaded, it can be directly converted to + a bitmap by using the new FT_Render_Glyph function. Note that this + function takes the glyph image from the glyph slot, and converts + it to a bitmap whose properties are returned in "face.glyph.bitmap", + "face.glyph.bitmap_left" and "face.glyph.bitmap_top". The original + native image might be lost after the conversion. + + + - when using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph + and FT_Load_Char functions will call FT_Render_Glyph automatically + when needed. + + + + + - reformated all modules source code in order to get rid of the basic + data types redifinitions (i.e. "TT_Int" instead of "FT_Int", "T1_Fixed" + instead of "FT_Fixed"). Hence the format-specific prefixes like "TT_", + "T1_", "T2_" and "CID_" are only used for relevant structures.. + +============================================================================ +OLD CHANGES FOR BETA 7 + + - bug-fixed the OpenType/CFF parser. It now loads and displays my two + fonts nicely, but I'm pretty certain that more testing is needed :-) + + - fixed the crummy Type 1 hinter, it now handles accented characters + correctly (well, the accent is not always well placed, but that's + another problem..) + + - added the CID-keyed Type 1 driver in "src/cid". Works pretty well for + only 13 Kb of code ;-) Doesn't read AFM files though, nor the really + useful CMAP files.. + + - fixed two bugs in the smooth renderer (src/base/ftgrays.c). Thanks to + Boris Letocha for spotting them and providing a fix.. + + - fixed potential "divide by zero" bugs in ftcalc.c.. my god.. + + - added source code for the OpenType/CFF driver (still incomplete though..) + + - modified the SFNT driver slightly to perform more robust header + checks in TT_Load_SFNT_Header. This prevents certain font files + (e.g. some Type 1 Multiple Masters) from being incorrectly "recognized" + as TrueType font files.. + + - moved a lot of stuff from the TrueType driver to the SFNT module, + this allows greater code re-use between font drivers (e.g. TrueType, + OpenType, Compact-TrueType, etc..) + + - added a tiny segment cache to the SFNT Charmap 4 decoder, in order + to minimally speed it up.. + + - added support for Multiple Master fonts in "type1z". There is also + a new file named which defines functions to + manage them from client applications. + + The new file "src/base/ftmm.c" is also optional to the engine.. + + - various formatting changes (e.g. EXPORT_DEF -> FT_EXPORT_DEF) + + small bug fixes in FT_Load_Glyph, the "type1" driver, etc.. + + - a minor fix to the Type 1 driver to let them apply the font matrix + correctly (used for many oblique fonts..) + + - some fixes for 64-bit systems (mainly changing some FT_TRACE calls + to use %p instead of %lx).. Thanks to Karl Robillard + + - fixed some bugs in the sbit loader (src/base/sfnt/ttsbit.c) + added + a new flag, FT_LOAD_CROP_BITMAP to query that bitmaps be cropped when + loaded from a file (maybe I should move the bitmap cropper to the + base layer ??). + + - changed the default number of gray levels of the smooth renderer to + 256 (instead of the previous 128). Of course, the human eye can't + see any difference ;-) + + - removed TT_MAX_SUBGLYPHS, there is no static limit on the number of + subglyphs in a TrueType font now.. + +============================================================================= +OLD CHANGES 16 May 2000 + + - tagged "BETA-6" in the CVS tree. This one is a serious release candidate + even though it doesn't incorporate the auto-hinter yet.. + + - various obsolete files were removed, and copyright header updated + + - finally updated the standard raster to fix the monochrome rendering bug + + re-enable support for 5-gray levels anti-aliasing (suck, suck..) + + - created new header files, and modified sources accordingly: + + - simple FreeType types, without the API + - definition of memory-management macros + + - added the "DSIG" (OpenType Digital Signature) tag to + + - light update/cleaning of the build system + changes to the sources in + order to get rid of _all_ compiler warnings with three compilers, i.e: + + gcc with "-ansi -pedantic -Wall -W", Visual C++ with "/W3 /WX" + and LCC + + IMPORTANT NOTE FOR WIN32-LCC USERS: + | + | It seems the C pre-processor that comes with LCC is broken, it + | doesn't recognize the ANSI standard directives # and ## correctly + | when one of the argument is a macro. Also, something like: + | + | #define F(x) print##x + | + | F(("hello")) + | + | will get incorrectly translated to: + | + | print "hello") + | + | by its pre-processor. For this reason, you simply cannot build + | FreeType 2 in debug mode with this compiler.. + + + - yet another massive grunt work. I've changed the definition of the + EXPORT_DEF, EXPORT_FUNC, BASE_DEF & BASE_FUNC macros. These now take + an argument, which is the function's return value type. + + This is necessary to compile FreeType as a DLL on Windows and OS/2. + Depending on the compiler used, a compiler-specific keyword like __export + or __system must be placed before (VisualC++) or after (BorlandC++) + the type.. + + Of course, this needed a lot of changes throughout the source code + to make it compile again... All cleaned up now, apparently.. + + Note also that there is a new EXPORT_VAR macro defined to allow the + _declaration_ of an exportable public (constant) variable. This is the + case of the raster interfaces (see ftraster.h and ftgrays.h), as well + as each module's interface (see sfdriver.h, psdriver.h, etc..) + + - new feature: it is now possible to pass extra parameters to font + drivers when creating a new face object. For now, this + capability is unused. It could however prove to be useful + in a near future.. + + the FT_Open_Args structure was changes, as well as the internal + driver interface (the specific "init_face" module function has now + a different signature). + + - updated the tutorial (not finished though). + - updated the top-level BUILD document + + - fixed a potential memory leak that could occur when loading embedded + bitmaps. + + - added the declaration of FT_New_Memory_Face in , as + it was missing from the public header (the implementation was already + in "ftobjs.c"). + + - the file has been seriously updated in order to + allow the automatic generation of error message tables. See the comments + within it for more information. + + - major directory hierarchy re-organisation. This was done for two things: + + * first, to ease the "manual" compilation of the library by requiring + at lot less include paths :-) + + * second, to allow external programs to effectively access internal + data fields. For example, this can be extremely useful if someone + wants to write a font producer or a font manager on top of FreeType. + + Basically, you should now use the 'freetype/' prefix for header inclusion, + as in: + + #include + #include + + Some new include sub-directories are available: + + a. the "freetype/config" directory, contains two files used to + configure the build of the library. Client applications should + not need to look at these normally, but they can if they want. + + #include + #include + + b. the "freetype/internal" directory, contains header files that + describes library internals. These are the header files that were + previously found in the "src/base" and "src/shared" directories. + + + As usual, the build system and the demos have been updated to reflect + the change.. + + Here's a layout of the new directory hierarchy: + + TOP + include/ + freetype/ + freetype.h + ... + config/ + ftoption.h + ftconfig.h + ftmodule.h + + internal/ + ftobjs.h + ftstream.h + ftcalc.h + ... + + src/ + base/ + ... + + sfnt/ + psnames/ + truetype/ + type1/ + type1z/ + + + Compiling a module is now much easier, for example, the following should + work when in the TOP directory on an ANSI build: + + gcc -c -I./include -I./src/base src/base/ftbase.c + gcc -c -I./include -I./src/sfnt src/sfnt/sfnt.c + etc.. + + (of course, using -Iconfig/ if you provide system-specific + configuration files). + + + - updated the structure of FT_Outline_Funcs in order to allow + direct coordinate scaling within the outline decomposition routine + (this is important for virtual "on" points with TrueType outlines) + + updates to the rasters to support this.. + + - updated the OS/2 table loading code in "src/sfnt/ttload.c" in order + to support version 2 of the table (see OpenType 1.2 spec) + + - created "include/tttables.h" and "include/t1tables.h" to allow + client applications to access some of the SFNT and T1 tables of a + face with a procedural interface (see FT_Get_Sfnt_Table()) + + updates to internal source files to reflect the change.. + + - some cleanups in the source code to get rid of warnings when compiling + with the "-Wall -W -ansi -pedantic" options in gcc. + + - debugged and moved the smooth renderer to "src/base/ftgrays.c" and + its header to "include/ftgrays.h" + + - updated TT_MAX_SUBGLYPHS to 96 as some CJK fonts have composites with + up to 80 sub-glyphs !! Thanks to Werner + +================================================================================ +OLD CHANGES - 14-apr-2000 + + - fixed a bug in the TrueType glyph loader that prevented the correct + loading of some CJK glyphs in mingli.ttf + + - improved the standard Type 1 hinter in "src/type1" + + - fixed two bugs in the experimental Type 1 driver in "src/type1z" + to handle the new XFree86 4.0 fonts (and a few other ones..) + + - the smooth renderer is now complete and supports sub-banding + to render large glyphs at high speed. However, it is still located + in "demos/src/ftgrays.c" and should move to the library itself + in the next beta.. NOTE: The smooth renderer doesn't compile in + stand-alone mode anymore, but this should be fixed RSN.. + + - introduced convenience functions to more easily deal with glyph + images, see "include/ftglyph.h" for more details, as well as the + new demo program named "demos/src/ftstring.c" that demonstrates + its use + + - implemented FT_LOAD_NO_RECURSE in both the TrueType and Type 1 + drivers (this is required by the auto-hinter to improve its results). + + - changed the raster interface, in order to allow client applications + to provide their own span-drawing callbacks. However, only the + smooth renderer supports this. See "FT_Raster_Params" in the + file "include/ftimage.h" + + - fixed a small bug in FT_MulFix that caused incorrect transform + computation !! + + - Note: The tutorial is out-of-date, grumpf.. :-( + +================================================================================ +OLD CHANGES - 12-mar-2000 + + - changed the layout of configuration files : now, all ANSI configuration + files are located in "freetype2/config". System-specific over-rides + can be placed in "freetype2/config/". + + - moved all configuration macros to "config/ftoption.h" + + - improvements in the Type 1 driver with AFM support + + - changed the fields in the FT_Outline structure : the old "flags" + array is re-named "tags", while all ancient flags are encoded into + a single unsigned int named "flags". + + - introduced new flags in FT_Outline.flags (see ft_outline_.... enums in + "ftimage.h"). + + - changed outline functions to "FT_Outline_" syntax + + - added a smooth anti-alias renderer to the demonstration programs + - added Mac graphics driver (thanks Just) + + - FT_Open_Face changed in order to received a pointer to a FT_Open_Args + descriptor.. + + - various cleanups, a few more API functions implemented (see FT_Attach_File) + + - updated some docs + +================================================================================ +OLD CHANGES - 22-feb-2000 + + - introduced the "psnames" module. It is used to: + + o convert a Postscript glyph name into the equivalent Unicode + character code (used by the Type 1 driver(s) to synthetize + on the fly a Unicode charmap). + + o provide an interface to retrieve the Postscript names of + the Macintosh, Adobe Standard & Adobe Expert character codes. + (the Macintosh names are used by the SFNT-module postscript + names support routines, while the other two tables are used + by the Type 1 driver(s)). + + - introduced the "type1z" alternate Type 1 driver. This is a (still + experimental) driver for the Type 1 format that will ultimately + replace the one in "src/type1". It uses pattern matching to load + data from the font, instead of a finite state analyzer. It works + much better than the "old" driver with "broken" fonts. It is also + much smaller (under 15 Kb). + + - the Type 1 drivers (both in "src/type1" and "src/type1z") are + nearly complete. They both provide automatic Unicode charmap + synthesis through the "psnames" module. No re-encoding vector + is needed. (note that they still leak memory due to some code + missing, and I'm getting lazy). + + Trivial AFM support has been added to read kerning information + but wasn't exactly tested as it should ;-) + + - The TrueType glyph loader has been seriously rewritten (see the + file "src/truetype/ttgload.c". It is now much, much simpler as + well as easier to read, maintain and understand :-) Preliminary + versions introduced a memory leak that has been reported by Jack + Davis, and is now fixed.. + + - introduced the new "ft_glyph_format_plotter", used to represent + stroked outlines like Windows "Vector" fonts, and certain Type 1 + fonts like "Hershey". The corresponding raster will be written + soon. + + - FT_New_Memory_Face is gone. Likewise, FT_Open_Face has a new + interface that uses a structure to describe the input stream, + the driver (if required), etc.. + +TODO + - Write FT_Get_Glyph_Bitmap and FT_Load_Glyph_Bitmap + + - Add a function like FT_Load_Character( face, char_code, load_flags ) + that would really embbed a call to FT_Get_Char_Index then FT_Load_Glyph + to ease developer's work. + + - Update the tutorial !! + - consider adding support for Multiple Master fonts in the Type 1 + drivers. + + - Test the AFM routines of the Type 1 drivers to check that kerning + information is returned correctly. + + - write a decent auto-gridding component !! We need this to release + FreeType 2.0 gold ! + + +----- less urgent needs : ---------- + - add a CFF/Type2 driver + - add a BDF driver + - add a FNT/PCF/HBF driver + - add a Speedo driver from the X11 sources + + +============================================================================== +OLDER CHANGES - 27-jan-2000 + + - updated the "sfnt" module interface to allow several SFNT-based + drivers to co-exist peacefully + + - updated the "T1_Face" type to better separate Postscript font content + from the rest of the FT_Face structure. Might be used later by the + CFF/Type2 driver.. + + - added an experimental replacement Type 1 driver featuring advanced + (and speedy) pattern matching to retrieve the data from postscript + fonts. + + - very minor changes in the implementation of FT_Set_Char_Size and + FT_Set_Pixel_Sizes (they now implement default to ligthen the + font driver's code). + + +============================================================================= +OLD MESSAGE + +This file summarizes the changes that occured since the last "beta" of FreeType 2. +Because the list is important, it has been divided into separate sections: + +Table Of Contents: + + I High-Level Interface (easier !) + II Directory Structure + III Glyph Image Formats + IV Build System + V Portability + VI Font Drivers + +----------------------------------------------------------------------------------------- +High-Level Interface : + + The high-level API has been considerably simplified. Here is how : + + - resource objects have disappeared. this means that face objects can + now be created with a single function call (see FT_New_Face and + FT_Open_Face) + + - when calling either FT_New_Face & FT_Open_Face, a size object and a + glyph slot object are automatically created for the face, and can be + accessed through "face->glyph" and "face->size" if one really needs to. + In most cases, there's no need to call FT_New_Size or FT_New_Glyph. + + - similarly, FT_Load_Glyph now only takes a "face" argument (instead of + a glyph slot and a size). Also, it's "result" parameter is gone, as + the glyph image type is returned in the field "face->glyph.format" + + - the list of available charmaps is directly accessible through + "face->charmaps", counting "face->num_charmaps" elements. Each + charmap has an 'encoding' field which specifies which known encoding + it deals with. Valid values are, for example : + + ft_encoding_unicode (for ASCII, Latin-1 and Unicode) + ft_encoding_apple_roman + ft_encoding_sjis + ft_encoding_adobe_standard + ft_encoding_adobe_expert + + other values may be added in the future. Each charmap still holds its + "platform_id" and "encoding_id" values in case the encoding is too + exotic for the current library + + +----------------------------------------------------------------------------------------- +Directory Structure: + + Should seem obvious to most of you: + + freetype/ + config/ -- configuration sub-makefiles + ansi/ + unix/ -- platform-specific configuration files + win32/ + os2/ + msdos/ + + include/ -- public header files, those to be included directly + by client apps + + src/ -- sources of the library + base/ -- the base layer + sfnt/ -- the sfnt "driver" (see the drivers section below) + truetype/ -- the truetype driver + type1/ -- the type1 driver + shared/ -- some header files shared between drivers + + demos/ -- demos/tools + + docs/ -- documentation (a bit empty for now) + +----------------------------------------------------------------------------------------- +Glyph Image Formats : + + Drivers are now able to register new glyph image formats within the library. + For now, the base layer supports of course bitmaps and vector outlines, but + one could imagine something different like colored bitmaps, bi-color + vectors or wathever else (Metafonts anyone ??). + + See the file `include/ftimage.h'. Note also that the type FT_Raster_Map is + gone, and is now replaced by FT_Bitmap, which should encompass all known + bitmap types. + + Each new image format must provide at least one "raster", i.e. a module + capable of transforming the glyph image into a bitmap. It's also possible + to change the default raster used for a given glyph image format. + + The default outline scan-converter now uses 128 levels of grays by default, + which tends to smooth many things. Note that the demo programs have been + updated significantly in order to display these.. + + +----------------------------------------------------------------------------------------- +Build system : + + You still need GNU Make to build the library. The build system has been + very seriously re-vamped in order to provide things like : + + - automatic host platform detection (reverting to 'config/ansi' + if it is not detected, with pseudo-standard compilation flags) + + - the ability to compile from the Makefiles with very different and + exotic compilers. Note that linking the library can be difficult for + some platforms. + + For example, the file `config/win32/lcclib.bat' is invoked by the + build system to create the ".lib" file with LCC-Win32 because its + librarian has too many flaws to be invoked directly from the Makefile. + + Here's how it works : + + - the first time you type `make', the build system runs a series of + sub-makefiles in order to detect your host platform. It then dumps + what it found, and creates a file called `config.mk' in the current + directory. This is a sub-Makefile used to define many important Make + variables used to build the library. + + - the second time, the build system detects the `config.mk' then use it + to build the library. All object files go into 'obj' by default, as + well as the library file, but this can easily be changed. + + Note that you can run "make setup" to force another host platform detection + even if a `config.mk' is present in the current directory. Another solution + is simply to delete the file, then re-run make. + + Finally, the default compiler for all platforms is gcc (for now, this will + hopefully changed in the future). You can however specify a different + compiler by specifying it after the 'setup' target as in : + + gnumake setup lcc on Win32 to use the LCC compiler + gnumake setup visualc on Win32 to use Visual C++ + + See the file `config//detect.mk' for a list of supported compilers + for your platforms. + + It should be relatively easy to write new detection rules files and + config.mk.. + + Finally, to build the demo programs, go to `demos' and launch GNU Make, + it will use the `config.mk' in the top directory to build the test + programs.. + +----------------------------------------------------------------------------------------- +Portability : + + In the previous beta, a single FT_System object was used to encompass + all low-level operations like thread synchronisation, memory management + and i/o access. This has been greatly simplified : + + - thread synchronisation has been dropped, for the simple reason that + the library is already re-entrant, and that if you really need two + threads accessing the same FT_Library, you should really synchronize + access to it yourself with a simple mutex. + + - memory management is performed through a very simple object called + "FT_Memory", which really is a table containing a table of pointers + to functions like malloc, realloc and free as well as some user data + (closure). + + - resources have disappeared (they created more problems than they + solved), and i/o management have been simplified greatly as a + result. Streams are defined through FT_Stream objects, which can + be either memory-based or disk-based. + + Note that each face has its own stream, which is closed only when + the face object is destroyed. Hence, a function like TT_Flush_Face + in 1.x cannot be directly supported. However, if you really need + something like this, you can easily tailor your own streams to achieve + the same feature at a lower level (and use FT_Open_Face instead of + FT_New_Face to create the face). + + See the file "include/ftsystem.h" for more details, as well as the + implementations found in "config/unix" and "config/ansi". + + +----------------------------------------------------------------------------------------- +Font Drivers : + + + The Font Driver interface has been modified in order to support + extensions & versioning. + + + The list of the font drivers that are statically linked to the + library at compile time is managed through a new configuration file + called `config//ftmodule.h'. + + This file is autogenerated when invoking `make modules'. This target + will parse all sub-directories of 'src', looking for a "module.mk" + rules file, used to describe the driver to the build system. + + Hence, one should call `make modules' each time a font driver is added + or removed from the `src' directory. + + + Finally, this version provides a "pseudo-driver" in `src/sfnt'. This + driver doesn't support font files directly, but provides services used + by all TrueType-like font drivers. Hence, its code is shared between + the TrueType & OpenType font formats, and possibly more formats to + come if we're lucky.. + +----------------------------------------------------------------------------------------- +Extensions support : + + The extensions support is inspired by the one found in 1.x. + + Now, each font driver has its own "extension registry", which lists + which extensions are available for the font faces managed by the driver. + + Extension ids are now strings, rather than 4-byte tags, as this is + usually more readable.. + + Each extension has: + - some data, associated to each face object + - an interface (table of function pointers) + + An extension that is format-specific should simply register itself + to the correct font driver. Here is some example code: + + // Registering an extensions + // + FT_Error FT_Init_XXXX_Extension( FT_Library library ) + { + FT_DriverInterface* tt_driver; + + driver = FT_Get_Driver( library, "truetype" ); + if (!driver) return FT_Err_Unimplemented_Feature; + + return FT_Register_Extension( driver, &extension_class ); + } + + + // Implementing the extensions + // + FT_Error FT_Proceed_Extension_XXX( FT_Face face ) + { + FT_XXX_Extension ext; + FT_XXX_Extension_Interface ext_interface; + + ext = FT_Get_Extension( face, "extensionid", &ext_interface ); + if (!ext) return error; + + return ext_interface->do_it(ext); + } + diff --git a/reactos/subsys/win32k/freetype/ahangles.c b/reactos/subsys/win32k/freetype/ahangles.c new file mode 100644 index 00000000000..2f759edd5c9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahangles.c @@ -0,0 +1,137 @@ +/***************************************************************************/ +/* */ +/* ahangles.h */ +/* */ +/* A routine used to compute vector angles with limited accuracy */ +/* and very high speed (body). */ +/* */ +/* Copyright 2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahangles.h" + +#else + +#include + +#endif + + + /* 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 + }; + + + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/ahangles.h b/reactos/subsys/win32k/freetype/ahangles.h new file mode 100644 index 00000000000..4eb36bf4d21 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahangles.h @@ -0,0 +1,63 @@ +/***************************************************************************/ +/* */ +/* ahangles.h */ +/* */ +/* A routine used to compute vector angles with limited accuracy */ +/* and very high speed (specification). */ +/* */ +/* Copyright 2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + +#include + + + /* 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]; + + + LOCAL_DEF + AH_Angle ah_angle( FT_Vector* v ); + + +#endif /* AHANGLES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ahglobal.c b/reactos/subsys/win32k/freetype/ahglobal.c new file mode 100644 index 00000000000..892ca861748 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahglobal.c @@ -0,0 +1,402 @@ +/***************************************************************************/ +/* */ +/* ahglobal.c */ +/* */ +/* Routines used to compute global metrics automatically (body). */ +/* */ +/* Copyright 2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahglobal.h" +#include "ahglyph.h" + +#else + +#include +#include + +#endif + + +#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 > 1; 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 = 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_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 = ( 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; + } + + + LOCAL_FUNC + FT_Error ah_hinter_compute_globals( AH_Hinter* hinter ) + { + return ah_hinter_compute_widths( hinter ) || + ah_hinter_compute_blues ( hinter ); + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ahglobal.h b/reactos/subsys/win32k/freetype/ahglobal.h new file mode 100644 index 00000000000..79e73586f98 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahglobal.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ahglobal.h */ +/* */ +/* Routines used to compute global metrics automatically */ +/* (specification). */ +/* */ +/* Copyright 2000 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 + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + +#include /* for LOCAL_DEF/LOCAL_FUNC */ + + +#define AH_IS_TOP_BLUE( b ) ( (b) == ah_blue_capital_top || \ + (b) == ah_blue_small_top ) + + + /* compute global metrics automatically */ + LOCAL_DEF + FT_Error ah_hinter_compute_globals( AH_Hinter* hinter ); + + +#endif /* AHGLOBAL_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ahglyph.c b/reactos/subsys/win32k/freetype/ahglyph.c new file mode 100644 index 00000000000..348ee8e32d5 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahglyph.c @@ -0,0 +1,1299 @@ +/***************************************************************************/ +/* */ +/* ahglyph.c */ +/* */ +/* Routines used to load and analyze a given glyph before hinting */ +/* (body). */ +/* */ +/* Copyright 2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahglyph.h" +#include "ahangles.h" +#include "ahglobal.h" + +#else + +#include +#include +#include + +#endif + + +#include + + +#define xxxAH_DEBUG_GLYPH + + + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_new */ + /* */ + /* */ + /* Creates a new and empty AH_Outline object. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_done */ + /* */ + /* */ + /* Destroys a given AH_Outline object. */ + /* */ + LOCAL_FUNC + 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_save */ + /* */ + /* */ + /* Saves the content of a given AH_Outline object into a face's glyph */ + /* slot. */ + /* */ + LOCAL_FUNC + void ah_outline_save( AH_Outline* outline, + AH_Loader* gloader ) + { + AH_Point* point = outline->points; + AH_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 < 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_load */ + /* */ + /* */ + /* Loads an unscaled outline from a glyph slot into an AH_Outline */ + /* object. */ + /* */ + LOCAL_FUNC + FT_Error ah_outline_load( AH_Outline* outline, + FT_Face face ) + { + FT_Memory memory = outline->memory; + FT_Error error = FT_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 FT_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, realloc the points, segments & edges arrays if needed */ + if ( num_points > outline->max_points ) + { + FT_Int news = ( num_points + 7 ) & -8; + FT_Int max = outline->max_points; + + + if ( REALLOC_ARRAY( outline->points, max, news, AH_Point ) || + REALLOC_ARRAY( outline->horz_edges, max, news, AH_Edge ) || + REALLOC_ARRAY( outline->horz_segments, max, news, AH_Segment ) ) + goto Exit; + + /* readjust some pointers */ + outline->vert_edges = outline->horz_edges + ( news >> 1 ); + outline->vert_segments = outline->horz_segments + ( news >> 1 ); + 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; + + /* Compute the vertical and horizontal major directions; this is */ + /* currently done by inspecting the `ft_outline_reverse_fill' flag. */ + /* However, some fonts have improper glyphs, and it'd be a good idea */ + /* to be able to re-compute these values on the fly. */ + outline->vert_major_dir = ah_dir_up; + outline->horz_major_dir = ah_dir_left; + + if ( source->flags & ft_outline_reverse_fill ) + { + 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; + + { + /* do one thing at a time -- it is easier to understand, and */ + /* the code is clearer */ + AH_Point* point = points; + AH_Point* limit = point + 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 < 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 < 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 < limit; point++ ) + { + point->prev = prev; + if ( point < end ) + { + point->next = point + 1; + prev = point; + } + else + { + point->next = first; + contour_index++; + if ( point + 1 < limit ) + { + end = points + source->contours[contour_index]; + first = point + 1; + prev = end; + } + } + } + } + + /* set-up the contours array */ + { + AH_Point** contour = outline->contours; + AH_Point** limit = contour + outline->num_contours; + short* end = source->contours; + short index = 0; + + + for ( ; contour < limit; contour++, end++ ) + { + contour[0] = points + index; + index = end[0] + 1; + } + } + + /* compute directions of in & out vectors */ + { + for ( point = points; 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; + } + + + LOCAL_FUNC + void ah_setup_uv( AH_Outline* outline, + AH_UV source ) + { + AH_Point* point = outline->points; + AH_Point* limit = point + outline->num_points; + + + for ( ; 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; + } + } + + + LOCAL_FUNC + 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; + + if ( point == max_point ) + max_point = 0; + + if ( point == min_point ) + min_point = 0; + } + + 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* limit = point + outline->num_points; + + AH_Point* min_point = 0; + AH_Point* max_point = 0; + FT_Pos min_pos = 32000; + FT_Pos max_pos = -32000; + + + /* compute minimum and maximum points */ + for ( ; 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 ); + } + } + + + LOCAL_FUNC + void ah_outline_link_segments( AH_Outline* outline ) + { + AH_Segment* segments; + AH_Segment* limit; + int dimension; + + + ah_setup_uv( outline, ah_uv_fyx ); + + segments = outline->horz_segments; + 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 < 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 < 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 = ( seg1->dir == outline->horz_major_dir || + seg1->dir == outline->vert_major_dir ); + is_pos = 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 < 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; + limit = segments + outline->num_vsegments; + } + } + + +#ifdef AH_DEBUG_GLYPH + + /* A function used to dump the array of linked segments */ + void ah_dump_segments( AH_Outline* outline ) + { + AH_Segment* segments; + AH_Segment* limit; + AH_Point* points; + FT_Int dimension; + + + points = outline->points; + segments = outline->horz_segments; + 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 < 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; + limit = segments + outline->num_vsegments; + } + } + +#endif /* AH_DEBUG_GLYPH */ + + + 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 = 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 = 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_straight == 0 && is_round ) + 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_detect_features */ + /* */ + /* */ + /* Performs feature detection on a given AH_Outline object. */ + /* */ + LOCAL_FUNC + void ah_outline_detect_features( AH_Outline* outline ) + { + ah_outline_compute_segments( outline ); + ah_outline_link_segments ( outline ); + ah_outline_compute_edges ( outline ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_compute_blue_edges */ + /* */ + /* */ + /* Computes the `blue edges' in a given outline (i.e. those that must */ + /* be snapped to a blue zone edge (top or bottom). */ + /* */ + LOCAL_FUNC + void ah_outline_compute_blue_edges( AH_Outline* outline, + AH_Face_Globals* face_globals ) + { + AH_Edge* edge = outline->horz_edges; + AH_Edge* limit = edge + outline->num_hedges; + AH_Globals* globals = &face_globals->design; + FT_Fixed y_scale = outline->y_scale; + + + /* compute for each horizontal edge, which blue zone is closer */ + for ( ; 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 = AH_IS_TOP_BLUE( blue ); + FT_Bool is_major_dir = edge->dir == outline->horz_major_dir; + + + /* 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 = 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_scale_blue_edges */ + /* */ + /* */ + /* 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'). */ + /* */ + LOCAL_FUNC + void ah_outline_scale_blue_edges( AH_Outline* outline, + AH_Face_Globals* globals ) + { + AH_Edge* edge = outline->horz_edges; + AH_Edge* limit = edge + outline->num_hedges; + FT_Int delta; + + + delta = globals->scaled.blue_refs - globals->design.blue_refs; + + for ( ; edge < limit; edge++ ) + { + if ( edge->blue_edge ) + edge->blue_edge += delta; + } + } + + +#ifdef AH_DEBUG_GLYPH + + void ah_dump_edges( AH_Outline* outline ) + { + AH_Edge* edges; + AH_Edge* limit; + AH_Segment* segments; + FT_Int dimension; + + + edges = outline->horz_edges; + 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 < 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; + limit = edges + outline->num_vedges; + segments = outline->vert_segments; + } + } + +#endif /* AH_DEBUG_GLYPH */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ahglyph.h b/reactos/subsys/win32k/freetype/ahglyph.h new file mode 100644 index 00000000000..66fd5e31551 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahglyph.h @@ -0,0 +1,93 @@ +/***************************************************************************/ +/* */ +/* ahglyph.h */ +/* */ +/* Routines used to load and analyze a given glyph before hinting */ +/* (specification). */ +/* */ +/* Copyright 2000 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 + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + + 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; + + + LOCAL_DEF + void ah_setup_uv( AH_Outline* outline, + AH_UV source ); + + + /* AH_Outline functions - they should be typically called in this order */ + + LOCAL_DEF + FT_Error ah_outline_new( FT_Memory memory, + AH_Outline** aoutline ); + + LOCAL_DEF + FT_Error ah_outline_load( AH_Outline* outline, + FT_Face face ); + + LOCAL_DEF + void ah_outline_compute_segments( AH_Outline* outline ); + + LOCAL_DEF + void ah_outline_link_segments( AH_Outline* outline ); + + LOCAL_DEF + void ah_outline_detect_features( AH_Outline* outline ); + + LOCAL_DEF + void ah_outline_compute_blue_edges( AH_Outline* outline, + AH_Face_Globals* globals ); + + LOCAL_DEF + void ah_outline_scale_blue_edges( AH_Outline* outline, + AH_Face_Globals* globals ); + + LOCAL_DEF + void ah_outline_save( AH_Outline* outline, AH_Loader* loader ); + + LOCAL_DEF + void ah_outline_done( AH_Outline* outline ); + + +#endif /* AHGLYPH_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ahhint.c b/reactos/subsys/win32k/freetype/ahhint.c new file mode 100644 index 00000000000..f50f8839de4 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahhint.c @@ -0,0 +1,1398 @@ +/***************************************************************************/ +/* */ +/* ahhint.c */ +/* */ +/* Glyph hinter (body). */ +/* */ +/* Copyright 2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahhint.h" +#include "ahglyph.h" +#include "ahangles.h" + +#else + +#include +#include +#include + +#endif + +#include + + +#define FACE_GLOBALS( face ) ((AH_Face_Globals*)(face)->autohint.data) + +#define AH_USE_IUP + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** Hinting routines ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + static int disable_horz_edges = 0; + static int disable_vert_edges = 0; + + + /* 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* before = 0; + AH_Edge* after = 0; + AH_Edge* anchor = 0; + int has_serifs = 0; + + + if ( disable_vert_edges && !dimension ) + goto Next_Dimension; + + if ( 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.. */ + before = 0; + after = 0; + 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; + } + } + + + LOCAL_FUNC + void ah_hinter_hint_edges( AH_Hinter* hinter, + int no_horz_edges, + int no_vert_edges ) + { + disable_horz_edges = no_horz_edges; + 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; + AH_Edge* before; + AH_Edge* after; + + + before = 0; + after = 0; + + 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; + AH_Edge* before; + AH_Edge* after; + + + before = 0; + after = 0; + + 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++ ) + { + FT_Pos 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_Edge* edges; + AH_Edge* edge_limit; + 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 */ + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + 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 */ + + + LOCAL_FUNC + 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 */ + 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_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_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 */ + 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_Fixed x_scale = face->size->metrics.x_scale; + FT_Fixed y_scale = face->size->metrics.y_scale; + FT_Glyph_Metrics metrics; /* temporary metrics */ + FT_Error error; + AH_Outline* outline = hinter->glyph; + AH_Loader* gloader = hinter->loader; + FT_Bool no_horz_hints = + ( load_flags & AH_HINT_NO_HORZ_EDGES ) != 0; + FT_Bool no_vert_hints = + ( load_flags & AH_HINT_NO_VERT_EDGES ) != 0; + + + /* load the glyph */ + error = FT_Load_Glyph( face, glyph_index, load_flags ); + if ( error ) + goto Exit; + + /* save current glyph metrics */ + metrics = slot->metrics; + + switch ( slot->format ) + { + case ft_glyph_format_outline: + /* first of all, 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_width, new_width; + FT_Pos old_advance, new_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_width = edge2->opos - edge1->opos; + new_width = edge2->pos - edge1->pos; + + old_advance = hinter->pp2.x; + old_lsb = edge1->opos; + new_lsb = edge1->pos; + + new_advance = old_advance + + ( new_width + new_lsb - old_width - old_lsb ); + + 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, start_contour; + FT_SubGlyph* subglyph; + + + start_point = gloader->base.outline.n_points; + start_contour = gloader->base.outline.n_contours; + + /* 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 = FT_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 = num_new_points; + + FT_Outline_Translate( &dummy, x, y ); + } + } + } + break; + + default: + /* we don't support other formats (yet?) */ + error = FT_Err_Unimplemented_Feature; + } + + Hint_Metrics: + if ( depth == 0 ) + { + FT_BBox bbox; + + + /* 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->loader ); + error = ah_loader_copy_points( slot->loader, gloader ); + if ( error ) + goto Exit; + + slot->outline = slot->loader->base.outline; + slot->format = ft_glyph_format_outline; + } + + Exit: + return error; + } + + + /* load and hint a given glyph */ + 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 ); + + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE; + + ah_loader_rewind( hinter->loader ); + + error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); + + Exit: + return error; + } + + + /* retrieve a face's autohint globals for client applications */ + 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; + } + + + void ah_hinter_done_global_hints( AH_Hinter* hinter, + void* global_hints ) + { + FT_Memory memory = hinter->memory; + + + FREE( global_hints ); + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ahhint.h b/reactos/subsys/win32k/freetype/ahhint.h new file mode 100644 index 00000000000..bb297fb80f1 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahhint.h @@ -0,0 +1,72 @@ +/***************************************************************************/ +/* */ +/* ahhint.h */ +/* */ +/* Glyph hinter (declaration). */ +/* */ +/* Copyright 2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ahglobal.h" + +#else + +#include + +#endif + + +#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_Error ah_hinter_new( FT_Library library, + AH_Hinter** ahinter ); + + /* Load a hinted glyph in the hinter */ + 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 */ + void ah_hinter_done( AH_Hinter* hinter ); + + LOCAL_DEF + void ah_hinter_done_face_globals( AH_Face_Globals* globals ); + + void ah_hinter_get_global_hints( AH_Hinter* hinter, + FT_Face face, + void** global_hints, + long* global_len ); + + void ah_hinter_done_global_hints( AH_Hinter* hinter, + void* global_hints ); + + +#endif /* AHHINT_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ahloader.h b/reactos/subsys/win32k/freetype/ahloader.h new file mode 100644 index 00000000000..4a8563c0aab --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahloader.h @@ -0,0 +1,124 @@ +/***************************************************************************/ +/* */ +/* ahloader.h */ +/* */ +/* Glyph loader for the auto-hinting module (declaration only). */ +/* */ +/* Copyright 2000 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 + + +#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 */ + }; + + + LOCAL_DEF + FT_Error AH_GlyphLoader_New( FT_Memory memory, + AH_GlyphLoader** aloader ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Create_Extra( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Done( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Reset( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Rewind( AH_GlyphLoader* loader ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Check_Points( AH_GlyphLoader* loader, + FT_UInt n_points, + FT_UInt n_contours ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Check_Subglyphs( AH_GlyphLoader* loader, + FT_UInt n_subs ); + + LOCAL_DEF + void AH_GlyphLoader_Prepare( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Add( AH_GlyphLoader* loader ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Copy_Points( AH_GlyphLoader* target, + FT_GlyphLoader* source ); + +#else /* _STANDALONE */ + +#include + + #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_ */ + +#endif /* AHLOADER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ahmodule.c b/reactos/subsys/win32k/freetype/ahmodule.c new file mode 100644 index 00000000000..85755681ee7 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahmodule.c @@ -0,0 +1,127 @@ +/***************************************************************************/ +/* */ +/* ahmodule.c */ +/* */ +/* Auto-hinting module implementation (declaration). */ +/* */ +/* Copyright 2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ahhint.h" + +#else + +#include + +#endif + + + typedef struct FT_AutoHinterRec_ + { + FT_ModuleRec root; + AH_Hinter* hinter; + + } FT_AutoHinterRec; + + + static + FT_Error ft_autohinter_init( FT_AutoHinter module ) + { + return ah_hinter_new( module->root.library, &module->hinter ); + } + + + static + void ft_autohinter_done( FT_AutoHinter module ) + { + ah_hinter_done( module->hinter ); + } + + + static + 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 ); + } + + + static + 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) ); + } + + + static + 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 ); + } + + + static + void ft_autohinter_done_globals( FT_AutoHinter module, + void* global_hints ) + { + ah_hinter_done_global_hints( module->hinter, global_hints ); + } + + + static + const FT_AutoHinter_Interface autohinter_interface = + { + ft_autohinter_reset, + ft_autohinter_load, + ft_autohinter_get_globals, + ft_autohinter_done_globals + }; + + + 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/reactos/subsys/win32k/freetype/ahmodule.h b/reactos/subsys/win32k/freetype/ahmodule.h new file mode 100644 index 00000000000..28b07538bcf --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahmodule.h @@ -0,0 +1,32 @@ +/***************************************************************************/ +/* */ +/* ahmodule.h */ +/* */ +/* Auto-hinting module (declaration). */ +/* */ +/* Copyright 2000 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 + + FT_EXPORT_VAR( const FT_Module_Class ) autohint_module_class; + +#endif /* AHMODULE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ahoptim.c b/reactos/subsys/win32k/freetype/ahoptim.c new file mode 100644 index 00000000000..d1d684132b9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahoptim.c @@ -0,0 +1,889 @@ +/***************************************************************************/ +/* */ +/* ahoptim.c */ +/* */ +/* FreeType auto hinting outline optimization (body). */ +/* */ +/* Copyright 2000 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 /* for ALLOC_ARRAY() and FREE() */ + + +#ifdef FT_FLAT_COMPILE + +#include "ahoptim.h" + +#else + +#include + +#endif + + + /* 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 +#include +#include + +#define FLOAT( x ) ( (float)( (x) / 64.0 ) ) + + static + void optim_log( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); +/* vprintf( fmt, ap ); FIXME */ + 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/reactos/subsys/win32k/freetype/ahoptim.h b/reactos/subsys/win32k/freetype/ahoptim.h new file mode 100644 index 00000000000..a1f52bf68ff --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahoptim.h @@ -0,0 +1,136 @@ +/***************************************************************************/ +/* */ +/* ahoptim.h */ +/* */ +/* FreeType auto hinting outline optimization (declaration). */ +/* */ +/* Copyright 2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + + /* 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 ); + + +#endif /* AHOPTIM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ahtypes.h b/reactos/subsys/win32k/freetype/ahtypes.h new file mode 100644 index 00000000000..3372ea9af6a --- /dev/null +++ b/reactos/subsys/win32k/freetype/ahtypes.h @@ -0,0 +1,492 @@ +/***************************************************************************/ +/* */ +/* ahtypes.h */ +/* */ +/* General types and definitions for the auto-hint module */ +/* (specification only). */ +/* */ +/* Copyright 2000 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 /* for freetype.h + LOCAL_DEF etc. */ + + +#ifdef FT_FLAT_COMPILE + +#include "ahloader.h" + +#else + +#include + +#endif + + +#define xxAH_DEBUG + + +#ifdef AH_DEBUG + +#include + +#define AH_LOG( x ) printf##x + +#else + +#define AH_LOG( x ) do ; while ( 0 ) /* nothing */ + +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** 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; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Point */ + /* */ + /* */ + /* A structure used to model an outline point to the AH_Outline type. */ + /* */ + /* */ + /* 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 */ + }; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Segment */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Edge */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Globals */ + /* */ + /* */ + /* Holds the global metrics for a given font face (be it in design */ + /* units or scaled pixel values). */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Face_Globals */ + /* */ + /* */ + /* Holds the complete global metrics for a given font face (i.e., the */ + /* design units version + a scaled version + the current scales */ + /* used). */ + /* */ + /* */ + /* 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; + + } AH_Hinter; + + +#endif /* AHTYPES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/autohint.c b/reactos/subsys/win32k/freetype/autohint.c new file mode 100644 index 00000000000..75ef2ecd930 --- /dev/null +++ b/reactos/subsys/win32k/freetype/autohint.c @@ -0,0 +1,45 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* autohint.c */ +/* */ +/* Automatic Hinting wrapper (body only). */ +/* */ +/* Copyright 2000 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 + +#ifdef FT_FLAT_COMPILE + +#include "ahangles.c" +#include "ahglyph.c" +#include "ahglobal.c" +#include "ahhint.c" +#include "ahmodule.c" + +#else + +#include +#include +#include +#include +#include + +#endif + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/builds/ansi/ansi.mk b/reactos/subsys/win32k/freetype/builds/ansi/ansi.mk new file mode 100644 index 00000000000..d326f839e56 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/ansi/ansi.mk @@ -0,0 +1,134 @@ +# +# FreeType 2 configuration rules for a `normal' ANSI compiler +# + + +# Copyright 1996-2000 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 TOP + TOP := . +endif + +DELETE := rm -f +SEP := / +HOSTSEP := $(SEP) +BUILD := $(TOP)/builds/ansi +PLATFORM := ansi + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f $TOP/Makefile setup [options] +# make -f $TOP/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_std + distclean_freetype: distclean_freetype_std + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $@ + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/detect.mk b/reactos/subsys/win32k/freetype/builds/detect.mk new file mode 100644 index 00000000000..d34904a37fd --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/detect.mk @@ -0,0 +1,130 @@ +# +# FreeType 2 host platform detection rules +# + + +# Copyright 1996-2000 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 sub-Makefile is in charge of detecting the current platform. It sets +# the following variables: +# +# BUILD The configuration and system-specific directory. Usually +# `freetype/builds/$(PLATFORM)' but can be different for +# custom builds of the library. +# +# The following variables must be defined in system specific `detect.mk' +# files: +# +# PLATFORM The detected platform. This will default to `ansi' if +# auto-detection fails. +# CONFIG_FILE The configuration sub-makefile to use. This usually depends +# on the compiler defined in the `CC' environment variable. +# DELETE The shell command used to remove a given file. +# COPY The shell command used to copy one file. +# SEP The platform-specific directory separator. +# CC The compiler to use. +# +# You need to set the following variable(s) before calling it: +# +# TOP The top-most directory in the FreeType library source +# hierarchy. If not defined, it will default to `.'. + +# If TOP is not defined, default it to `.' +# +ifndef TOP + TOP := . +endif + +# Set auto-detection default to `ansi' resp. UNIX-like operating systems. +# Note that we delay the evaluation of $(BUILD_CONFIG_), $(BUILD), and +# $(CONFIG_RULES). +# +PLATFORM := ansi +DELETE := $(RM) +COPY := cp +SEP := / + +BUILD_CONFIG_ = $(TOP)$(SEP)builds$(SEP) +BUILD = $(BUILD_CONFIG_)$(PLATFORM) +CONFIG_RULES = $(BUILD)$(SEP)$(CONFIG_FILE) + +# We define the BACKSLASH variable to hold a single back-slash character. +# This is needed because a line like +# +# SEP := \ +# +# does not work with GNU Make (the backslash is interpreted as a line +# continuation). While a line like +# +# SEP := \\ +# +# really defines $(SEP) as `\' on Unix, and `\\' on Dos and Windows! +# +BACKSLASH := $(strip \ ) + +# Now, include all detection rule files found in the `builds/' +# directories. Note that the calling order of the various `detect.mk' files +# isn't predictable. +# +include $(wildcard $(BUILD_CONFIG_)*/detect.mk) + +# In case no detection rule file was successful, use the default. +# +ifndef CONFIG_FILE + CONFIG_FILE := ansi.mk + setup: std_setup +endif + +# The following targets are equivalent, with the exception that they use +# a slightly different syntax for the `echo' command. +# +# std_setup: defined for most (i.e. Unix-like) platforms +# dos_setup: defined for Dos-ish platforms like Dos, Windows & OS/2 +# +.PHONY: std_setup dos_setup + +std_setup: + @echo "" + @echo "FreeType build system -- automatic system detection" + @echo "" + @echo "The following settings are used:" + @echo "" + @echo " platform $(PLATFORM)" + @echo " compiler $(CC)" + @echo " configuration directory $(BUILD)" + @echo " configuration rules $(CONFIG_RULES)" + @echo "" + @echo "If this does not correspond to your system or settings please remove the file" + @echo "\`$(CONFIG_MK)' from this directory then read the INSTALL file for help." + @echo "" + @echo "Otherwise, simply type \`make' again to build the library." + @echo "" + @$(COPY) $(CONFIG_RULES) $(CONFIG_MK) + +dos_setup: + @echo ÿ + @echo FreeType build system -- automatic system detection + @echo ÿ + @echo The following settings are used: + @echo ÿ + @echo ÿÿplatformÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$(PLATFORM) + @echo ÿÿcompilerÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$(CC) + @echo ÿÿconfiguration directoryÿÿÿÿÿÿ$(BUILD) + @echo ÿÿconfiguration rulesÿÿÿÿÿÿÿÿÿÿ$(CONFIG_RULES) + @echo ÿ + @echo If this does not correspond to your system or settings please remove the file + @echo '$(CONFIG_MK)' from this directory then read the INSTALL file for help. + @echo ÿ + @echo Otherwise, simply type 'make' again to build the library. + @echo ÿ + @$(COPY) $(subst /,\,$(CONFIG_RULES) $(CONFIG_MK)) > nul + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/dos/detect.mk b/reactos/subsys/win32k/freetype/builds/dos/detect.mk new file mode 100644 index 00000000000..f8c17069f5a --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/dos/detect.mk @@ -0,0 +1,87 @@ +# +# FreeType 2 configuration file to detect a DOS host platform. +# + + +# Copyright 1996-2000 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. + + +# We test for the COMSPEC environment variable, then run the `ver' +# command-line program to see if its output contains the word `Dos'. +# +# If this is true, we are running a Dos-ish platform (or an emulation). +# +ifeq ($(PLATFORM),ansi) + + ifdef COMSPEC + + is_dos := $(findstring Dos,$(shell ver)) + + # We try to recognize a Dos session under OS/2. The `ver' command + # returns `Operating System/2 ...' there, so `is_dos' should be empty. + # + # To recognize a Dos session under OS/2, we check COMSPEC for the + # substring `MDOS\COMMAND' + # + ifeq ($(is_dos),) + is_dos := $(findstring MDOS\COMMAND,$(COMSPEC)) + endif + + ifneq ($(is_dos),) + + PLATFORM := dos + DELETE := del + COPY := copy + + # Use DJGPP (i.e. gcc) by default. + # + CONFIG_FILE := dos-gcc.mk + SEP := / + ifndef CC + CC := gcc + endif + + # additionally, we provide hooks for various other compilers + # + ifneq ($(findstring turboc,$(MAKECMDGOALS)),) # Turbo C + CONFIG_FILE := dos-tcc.mk + SEP := $(BACKSLASH) + CC := tcc + .PHONY: turboc + endif + + ifneq ($(findstring watcom,$(MAKECMDGOALS)),) # Watcom C/C++ + CONFIG_FILE := dos-wat.mk + SEP := $(BACKSLASH) + CC := wcc386 + .PHONY: watcom + endif + + ifneq ($(findstring borlandc16,$(MAKECMDGOALS)),) # Borland C/C++ 16-bit + CONFIG_FILE := dos-bcc.mk + SEP := $(BACKSLASH) + CC := bcc + .PHONY: borlandc16 + endif + + ifneq ($(findstring borlandc,$(MAKECMDGOALS)),) # Borland C/C++ 32-bit + CONFIG_FILE := dos-bcc.mk + SEP := $(BACKSLASH) + CC := bcc32 + .PHONY: borlandc + endif + + setup: dos_setup + + endif # test Dos + endif # test COMSPEC +endif # test PLATFORM + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/dos/dos-gcc.mk b/reactos/subsys/win32k/freetype/builds/dos/dos-gcc.mk new file mode 100644 index 00000000000..b9f55a21b7c --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/dos/dos-gcc.mk @@ -0,0 +1,134 @@ +# +# FreeType 2 configuration rules for the DJGPP compiler +# + + +# Copyright 1996-2000 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 TOP + TOP := . +endif + +DELETE := rm -f +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/dos +PLATFORM := dos + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g -O6 -Wall +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := -ansi -pedantic + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like: + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $@ + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/freetype.mk b/reactos/subsys/win32k/freetype/builds/freetype.mk new file mode 100644 index 00000000000..172678f8ff3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/freetype.mk @@ -0,0 +1,279 @@ +# +# FreeType 2 library sub-Makefile +# + + +# Copyright 1996-2000 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. + + +# DO NOT INVOKE THIS MAKEFILE DIRECTLY! IT IS MEANT TO BE INCLUDED BY +# OTHER MAKEFILES. + + +# The following variables (set by other Makefile components, in the +# environment, or on the command line) are used: +# +# BUILD The architecture dependent directory, +# e.g. `$(TOP)/builds/unix'. +# +# OBJ_DIR The directory in which object files are created. +# +# LIB_DIR The directory in which the library is created. +# +# INCLUDES A list of directories to be included additionally. +# Usually empty. +# +# CFLAGS Compilation flags. This overrides the default settings +# in the platform-specific configuration files. +# +# FTSYS_SRC If set, its value is used as the name of a replacement +# file for `src/base/ftsystem.c'. +# +# FTDEBUG_SRC If set, its value is used as the name of a replacement +# file for `src/base/ftdebug.c'. [For a normal build, this +# file does nothing.] +# +# FT_MODULE_LIST The file which contains the list of modules for the +# current build. Usually, this is automatically created by +# `modules.mk'. +# +# BASE_OBJ_S +# BASE_OBJ_M A list of base objects (for single object and multiple +# object builds, respectively). Set up in +# `src/base/rules.mk'. +# +# BASE_EXT_OBJ A list of base extension objects. Set up in +# `src/base/rules.mk'. +# +# DRV_OBJ_S +# DRV_OBJ_M A list of driver objects (for single object and multiple +# object builds, respectively). Set up cumulatively in +# `src//rules.mk'. +# +# CLEAN +# DISTCLEAN The sub-makefiles can append additional stuff to these two +# variables which is to be removed for the `clean' resp. +# `distclean' target. +# +# TOP, SEP, +# LIBRARY, CC, +# A, I, O, T Check `config.mk' for details. + + +# The targets `objects' and `library' are defined at the end of this +# Makefile after all other rules have been included. +# +.PHONY: single objects library + +# default target -- build single objects and library +# +single: objects library + +# `multi' target -- build multiple objects and library +# +multi: objects library + + +# The FreeType source directory, usually `./src'. +# +SRC := $(TOP)$(SEP)src + + +# The directory where the base layer components are placed, usually +# `./src/base'. +# +BASE_DIR := $(SRC)$(SEP)base + + +# A few short-cuts in order to avoid typing $(SEP) all the time for the +# directory separator. +# +# For example: $(SRC_) equals to `./src/' where `.' is $(TOP). +# +# +SRC_ := $(SRC)$(SEP) +BASE_ := $(BASE_DIR)$(SEP) +OBJ_ := $(OBJ_DIR)$(SEP) +LIB_ := $(LIB_DIR)$(SEP) +PUBLIC_ := $(TOP)$(SEP)include$(SEP)freetype$(SEP) +INTERNAL_ := $(PUBLIC_)internal$(SEP) +CONFIG_ := $(PUBLIC_)config$(SEP) + + +# The final name of the library file. +# +FT_LIBRARY := $(LIB_)$(LIBRARY).$A + + +# include paths +# +# IMPORTANT NOTE: The architecture-dependent directory must ALWAYS be placed +# in front of the include list. Porters are then able to +# put their own version of some of the FreeType components +# in the `freetype/builds/' directory, as these +# files will override the default sources. +# +INCLUDES := $(BUILD) $(TOP)$(SEP)include $(SRC) + +INCLUDE_FLAGS = $(INCLUDES:%=$I%) + + +# C flags used for the compilation of an object file. This must include at +# least the paths for the `base' and `builds/' directories; +# debug/optimization/warning flags + ansi compliance if needed. +# +FT_CFLAGS = $(CFLAGS) $(INCLUDE_FLAGS) +FT_CC = $(CC) $(FT_CFLAGS) +FT_COMPILE = $(CC) $(ANSIFLAGS) $(FT_CFLAGS) + + +# Include the `modules' rules file. +# +include $(TOP)/builds/modules.mk + + +# Initialize the list of objects. +# +OBJECTS_LIST := + + +# Define $(PUBLIC_H) as the list of all public header files located in +# `$(TOP)/include/freetype'. $(BASE_H) and $(CONFIG_H) are defined +# similarly. +# +# This is used to simplify the dependency rules -- if one of these files +# changes, the whole library is recompiled. +# +PUBLIC_H := $(wildcard $(PUBLIC_)*.h) +BASE_H := $(wildcard $(INTERNAL_)*.h) +CONFIG_H := $(wildcard $(CONFIG_)*.h) + +FREETYPE_H := $(PUBLIC_H) $(BASE_H) $(CONFIG_H) + + +# ftsystem component +# +ifndef FTSYS_SRC + FTSYS_SRC = $(BASE_)ftsystem.c +endif + +FTSYS_OBJ = $(OBJ_)ftsystem.$O + +OBJECTS_LIST += $(FTSYS_OBJ) + +$(FTSYS_OBJ): $(FTSYS_SRC) $(FREETYPE_H) + $(FT_COMPILE) $T$@ $< + + +# ftdebug component +# +ifndef FTDEBUG_SRC + FTDEBUG_SRC = $(BASE_)ftdebug.c +endif + +FTDEBUG_OBJ = $(OBJ_)ftdebug.$O + +OBJECTS_LIST += $(FTDEBUG_OBJ) + +$(FTDEBUG_OBJ): $(FTDEBUG_SRC) $(FREETYPE_H) + $(FT_COMPILE) $T$@ $< + + +# Include all rule files from FreeType components. +# +include $(wildcard $(SRC)/*/rules.mk) + + +# ftinit component +# +# The C source `ftinit.c' contains the FreeType initialization routines. +# It is able to automatically register one or more drivers when the API +# function FT_Init_FreeType() is called. +# +# The set of initial drivers is determined by the driver Makefiles +# includes above. Each driver Makefile updates the FTINIT_xxx lists +# which contain additional include paths and macros used to compile the +# single `ftinit.c' source. +# +FTINIT_SRC := $(BASE_)ftinit.c +FTINIT_OBJ := $(OBJ_)ftinit.$O + +OBJECTS_LIST += $(FTINIT_OBJ) + +$(FTINIT_OBJ): $(FTINIT_SRC) $(FREETYPE_H) $(FT_MODULE_LIST) + $(FT_COMPILE) $T$@ $< + + +# All FreeType library objects +# +# By default, we include the base layer extensions. These could be +# omitted on builds which do not want them. +# +OBJ_M = $(BASE_OBJ_M) $(BASE_EXT_OBJ) $(DRV_OBJS_M) +OBJ_S = $(BASE_OBJ_S) $(BASE_EXT_OBJ) $(DRV_OBJS_S) + + +# The target `multi' on the Make command line indicates that we want to +# compile each source file independently. +# +# Otherwise, each module/driver is compiled in a single object file through +# source file inclusion (see `src/base/ftbase.c' or +# `src/truetype/truetype.c' for examples). +# +BASE_OBJECTS := $(OBJECTS_LIST) + +ifneq ($(findstring multi,$(MAKECMDGOALS)),) + OBJECTS_LIST += $(OBJ_M) +else + OBJECTS_LIST += $(OBJ_S) +endif + +objects: $(OBJECTS_LIST) + +library: $(FT_LIBRARY) + +.c.$O: + $(FT_COMPILE) $T$@ $< + + +# Standard cleaning and distclean rules. These are not accepted +# on all systems though. +# +clean_freetype_std: + -$(DELETE) $(BASE_OBJECTS) $(OBJ_M) $(OBJ_S) $(CLEAN) + +distclean_freetype_std: clean_freetype_std + -$(DELETE) $(FT_LIBRARY) + -$(DELETE) *.orig *~ core *.core $(DISTCLEAN) + +# The Dos command shell does not support very long list of arguments, so +# we are stuck with wildcards. +# +clean_freetype_dos: + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(OBJ_))*.$O $(CLEAN) 2> nul + +distclean_freetype_dos: clean_freetype_dos + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_LIBRARY)) $(DISTCLEAN) 2> nul + +# Remove configuration file (used for distclean). +# +remove_config_mk: + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(CONFIG_MK)) + + +# The `config.mk' file must define `clean_freetype' and +# `distclean_freetype'. Implementations may use to relay these to either +# the `std' or `dos' versions from above, or simply provide their own +# implementation. +# +clean: clean_freetype +distclean: distclean_freetype remove_config_mk + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/mac/ftlib.prj b/reactos/subsys/win32k/freetype/builds/mac/ftlib.prj new file mode 100644 index 0000000000000000000000000000000000000000..d624c2502ff104ae5014f36690ca32123c42def5 GIT binary patch literal 603 zcmd_mI}QO+6vpv$$9TWrG$^SQ647f^LZu@zrXZ3VH*A1bY(irb5~U4@MX2?@F`req z#r^+gZgq~M^;$#%BC08}S0aa&h<(SujZ{e8~>w@uH`AiYCF^a%~q7c@d&(J1{yWAq!1`&Qn2g07)Sx{IdhA)2PAXolXP mS^9|P=rfw9Z)kyjphfzHmV8^@d}X?hR_Gq;?FGjg + +DISCLAIMER: this subdirectory is *not* being maintained by the +FreeType team, but by Just van Rossum. It's being released under +the same terms as FreeType (see LICENSE.TXT). diff --git a/reactos/subsys/win32k/freetype/builds/modules.mk b/reactos/subsys/win32k/freetype/builds/modules.mk new file mode 100644 index 00000000000..110ee8128b8 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/modules.mk @@ -0,0 +1,75 @@ +# +# FreeType 2 modules sub-Makefile +# + +# Copyright 1996-2000 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. + + +# DO NOT INVOKE THIS MAKEFILE DIRECTLY! IT IS MEANT TO BE INCLUDED BY +# OTHER MAKEFILES. + + +# This file is in charge of handling the generation of the modules list +# file. + +.PHONY: make_module_list clean_module_list remake_module_list + +# MODULE_LIST, as its name suggests, indicates where the modules list +# resides. For now, it is in `include/freetype/config/ftmodule.h'. +# +ifndef FT_MODULE_LIST + FT_MODULE_LIST := $(TOP)$(SEP)include$(SEP)freetype$(SEP)config$(SEP)ftmodule.h +endif + +# To build the modules list, we invoke the `make_module_list' target. +# +# This rule is commented out by default since FreeType comes already with +# a ftmodule.h file. +# +#$(FT_MODULE_LIST): make_module_list + +# Before the modules list file can be generated, we must remove the file in +# order to `clean' the list. +# +clean_module_list: + @-$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_MODULE_LIST)) + @-echo Regenerating the modules list in $(FT_MODULE_LIST)... + +make_module_list: clean_module_list + @echo done. + + +# Trailing spaces are protected with a `#' sign to avoid accidental +# removing. +# +ifneq ($(findstring $(PLATFORM),dos win32 win16 os2),) + OPEN_MODULE := @echo # + CLOSE_MODULE := >> $(subst $(SEP),$(HOSTSEP),$(FT_MODULE_LIST)) +else + OPEN_MODULE := @echo " + CLOSE_MODULE := " >> $(FT_MODULE_LIST) +endif + +# $(OPEN_DRIVER) & $(CLOSE_DRIVER) are used to specify a given font driver +# in the `module.mk' rules file. +# +OPEN_DRIVER := $(OPEN_MODULE)FT_USE_MODULE( +CLOSE_DRIVER := )$(CLOSE_MODULE) + +ECHO_DRIVER := @echo "* module: # +ECHO_DRIVER_DESC := ( +ECHO_DRIVER_DONE := )" + +# Each `module.mk' in the `src' sub-dirs is used to add one rule to the +# target `make_module_list'. +# +include $(wildcard $(TOP)/src/*/module.mk) + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/os2/detect.mk b/reactos/subsys/win32k/freetype/builds/os2/detect.mk new file mode 100644 index 00000000000..ed0f1249321 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/os2/detect.mk @@ -0,0 +1,62 @@ +# +# FreeType 2 configuration file to detect an OS/2 host platform. +# + + +# Copyright 1996-2000 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. + + +ifeq ($(PLATFORM),ansi) + + ifdef OS2_SHELL + + PLATFORM := os2 + COPY := copy + DELETE := del + + CONFIG_FILE := os2-gcc.mk # gcc-emx by default + SEP := / + + # additionally, we provide hooks for various other compilers + # + ifneq ($(findstring visualage,$(MAKECMDGOALS)),) # Visual Age C++ + CONFIG_FILE := os2-icc.mk + SEP := $(BACKSLASH) + CC := icc + .PHONY: visualage + endif + + ifneq ($(findstring watcom,$(MAKECMDGOALS)),) # Watcom C/C++ + CONFIG_FILE := os2-wat.mk + SEP := $(BACKSLASH) + CC := wcc386 + .PHONY: watcom + endif + + ifneq ($(findstring borlandc,$(MAKECMDGOALS)),) # Borland C++ 32-bit + CONFIG_FILE := os2-bcc.mk + SEP := $(BACKSLASH) + CC := bcc32 + .PHONY: borlandc + endif + + ifneq ($(findstring devel,$(MAKECMDGOALS)),) # development target + CONFIG_FILE := os2-dev.mk + CC := gcc + SEP := / + devel: setup + endif + + setup: dos_setup + + endif # test OS2_SHELL +endif # test PLATFORM + +#EOF diff --git a/reactos/subsys/win32k/freetype/builds/os2/os2-dev.mk b/reactos/subsys/win32k/freetype/builds/os2/os2-dev.mk new file mode 100644 index 00000000000..93939d20044 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/os2/os2-dev.mk @@ -0,0 +1,137 @@ +# +# FreeType 2 configuration rules for OS/2 + gcc +# +# Development version without optimizations. +# + + +# Copyright 1996-2000 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 TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/os2 +PLATFORM := os2 +CC := gcc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g -O0 -Wall +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := -ansi -pedantic + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_LIBRARY)) 2> nul + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/os2/os2-gcc.mk b/reactos/subsys/win32k/freetype/builds/os2/os2-gcc.mk new file mode 100644 index 00000000000..14992e64a97 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/os2/os2-gcc.mk @@ -0,0 +1,135 @@ +# +# FreeType 2 configuration rules for OS/2 + gcc +# + + +# Copyright 1996-2000 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 TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/os2 +PLATFORM := os2 +CC := gcc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g -O6 -Wall +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := -ansi -pedantic + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_LIBRARY)) 2> nul + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/unix/aclocal.m4 b/reactos/subsys/win32k/freetype/builds/unix/aclocal.m4 new file mode 100644 index 00000000000..47abe430644 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/aclocal.m4 @@ -0,0 +1,430 @@ +## libtool.m4 - Configure libtool for the target system. -*-Shell-script-*- +## Copyright (C) 1996-1999 Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 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. + +# 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 &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/reactos/subsys/win32k/freetype/builds/unix/config.guess b/reactos/subsys/win32k/freetype/builds/unix/config.guess new file mode 100644 index 00000000000..499496436cd --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/config.guess @@ -0,0 +1,1273 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. + +version='2000-06-13' + +# 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 . +# Please send patches to . +# +# 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). +# + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of this system. + +Operation modes: + -h, --help print this help, then exit + -V, --version print version number, then exit" + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case "$1" in + --version | --vers* | -V ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + exec >&2 + echo "$me: invalid option $1" + echo "$help" + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +# 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 + *:NetBSD:*:*) + # Netbsd (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # Determine the machine/vendor (is the vendor relevant). + case "${UNAME_MACHINE}" in + amiga) machine=m68k-cbm ;; + arm32) machine=arm-unknown ;; + atari*) machine=m68k-atari ;; + sun3*) machine=m68k-sun ;; + mac68k) machine=m68k-apple ;; + macppc) machine=powerpc-apple ;; + hp3[0-9][05]) machine=m68k-hp ;; + ibmrt|romp-ibm) machine=romp-ibm ;; + *) machine=${UNAME_MACHINE}-unknown ;; + esac + # The Operating System including object format. + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + 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 <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 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: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 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + 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*: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*:OpenBSD:*:*) + echo m68k-unknown-openbsd${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 ;; + 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 +#include /* for printf() prototype */ + 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 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${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 + + 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 BSD 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 + + #define _HPUX_SOURCE + #include + #include + + 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 + (CCOPTS= $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 + 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} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + 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 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | i?86:BSD/OS:*:* | *:Ascend\ Embedded/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:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`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 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + *:Linux:*:*) + + # 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 + *ia64) + echo "${UNAME_MACHINE}-unknown-linux" + exit 0 + ;; + i?86linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 + ;; + elf_i?86) + echo "${UNAME_MACHINE}-pc-linux" + 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 + ;; + elf32arm*) + echo "${UNAME_MACHINE}-unknown-linux-gnuoldld" + exit 0 + ;; + armelf_linux*) + echo "${UNAME_MACHINE}-unknown-linux-gnu" + exit 0 + ;; + m68klinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + elf32ppc | elf32ppclinux) + # Determine Lib Version + cat >$dummy.c < +#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 + ;; + shelf_linux) + echo "${UNAME_MACHINE}-unknown-linux-gnu" + exit 0 + ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + cat <$dummy.s + .data + \$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main + main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + LIBC="" + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 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 < /* for printf() prototype */ + 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 + elif test "${UNAME_MACHINE}" = "s390"; then + echo s390-ibm-linux && exit 0 + 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 < +#ifdef __cplusplus +#include /* for printf() prototype */ + 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.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i?86:*:5:7*) + # Fixed at (any) Pentium or better + UNAME_MACHINE=i586 + if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then + echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i?86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /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 ;; + i?86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # 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 + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # 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 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_MACHINE=pc + fi + echo `uname -p`-${UNAME_MACHINE}-nto-qnx + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-W:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${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 < +# include +#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 + 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 + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess version = $version + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "version='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/reactos/subsys/win32k/freetype/builds/unix/config.sub b/reactos/subsys/win32k/freetype/builds/unix/config.sub new file mode 100644 index 00000000000..6e5f1a80c0b --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/config.sub @@ -0,0 +1,1319 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. + +version='2000-06-20' + +# 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. + +# Please send patches to . +# +# 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. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -V, --version print version number, then exit" + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case "$1" in + --version | --vers* | -V ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + exec >&2 + echo "$me: invalid option $1" + echo "$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +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 + nto-qnx* | 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 | -axis) + 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 + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +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 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ + | 580 | i960 | h8300 \ + | x86 | ppcbe | mipsbe | mipsle | shbe | shle | armbe | armle \ + | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ + | hppa64 \ + | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ + | alphaev6[78] \ + | we32k | ns16k | clipper | i370 | sh | sh[34] \ + | powerpc | powerpcle \ + | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \ + | mips64orion | mips64orionel | mipstx39 | mipstx39el \ + | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ + | mips64vr5000 | miprs64vr5000el | mcore \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \ + | thumb | d10v | fr30 | avr) + basic_machine=$basic_machine-unknown + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65 | pj | pjl) + ;; + + # 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[234567]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. + # FIXME: clean up the formatting here. + vax-* | tahoe-* | i[234567]86-* | i860-* | ia64-* | 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-* \ + | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* | armbe-* | armle-* \ + | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ + | hppa2.0n-* | hppa64-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ + | alphaev6[78]-* \ + | 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-* | mcore-* \ + | f301-* | armv*-* | s390-* | sv1-* | t3e-* \ + | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ + | thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* \ + | bs2000-* | tic54x-* | c54x-*) + ;; + # 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 + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + 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 + ;; +# 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[0-9]* | *MiNT | *MiNT[0-9]*) + 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 + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) + basic_machine=i386-unknown + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + 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 + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + 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 | athlon) + 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-* | athlon-*) + 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 + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=t3e-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + 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 + ;; + sh3 | sh4) + base_machine=sh-unknown + ;; + 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* | -darwin* | -opened* \ + | -openstep* | -oskit*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i[34567]86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -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|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -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 + ;; + -nsk) + os=-nsk + ;; + # 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*-rebel) + 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* | -opened*) + 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 +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "version='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/reactos/subsys/win32k/freetype/builds/unix/configure b/reactos/subsys/win32k/freetype/builds/unix/configure new file mode 100644 index 00000000000..78e572b7375 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/configure @@ -0,0 +1,2514 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-shared[=PKGS] build shared libraries [default=yes]" +ac_help="$ac_help + --enable-static[=PKGS] build static libraries [default=yes]" +ac_help="$ac_help + --enable-fast-install[=PKGS] optimize for fast installation [default=yes]" +ac_help="$ac_help + --with-gnu-ld assume the C compiler uses GNU ld [default=no]" +ac_help="$ac_help + --disable-libtool-lock avoid locking (might break parallel builds)" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +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' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# 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 +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=ftconfig.in + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +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 + + + + + +version_info='6:0:0' + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:588: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:609: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:627: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:653: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:683: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:734: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:766: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 777 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:782: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:808: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:813: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:841: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:873: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:894: \"$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 + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:911: \"$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 + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:928: \"$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 + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + + +if test "x$CC" = xgcc; then + XX_CFLAGS="-Wall" + XX_ANSIFLAGS="-pedantic -ansi" +else + case "$host" in + *-dec-osf*) + XX_CFLAGS="-std1 -O2 -g3" + XX_ANSIFLAGS= + ;; + *) + XX_CFLAGS= + XX_ANSIFLAGS= + ;; + esac +fi + + + +# Extract the first word of "rm", so it can be a program name with args. +set dummy rm; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:974: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RMF'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RMF"; then + ac_cv_prog_RMF="$RMF" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RMF="rm -f" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +RMF="$ac_cv_prog_RMF" +if test -n "$RMF"; then + echo "$ac_t""$RMF" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "rmdir", so it can be a program name with args. +set dummy rmdir; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1003: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RMDIR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RMDIR"; then + ac_cv_prog_RMDIR="$RMDIR" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RMDIR="rmdir" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +RMDIR="$ac_cv_prog_RMDIR" +if test -n "$RMDIR"; then + echo "$ac_t""$RMDIR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1041: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1095: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1108: \"$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* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1175: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +for ac_hdr in fcntl.h unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1202: 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 +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1212: \"$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 "configure: 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 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:1240: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:1294: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking size of int""... $ac_c" 1>&6 +echo "configure:1315: checking size of int" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(int)); + exit(0); +} +EOF +if { (eval echo configure:1334: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_int=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_int=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_int" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1354: checking size of long" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(long)); + exit(0); +} +EOF +if { (eval echo configure:1373: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_long=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_long=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_long" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1398: 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 +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1408: \"$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 "configure: 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 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1437: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* 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 $ac_func(); + +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_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1465: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:1490: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext < +#include +#include + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:1638: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + +if test "$ac_cv_func_mmap_fixed_mapped" != yes; then + FTSYS_SRC='$(BASE_)ftsystem.c' +else + FTSYS_SRC='$(BUILD)/ftsystem.c' +fi + + +for ac_func in memcpy memmove +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1670: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* 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 $ac_func(); + +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_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1698: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + 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 +else + enable_shared=yes +fi + +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + 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 +else + enable_static=yes +fi + +# Check whether --enable-fast-install or --disable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval="$enable_fast_install" + 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 +else + enable_fast_install=yes +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1795: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$ac_cv_prog_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 "configure:1834: 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 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 + echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 +echo "configure:1858: checking for GNU ld" >&5 +else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 +echo "configure:1861: checking for non-GNU ld" >&5 +fi +if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + 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 +fi + +LD="$ac_cv_path_LD" +if test -n "$LD"; then + echo "$ac_t""$LD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; } +echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6 +echo "configure:1896: checking if the linker ($LD) is GNU ld" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6 + + +echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6 +echo "configure:1912: checking for BSD-compatible nm" >&5 +if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + 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 +fi + +NM="$ac_cv_path_NM" +echo "$ac_t""$NM" 1>&6 + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:1948: checking whether ln -s works" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +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" + + +# Check whether --enable-libtool-lock or --disable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval="$enable_libtool_lock" + : +fi + +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 1997 "configure"' > conftest.$ac_ext + if { (eval echo configure:1998: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; 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" + echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6 +echo "configure:2019: checking whether the C compiler needs -belf" >&5 +if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + lt_cv_cc_needs_belf=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + lt_cv_cc_needs_belf=no +fi +rm -f conftest* +fi + +echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6 + 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 + ;; + + +esac + + +# Save cache, so that ltconfig can load it +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 + + +# 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 \ +|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; } + +# Reload cache, that may have been modified by ltconfig +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + + +# 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' + +# Redirect the config.log output again, so that the ltconfig log is not +# clobbered by the next message. +exec 5>>./config.log + + +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 + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "unix.mk:unix.in ftconfig.h:ftconfig.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@version_info@%$version_info%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@XX_CFLAGS@%$XX_CFLAGS%g +s%@XX_ANSIFLAGS@%$XX_ANSIFLAGS%g +s%@RMF@%$RMF%g +s%@RMDIR@%$RMDIR%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@FTSYS_SRC@%$FTSYS_SRC%g +s%@RANLIB@%$RANLIB%g +s%@LN_S@%$LN_S%g +s%@LIBTOOL@%$LIBTOOL%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + + diff --git a/reactos/subsys/win32k/freetype/builds/unix/configure.in b/reactos/subsys/win32k/freetype/builds/unix/configure.in new file mode 100644 index 00000000000..cfaf1b7a47b --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/configure.in @@ -0,0 +1,74 @@ +dnl This file is part of the FreeType project. +dnl +dnl Process this file with autoconf to produce a configure script. +dnl + +AC_INIT(ftconfig.in) + +dnl Configuration file -- stay in 8.3 limit +AC_CONFIG_HEADER(ftconfig.h:ftconfig.in) + +version_info='6:0:0' +AC_SUBST(version_info) + +dnl checks for system type +AC_CANONICAL_SYSTEM + +dnl checks for programs +AC_PROG_CC +AC_PROG_CPP + +dnl get Compiler flags right. +if test "x$CC" = xgcc; then + XX_CFLAGS="-Wall" + XX_ANSIFLAGS="-pedantic -ansi" +else + case "$host" in + *-dec-osf*) + XX_CFLAGS="-std1 -O2 -g3" + XX_ANSIFLAGS= + ;; + *) + XX_CFLAGS= + XX_ANSIFLAGS= + ;; + esac +fi +AC_SUBST(XX_CFLAGS) +AC_SUBST(XX_ANSIFLAGS) + +AC_CHECK_PROG(RMF, rm, rm -f) +AC_CHECK_PROG(RMDIR, rmdir, rmdir) +AC_PROG_INSTALL + +dnl checks for header files +AC_HEADER_STDC +AC_CHECK_HEADERS(fcntl.h unistd.h) + +dnl checks for typedefs, structures, and compiler characteristics +AC_C_CONST +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) + +dnl Checks for library functions. + +dnl Here we check whether we can use our mmap file component. +AC_FUNC_MMAP +if test "$ac_cv_func_mmap_fixed_mapped" != yes; then + FTSYS_SRC='$(BASE_)ftsystem.c' +else + FTSYS_SRC='$(BUILD)/ftsystem.c' +fi +AC_SUBST(FTSYS_SRC) + +AC_CHECK_FUNCS(memcpy memmove) + +AM_PROG_LIBTOOL + +dnl create the Unix-specific sub-Makefile `builds/unix/unix.mk' that will be +dnl used by the build system +dnl +AC_OUTPUT(unix.mk:unix.in) + + +dnl end of configure.in diff --git a/reactos/subsys/win32k/freetype/builds/unix/detect.mk b/reactos/subsys/win32k/freetype/builds/unix/detect.mk new file mode 100644 index 00000000000..dec1baa7966 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/detect.mk @@ -0,0 +1,59 @@ +# +# FreeType 2 configuration file to detect a UNIX host platform. +# + + +# Copyright 1996-2000 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. + + +ifeq ($(PLATFORM),ansi) + + has_init := $(strip $(wildcard /sbin/init)) + ifneq ($(has_init),) + + PLATFORM := unix + COPY := cp + DELETE := rm -f + + # If a Unix platform is detected, the configure script is called and + # `unix.mk' is created. + # + # Arguments to `configure' should be in the CFG variable. Example: + # + # make CFG="--prefix=/usr --disable-static" + # + # If you need to set CFLAGS or LDFLAGS, do it here also. + # + # Feel free to add support for other platform specific compilers in this + # directory (e.g. solaris.mk + changes here to detect the platform). + # + CONFIG_FILE := unix.mk + setup: unix.mk + unix: setup + + # If `devel' is the requested target, use `-g -O0' as the default value + # for CFLAGS if CFLAGS isn't set. + # + ifneq ($(findstring devel,$(MAKECMDGOALS)),) + ifndef CFLAGS + USE_CFLAGS := CFLAGS="-g -O0" + endif + devel: setup + endif + + setup: std_setup + + unix.mk: builds/unix/unix.in + cd builds/unix; $(USE_CFLAGS) ./configure $(CFG) + + endif # test Unix +endif # test PLATFORM + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/unix/ftconfig.in b/reactos/subsys/win32k/freetype/builds/unix/ftconfig.in new file mode 100644 index 00000000000..a24b6793899 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/ftconfig.in @@ -0,0 +1,172 @@ +/***************************************************************************/ +/* */ +/* ftconfig.in */ +/* */ +/* UNIX-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-2000 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/', and */ + /* contains system-specific files that are always included first when */ + /* building the library. */ + /* */ + /*************************************************************************/ + + +#ifndef FTCONFIG_H +#define FTCONFIG_H + + + /* Include the header file containing all developer build options */ +#include + + + /*************************************************************************/ + /* */ + /* 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/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + +#define HAVE_UNISTD_H 0 +#define HAVE_FCNTL_H 0 + +#define SIZEOF_INT 2 +#define SIZEOF_LONG 2 + + +#define FT_SIZEOF_INT SIZEOF_INT +#define FT_SIZEOF_LONG SIZEOF_LONG + + + /* 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 + +#if FT_SIZEOF_LONG == 8 + + /* FT_LONG64 must be defined if a 64-bit type is available */ +#define FT_LONG64 +#define FT_INT64 long + +#else + + + /*************************************************************************/ + /* */ + /* Many compilers provide the non-ANSI `long long' 64-bit type. You can */ + /* activate it by defining the FTCALC_USE_LONG_LONG macro in */ + /* `ftoption.h'. */ + /* */ + /* Note that this will produce many -ansi warnings during library */ + /* compilation, and that in many cases, the generated code will be */ + /* neither smaller nor faster! */ + /* */ +#ifdef FTCALC_USE_LONG_LONG + +#define FT_LONG64 +#define FT_INT64 long long + +#endif /* FTCALC_USE_LONG_LONG */ +#endif /* FT_SIZEOF_LONG == 8 */ + + +#ifdef FT_MAKE_OPTION_SINGLE_OBJECT +#define LOCAL_DEF static +#define LOCAL_FUNC static +#else +#define LOCAL_DEF extern +#define LOCAL_FUNC /* nothing */ +#endif + +#ifdef FT_MAKE_OPTION_SINGLE_LIBRARY_OBJECT +#define BASE_DEF( x ) static x +#define BASE_FUNC( x ) static x +#else +#define BASE_DEF( x ) extern x +#define BASE_FUNC( x ) extern x +#endif + +#ifndef FT_EXPORT_DEF +#define FT_EXPORT_DEF( x ) extern x +#endif + +#ifndef FT_EXPORT_FUNC +#define FT_EXPORT_FUNC( x ) extern x +#endif + +#ifndef FT_EXPORT_VAR +#define FT_EXPORT_VAR( x ) extern x +#endif + +#endif /* FTCONFIG_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/builds/unix/ftsystem.c b/reactos/subsys/win32k/freetype/builds/unix/ftsystem.c new file mode 100644 index 00000000000..9ecd95c7dce --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/ftsystem.c @@ -0,0 +1,306 @@ +/***************************************************************************/ +/* */ +/* ftsystem.c */ +/* */ +/* Unix-specific FreeType low-level system interface (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include + +#include +#include +#include + + + /* memory-mapping includes and definitions */ +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#ifndef MAP_FILE +#define MAP_FILE 0x00 +#endif + + /*************************************************************************/ + /* */ + /* The prototype for munmap() is not provided on SunOS. This needs to */ + /* have a check added later to see if the GNU C library is being used. */ + /* If so, then this prototype is not needed. */ + /* */ +#if defined( __sun__ ) && !defined( SVR4 ) && !defined( __SVR4 ) + extern int munmap( caddr_t addr, + int len ); +#endif + +#include + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* MEMORY MANAGEMENT INTERFACE */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* ft_alloc */ + /* */ + /* */ + /* The memory allocation function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* size :: The requested size in bytes. */ + /* */ + /* */ + /* block :: The address of newly allocated block. */ + /* */ + static + void* ft_alloc( FT_Memory memory, + long size ) + { + FT_UNUSED( memory ); + + return malloc( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_realloc */ + /* */ + /* */ + /* The memory reallocation function. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The address of the reallocated memory block. */ + /* */ + static + 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_free */ + /* */ + /* */ + /* The memory release function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* block :: The address of block in memory to be freed. */ + /* */ + static + 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 ) + + + /*************************************************************************/ + /* */ + /* */ + /* ft_close_stream */ + /* */ + /* */ + /* The function to close a stream. */ + /* */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + static + void ft_close_stream( FT_Stream stream ) + { + munmap ( stream->descriptor.pointer, stream->size ); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Stream */ + /* */ + /* */ + /* Creates a new stream object. */ + /* */ + /* */ + /* filepathname :: The name of the stream (usually a file) to be */ + /* opened. */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Stream( const char* filepathname, + FT_Stream stream ) + { + int file; + struct stat stat_buf; + + + if ( !stream ) + return FT_Err_Invalid_Stream_Handle; + + /* open the file */ + file = open( filepathname, O_RDONLY ); + if ( file < 0 ) + { + FT_ERROR(( "FT_New_Stream:" )); + FT_ERROR(( " could not open `%s'\n", filepathname )); + return FT_Err_Cannot_Open_Resource; + } + + if ( fstat( file, &stat_buf ) < 0 ) + { + FT_ERROR(( "FT_New_Stream:" )); + FT_ERROR(( " could not `fstat' file `%s'\n", filepathname )); + goto Fail_Map; + } + + stream->size = stat_buf.st_size; + stream->pos = 0; + stream->base = mmap( NULL, + stream->size, + PROT_READ, + MAP_FILE | MAP_PRIVATE, + file, + 0 ); + + if ( (long)stream->base == -1 ) + { + FT_ERROR(( "FT_New_Stream:" )); + FT_ERROR(( " could not `mmap' file `%s'\n", filepathname )); + goto Fail_Map; + } + + close( file ); + + stream->descriptor.pointer = stream->base; + stream->pathname.pointer = (char*)filepathname; + + stream->close = ft_close_stream; + stream->read = 0; + + FT_TRACE1(( "FT_New_Stream:" )); + FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", + filepathname, stream->size )); + + return FT_Err_Ok; + + Fail_Map: + close( file ); + + stream->base = NULL; + stream->size = 0; + stream->pos = 0; + + return FT_Err_Cannot_Open_Stream; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory */ + /* */ + /* */ + /* Creates a new memory object. */ + /* */ + /* */ + /* A pointer to the new memory object. 0 in case of error. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/builds/unix/install-sh b/reactos/subsys/win32k/freetype/builds/unix/install-sh new file mode 100644 index 00000000000..ebc66913e94 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/install-sh @@ -0,0 +1,250 @@ +#! /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=: + 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/reactos/subsys/win32k/freetype/builds/unix/ltconfig b/reactos/subsys/win32k/freetype/builds/unix/ltconfig new file mode 100644 index 00000000000..a01334f9212 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/ltconfig @@ -0,0 +1,3078 @@ +#! /bin/sh + +# ltconfig - Create a system-specific libtool. +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 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 </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 "X${CDPATH+set}" = Xset; 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.4 +TIMESTAMP=" (1.385.2.196 1999/12/07 21:47:57)" +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $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 <&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 "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi +if test "X${LANG+set}" = Xset; 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 "X${COLLECT_NAMES+set}" != Xset; 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 <&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* | osf5*) + # 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* | osf5*) + # 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 &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 <&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 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 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 echo __ELF__ | $CC -E - | grep __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* | sysv5*) + if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <&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= + ;; + *) + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + ;; + 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*) + 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=: + ;; + + osf4* | osf5*) # As osf3* with the addition of the -msym flag + if test "$with_gcc" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${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 -msym -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' + ;; + + sysv5*) + 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= + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + ;; + + 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 -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4.2uw2*) + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts' + hardcode_direct=yes + hardcode_minus_L=no + hardcode_shlibpath_var=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + unixware7*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + *) + 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 <&5 + if { (eval echo $progname:1636: \"$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:1639: 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 < conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c' + + cat <> 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:1691: \"$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 + 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 $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" + export_dynamic_flag_spec=-rdynamic + # 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 + shlibpath_var=LD_LIBRARY_PATH + case "$host_os" in + freebsd2* | freebsd3.[01]* | freebsdelf3.[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 + ;; + 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* | osf5*) + 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 <&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:2212: 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 <&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:2252: 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 < +/* 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. */ +#ifdef __cplusplus +extern "C" +#endif +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:2282: \"$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:2299: 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 <&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:2339: 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 < +/* 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. */ +#ifdef __cplusplus +extern "C" +#endif +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:2369: \"$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:2387: 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 <&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:2452: 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 < +int fnord = 0; +EOF +ac_try="$ac_compile >/dev/null 2>conftest.out" +{ (eval echo $progname:2462: \"$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:2490: 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 < +#endif + +#include + +#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:2544: \"$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:2563: 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 < +#endif + +#include + +#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:2617: \"$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 < "$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. +# Originally by Gordon Matzigkeit , 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 "X\${CDPATH+set}" = Xset; 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 < "$cfgfile" +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +EOF + ;; +esac + +cat <> "$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 "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # Append the ltmain.sh script. + sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1) + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + + 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/reactos/subsys/win32k/freetype/builds/unix/ltmain.sh b/reactos/subsys/win32k/freetype/builds/unix/ltmain.sh new file mode 100644 index 00000000000..ab65054f17a --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/ltmain.sh @@ -0,0 +1,4012 @@ +# 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 , 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 <&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 $srcfile $pic_flag -DPIC" + 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 + + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` + libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` + # Now arrange that obj and lo_libobj become the same file + $show "(cd $xdir && $LN_S $baseobj $libobj)" + if $run eval '(cd $xdir && $LN_S $baseobj $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" + 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 +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #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 +# 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 /* for printf() */ +# #include /* for open(), lseek(), read() */ +# #include /* for O_RDONLY, O_BINARY */ +# #include /* 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&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 </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) in case we are running --disable-static + for obj in $libobjs; do + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` + if test ! -f $xdir/$oldobj; then + $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" + $run eval '(cd $xdir && ${LN_S} $baseobj $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 + xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$libobj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` + $show "(cd $xdir && $LN_S $oldobj $baseobj)" + $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || 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*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $CC -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' + 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 in case 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 + xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$oldobj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` + obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` + $show "(cd $xdir && ${LN_S} $obj $baseobj)" + $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || 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 + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # 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. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $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/reactos/subsys/win32k/freetype/builds/unix/mkinstalldirs b/reactos/subsys/win32k/freetype/builds/unix/mkinstalldirs new file mode 100644 index 00000000000..cdb20218042 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.1 2001/05/02 12:21:30 jfilby Exp $ + +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" 1>&2 + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/reactos/subsys/win32k/freetype/builds/unix/unix.in b/reactos/subsys/win32k/freetype/builds/unix/unix.in new file mode 100644 index 00000000000..9aeea24a488 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/unix/unix.in @@ -0,0 +1,216 @@ +# +# FreeType 2 configuration rules templates for Unix + configure +# + + +# Copyright 1996-2000 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 TOP + TOP := . +endif + +DELETE := @RMF@ +DELDIR := @RMDIR@ +SEP := / +HOSTSEP := $(SEP) +BUILD := $(TOP)/builds/unix +PLATFORM := unix +CC := @CC@ + +INSTALL := @INSTALL@ +INSTALL_DATA := @INSTALL_DATA@ +MKINSTALLDIRS := $(BUILD)/mkinstalldirs + +LIBTOOL := $(BUILD)/libtool + + +# don't use `:=' here since the path stuff will be included after this file +# +FTSYS_SRC = @FTSYS_SRC@ + +DISTCLEAN += $(BUILD)/config.cache \ + $(BUILD)/config.log \ + $(BUILD)/config.status \ + $(BUILD)/unix.mk \ + $(BUILD)/ftconfig.h \ + $(LIBTOOL) + + +# Standard installation variables. +# +prefix := @prefix@ +exec_prefix := @exec_prefix@ +libdir := @libdir@ +bindir := @bindir@ +includedir := @includedir@ + +version_info := @version_info@ + + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f $TOP/Makefile setup [options] +# make -f $TOP/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := lo +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := la +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +CFLAGS := -c @XX_CFLAGS@ @CFLAGS@ + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := @XX_ANSIFLAGS@ + +# C compiler to use -- we use libtool! +# +# +CCraw := $(CC) +CC := $(LIBTOOL) --mode=compile $(CCraw) + +# Linker flags. +# +LDFLAGS := @LDFLAGS@ + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + + # The cleanup targets. + # + clean_freetype: clean_freetype_unix + distclean_freetype: distclean_freetype_unix + + + # Unix installation and deinstallation targets. + install: $(FT_LIBRARY) + $(MKINSTALLDIRS) $(libdir) \ + $(includedir)/freetype/config \ + $(includedir)/freetype/internal + $(LIBTOOL) --mode=install $(INSTALL) $(FT_LIBRARY) $(libdir) + -for P in $(PUBLIC_H) ; do \ + $(INSTALL_DATA) $$P $(includedir)/freetype ; \ + done + -for P in $(BASE_H) ; do \ + $(INSTALL_DATA) $$P $(includedir)/freetype/internal ; \ + done + -for P in $(CONFIG_H) ; do \ + $(INSTALL_DATA) $$P $(includedir)/freetype/config ; \ + done + + uninstall: + -$(LIBTOOL) --mode=uninstall $(RM) $(libdir)/$(LIBRARY).$A + -$(DELETE) $(includedir)/freetype/config/* + -$(DELDIR) $(includedir)/freetype/config + -$(DELETE) $(includedir)/freetype/internal/* + -$(DELDIR) $(includedir)/freetype/internal + -$(DELETE) $(includedir)/freetype/* + -$(DELDIR) $(includedir)/freetype + + + # Unix cleaning and distclean rules. + # + clean_freetype_unix: + -$(DELETE) $(BASE_OBJECTS) $(OBJ_M) $(OBJ_S) + -$(DELETE) $(subst $O,$(SO),$(BASE_OBJECTS) $(OBJ_M) $(OBJ_S)) \ + $(CLEAN) + + distclean_freetype_unix: clean_freetype_unix + -$(DELETE) $(FT_LIBRARY) + -$(DELETE) $(OBJ_DIR)/.libs/* + -$(DELDIR) $(OBJ_DIR)/.libs + -$(DELETE) *.orig *~ core *.core $(DISTCLEAN) + + + # Librarian to use to build the library + # + FT_LIBRARIAN := $(LIBTOOL) --mode=link $(CCraw) + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + $(FT_LIBRARIAN) -o $@ $(OBJECTS_LIST) \ + -rpath $(libdir) -version-info $(version_info) + +endif + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/win32/detect.mk b/reactos/subsys/win32k/freetype/builds/win32/detect.mk new file mode 100644 index 00000000000..c2bf8ccedfa --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/win32/detect.mk @@ -0,0 +1,90 @@ +# +# FreeType 2 configuration file to detect a Win32 host platform. +# + + +# Copyright 1996-2000 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. + + +ifeq ($(PLATFORM),ansi) + + # Detecting Windows NT is easy, as the OS variable must be defined and + # contains `Windows_NT'. Untested with Windows 2K, but I guess it should + # work... + # + ifeq ($(OS),Windows_NT) + is_windows := 1 + + # We test for the COMSPEC environment variable, then run the `ver' + # command-line program to see if its output contains the word `Windows'. + # + # If this is true, we are running a win32 platform (or an emulation). + # + else + ifdef COMSPEC + is_windows := $(findstring Windows,$(strip $(shell ver))) + endif + endif # test NT + + ifdef is_windows + + PLATFORM := win32 + DELETE := del + COPY := copy + + CONFIG_FILE := w32-gcc.mk # gcc Makefile by default + SEP := / + ifeq ($(firstword $(CC)),cc) + CC := gcc + endif + + # additionally, we provide hooks for various other compilers + # + ifneq ($(findstring visualc,$(MAKECMDGOALS)),) # Visual C/C++ + CONFIG_FILE := w32-vcc.mk + SEP := $(BACKSLASH) + CC := cl + visualc: setup + endif + + ifneq ($(findstring watcom,$(MAKECMDGOALS)),) # Watcom C/C++ + CONFIG_FILE := w32-wat.mk + SEP := $(BACKSLASH) + CC := wcc386 + watcom: setup + endif + + ifneq ($(findstring visualage,$(MAKECMDGOALS)),) # Visual Age C++ + CONFIG_FILE := w32-icc.mk + SEP := $(BACKSLASH) + CC := icc + visualage: setup + endif + + ifneq ($(findstring lcc,$(MAKECMDGOALS)),) # LCC-Win32 + CONFIG_FILE := w32-lcc.mk + SEP := $(BACKSLASH) + CC := lcc + lcc: setup + endif + + ifneq ($(findstring devel,$(MAKECMDGOALS)),) # development target + CONFIG_FILE := w32-dev.mk + CC := gcc + SEP := / + devel: setup + endif + + setup: dos_setup + + endif # test is_windows +endif # test PLATFORM + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/win32/w32-dev.mk b/reactos/subsys/win32k/freetype/builds/win32/w32-dev.mk new file mode 100644 index 00000000000..8eea55af725 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/win32/w32-dev.mk @@ -0,0 +1,140 @@ +# +# FreeType 2 Configuration rules for Win32 + GCC +# +# Development version without optimizations. +# + + +# Copyright 1996-2000 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: This version requires that GNU Make is invoked from the Windows +# Shell (_not_ Cygwin BASH)! +# + +ifndef TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/win32 +PLATFORM := win32 +CC := gcc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g -O0 -Wall -W +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := -ansi -pedantic + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_LIBRARY)) 2> nul + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/win32/w32-gcc.mk b/reactos/subsys/win32k/freetype/builds/win32/w32-gcc.mk new file mode 100644 index 00000000000..3501a7967f9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/win32/w32-gcc.mk @@ -0,0 +1,138 @@ +# +# FreeType 2 Configuration rules for Win32 + GCC +# + + +# Copyright 1996-2000 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: This version requires that GNU Make is invoked from the Windows +# Shell (_not_ Cygwin BASH)! +# + +ifndef TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/win32 +PLATFORM := win32 +CC := gcc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g -O6 -Wall +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := -ansi -pedantic + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_LIBRARY)) 2> nul + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/win32/w32-icc.mk b/reactos/subsys/win32k/freetype/builds/win32/w32-icc.mk new file mode 100644 index 00000000000..504579e6120 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/win32/w32-icc.mk @@ -0,0 +1,122 @@ +# +# FreeType 2 Configuration rules for Win32 + IBM Visual Age C++ +# + + +# Copyright 1996-2000 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. +# + +DELETE := del +SEP := $(strip \ ) +HOSTSEP := $(strip \ ) +BUILD := $(TOP)$(SEP)config$(SEP)win32 +PLATFORM := win32 +CC := icc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := obj +SO := obj + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := lib +SA := lib + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := freetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := /I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := /D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := /Fl + + +# Target flag. +# +T := /Fo + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +ifndef CFLAGS + CFLAGS := /Q- /Gd+ /O2 /G5 /W3 /C +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSI_FLAGS := /Sa + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + lib /nologo /out:$@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/win32/w32-lcc.mk b/reactos/subsys/win32k/freetype/builds/win32/w32-lcc.mk new file mode 100644 index 00000000000..476de14a36f --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/win32/w32-lcc.mk @@ -0,0 +1,130 @@ +# +# FreeType 2 Configuration rules for Win32 + LCC +# + + +# Copyright 1996-2000 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 TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/win32 +PLATFORM := win32 +CC := lcc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := obj +SO := obj + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := lib +SA := lib + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := freetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -Fl + + +# Target flag. +# +T := -Fo + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g2 -O +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + lcclib /out:$(subst $(SEP),\\,$@) \ + $(subst $(SEP),\\,$(OBJECTS_LIST)) + +endif + +# EOF diff --git a/reactos/subsys/win32k/freetype/builds/win32/w32-vcc.mk b/reactos/subsys/win32k/freetype/builds/win32/w32-vcc.mk new file mode 100644 index 00000000000..955f44a8230 --- /dev/null +++ b/reactos/subsys/win32k/freetype/builds/win32/w32-vcc.mk @@ -0,0 +1,129 @@ +# +# FreeType 2 Configuration rules for Win32 + Visual C/C++ +# + + +# Copyright 1996-2000 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 TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/win32 +PLATFORM := win32 +CC := cl + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := obj +SO := obj + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := lib +SA := lib + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := freetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := /I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := /D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := /Fl + + +# Target flag. +# +T := /Fo + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := /nologo /c /Ox /G5 /W3 /WX +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := /Za + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + lib /nologo /out:$@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/reactos/subsys/win32k/freetype/cff.c b/reactos/subsys/win32k/freetype/cff.c new file mode 100644 index 00000000000..0359694979d --- /dev/null +++ b/reactos/subsys/win32k/freetype/cff.c @@ -0,0 +1,42 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* cff.c */ +/* */ +/* FreeType OpenType driver component (body only). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef FT_FLAT_COMPILE + +#include "t2driver.c" /* driver interface */ +#include "t2parse.c" /* token parser */ +#include "t2load.c" /* tables loader */ +#include "t2objs.c" /* object management */ +#include "t2gload.c" /* glyph loader */ + +#else + +#include /* driver interface */ +#include /* token parser */ +#include /* tables loader */ +#include /* object management */ +#include /* glyph loader */ + +#endif + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/cidafm.c b/reactos/subsys/win32k/freetype/cidafm.c new file mode 100644 index 00000000000..b5638836eac --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidafm.c @@ -0,0 +1,293 @@ +/***************************************************************************/ +/* */ +/* cidafm.c */ +/* */ +/* AFM support for CID-keyed fonts (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "cidafm.h" + +#else + +#include + +#endif + + +#include +#include +#include + +#include /* for qsort() */ +#include /* for strcmp() */ +#include /* 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_cidafm + + + LOCAL_FUNC + void CID_Done_AFM( FT_Memory memory, + CID_AFM* afm ) + { + FREE( afm->kern_pairs ); + afm->num_pairs = 0; + } + + +#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 = 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 */ + static + int compare_kern_pairs( const void* a, + const void* b ) + { + CID_Kern_Pair* pair1 = (CID_Kern_Pair*)a; + CID_Kern_Pair* pair2 = (CID_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 */ + LOCAL_FUNC + FT_Error CID_Read_AFM( FT_Face cid_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; + CID_Kern_Pair* pair; + T1_Font* type1 = &((T1_Face)t1_face)->type1; + CID_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 occurrences 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, CID_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; + + 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 ( CID_Kern_Pair ), + compare_kern_pairs ); + + Exit: + if ( error ) + FREE( afm ); + + FORGET_Frame(); + + return error; + } + + + /* find the kerning for a given glyph pair */ + LOCAL_FUNC + void CID_Get_Kerning( CID_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + CID_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/reactos/subsys/win32k/freetype/cidafm.h b/reactos/subsys/win32k/freetype/cidafm.h new file mode 100644 index 00000000000..542604e0ddb --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidafm.h @@ -0,0 +1,78 @@ +/***************************************************************************/ +/* */ +/* cidafm.h */ +/* */ +/* AFM support for CID-keyed fonts (specification). */ +/* */ +/* Copyright 1996-2000 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 CIDAFM_H +#define CIDAFM_H + + +#ifdef FT_FLAT_COMPILE + +#include "cidobjs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct CID_Kern_Pair_ + { + FT_UInt glyph1; + FT_UInt glyph2; + FT_Vector kerning; + + } CID_Kern_Pair; + + typedef struct CID_AFM_ + { + FT_UInt num_pairs; + CID_Kern_Pair* kern_pairs; + + } CID_AFM; + + + LOCAL_DEF + FT_Error CID_Read_AFM( FT_Face cid_face, + FT_Stream stream ); + + LOCAL_DEF + void CID_Done_AFM( FT_Memory memory, + CID_AFM* afm ); + + LOCAL_DEF + void CID_Get_Kerning( CID_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDAFM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/cidgload.c b/reactos/subsys/win32k/freetype/cidgload.c new file mode 100644 index 00000000000..97c9252be2a --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidgload.c @@ -0,0 +1,1558 @@ +/***************************************************************************/ +/* */ +/* cidgload.c */ +/* */ +/* CID-keyed Type1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "cidload.h" +#include "cidgload.h" + +#else + +#include +#include + +#endif + + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /* forward */ + static + FT_Error cid_load_glyph( CID_Decoder* decoder, + FT_UInt glyph_index ); + + + typedef enum CID_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 */ + + } CID_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 */ + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + LOCAL_FUNC + void CID_Init_Builder( CID_Builder* builder, + CID_Face face, + CID_Size size, + CID_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.loader; + + + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; + + FT_GlyphLoader_Rewind( loader ); + } + + if ( size ) + { + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.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; + + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Builder */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + LOCAL_FUNC + void CID_Done_Builder( CID_Builder* builder ) + { + CID_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + LOCAL_FUNC + void CID_Init_Decoder( CID_Decoder* decoder ) + { + MEM_Set( decoder, 0, sizeof ( *decoder ) ); + + decoder->font_matrix.xx = 0x10000L; + decoder->font_matrix.yy = 0x10000L; + } + + + /* check that there is enough space for `count' more points */ + static + FT_Error check_points( CID_Builder* builder, + FT_Int count ) + { + return FT_GlyphLoader_Check_Points( builder->loader, count, 0 ); + } + + + /* add a new point, but do not check space */ + static + void add_point( CID_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; + point->y = y; + *control = 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( CID_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( CID_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return T1_Err_Ok; + } + + error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + + outline->n_contours++; + } + return error; + } + + + /* if a path has been started, add its first on-curve point */ + static + FT_Error start_point( CID_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + FT_Error error; + + + builder->path_begun = 1; + error = add_contour( builder ); + if ( error ) + return error; + } + + return add_point1( builder, x, y ); + } + + + /* close the current contour */ + static + void close_contour( CID_Builder* builder ) + { + FT_Outline* outline = builder->current; + + + /* XXX: 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; + + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + } + + +#if 0 + + + /*************************************************************************/ + /* */ + /* */ + /* lookup_glyph_by_stdcharcode */ + /* */ + /* */ + /* Looks up a given glyph by its StandardEncoding charcode. Used */ + /* to implement the SEAC Type 1 operator. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + static + FT_Int lookup_glyph_by_stdcharcode( CID_Face face, + FT_Int charcode ) + { + FT_Int n; + const FT_String* glyph_name; + PSNames_Interface* psnames = (PSNames_Interface*)face->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 < face->cid.cid_count; n++ ) + { + FT_String* name = (FT_String*)face->type1.glyph_names[n]; + + + if ( name && strcmp( name, glyph_name ) == 0 ) + return n; + } + + return -1; + } + + +#endif /* 0 */ + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_seac */ + /* */ + /* */ + /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error t1operator_seac( CID_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; + + + bchar_index = bchar; + achar_index = achar; + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return T1_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->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->current.subglyphs; + glyph->format = ft_glyph_format_composite; + + loader->current.num_subglyphs = 2; + } + + /* First load `bchar' in builder */ + /* now load the unscaled outline */ + if ( decoder->builder.loader ) + FT_GlyphLoader_Prepare( decoder->builder.loader ); + + error = cid_load_glyph( decoder, bchar_index ); /* load one glyph */ + 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 = cid_load_glyph( decoder, achar_index ); + if ( error ) + return error; + + /* 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 = base->n_points - n_base_points; + dummy.points = base->points + n_base_points; + FT_Outline_Translate( &dummy, adx - asb, ady ); + } + } + + Exit: + return error; + } + + +#define USE_ARGS( n ) do \ + { \ + top -= n; \ + if ( top < decoder->stack ) \ + goto Stack_Underflow; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given CID charstrings program. */ + /* */ + /* */ + /* decoder :: The current CID decoder. */ + /* */ + /* */ + /* charstring_base :: The base of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error CID_Parse_CharStrings( CID_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ) + { + FT_Error error; + CID_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + CID_Builder* builder = &decoder->builder; + FT_Outline* outline; + FT_Pos x, y; + + + /* 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 = T1_Err_Ok; + outline = builder->current; + + x = builder->pos_x; + y = builder->pos_y; + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Int* top = decoder->top; + CID_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(( "CID_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(( "CID_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + break; + + case 255: /* four bytes integer */ + if ( ip + 4 > limit ) + { + FT_ERROR(( "CID_Parse_CharStrings: unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = ( (long)ip[0] << 24 ) | + ( (long)ip[1] << 16 ) | + ( (long)ip[2] << 8 ) | + ip[3]; + ip += 4; + break; + + default: + if ( ip[-1] >= 32 ) + { + if ( ip[-1] < 247 ) + value = (long)ip[-1] - 139; + else + { + if ( ++ip > limit ) + { + FT_ERROR(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + if ( ip[-2] < 251 ) + value = ( (long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108; + else + value = -( ( ( (long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 ); + } + } + else + { + FT_ERROR(( "CID_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(( "CID_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(( "CID_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(( "CID_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(( "CID_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if ( ip[0] != 12 || ip[1] != 17 ) + { + FT_ERROR(( "CID_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; + +#if 0 + + case 14: + case 15: + case 16: + case 17: + case 18: /* multiple masters */ + { + T1_Blend* blend = decoder->blend; + FT_UInt num_points, nn, mm; + FT_Int* delta; + FT_Int* values; + + + if ( !blend ) + { + FT_ERROR(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " unexpected multiple masters operator!\n" )); + goto Syntax_Error; + } + + num_points = top[1] - 13 + ( top[1] == 18 ); + if ( top[0] != num_points * blend->num_designs ) + { + FT_ERROR(( "CID_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 x = values[0]; + + + for ( mm = 1; mm < blend->num_designs; mm++ ) + x += FT_MulFix( *delta++, blend->weight_vector[mm] ); + + *values++ = x; + } + /* note that `top' will be incremented later by calls to `pop' */ + } + break; + +#endif + + default: + Unexpected_OtherSubr: + FT_ERROR(( "CID_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 T1_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 T1_Err_Ok; + + break; + + case op_seac: + /* return immediately after 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 T1_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]; + 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]; + 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]; + break; + + case op_div: + FT_TRACE4(( " div" )); + + if ( top[1] ) + { + *top = top[0] / top[1]; + top++; + } + else + { + FT_ERROR(( "CID_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->subrs->num_subrs ) + { + FT_ERROR(( "CID_Parse_CharStrings: invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "CID_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = decoder->subrs->code[index] + decoder->lenIV; + zone->limit = decoder->subrs->code[index + 1]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "CID_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(( "CID_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(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + + default: + FT_ERROR(( "CID_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 T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + + Memory_Error: + return builder->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. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error CID_Compute_Max_Advance( CID_Face face, + FT_Int* max_advance ) + { + FT_Error error; + CID_Decoder decoder; + FT_Int glyph_index; + + + *max_advance = 0; + + /* Initialize load decoder */ + CID_Init_Decoder( &decoder ); + CID_Init_Builder( &decoder.builder, 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++ ) + { + /* 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 T1_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. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error cid_load_glyph( CID_Decoder* decoder, + FT_UInt glyph_index ) + { + CID_Face 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; + FT_Byte* charstring; + FT_UInt lenIV; + FT_Memory memory = face->root.memory; + + + /* setup subrs */ + decoder->subrs = face->subrs + fd_select; + + /* setup font matrix */ + dict = cid->font_dicts + fd_select; + decoder->font_matrix = dict->font_matrix; + lenIV = dict->private_dict.lenIV; + decoder->lenIV = 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 ) ) + { + cid_decrypt( charstring, glyph_len, 4330 ); + error = CID_Parse_CharStrings( decoder, + charstring + lenIV, + glyph_len - lenIV ); + } + + FREE( charstring ); + } + + Exit: + return error; + } + + + LOCAL_FUNC + FT_Error CID_Load_Glyph( CID_GlyphSlot glyph, + CID_Size size, + FT_Int glyph_index, + FT_Int load_flags ) + { + FT_Error error; + CID_Decoder decoder; + CID_Face face = (CID_Face)glyph->root.face; + FT_Bool hinting; + + + 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 = ( load_flags & FT_LOAD_NO_SCALE ) == 0 && + ( load_flags & FT_LOAD_NO_HINTING ) == 0; + + glyph->root.format = ft_glyph_format_outline; + + { + CID_Init_Decoder( &decoder ); + CID_Init_Builder( &decoder.builder, face, size, glyph ); + + /* set up the decoder */ + decoder.builder.no_recurse = + (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE ); + + error = cid_load_glyph( &decoder, glyph_index ); + + /* save new glyph tables */ + CID_Done_Builder( &decoder.builder ); + } + + /* 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 the left side bearing and the */ + /* advance width */ + if ( load_flags & FT_LOAD_NO_RECURSE ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.builder.advance.x; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.format = ft_glyph_format_outline; + + glyph->root.outline.flags &= ft_outline_owner; + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= ft_outline_high_precision; + + glyph->root.outline.flags |= ft_outline_reverse_fill; + +#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 + + 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 ); + } + + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, &decoder.font_matrix ); + + /* 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/reactos/subsys/win32k/freetype/cidgload.h b/reactos/subsys/win32k/freetype/cidgload.h new file mode 100644 index 00000000000..5f3913d5270 --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidgload.h @@ -0,0 +1,198 @@ +/***************************************************************************/ +/* */ +/* cidgload.h */ +/* */ +/* OpenType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "cidobjs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* 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 CID_Builder_ + { + FT_Memory memory; + CID_Face face; + CID_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; + + } CID_Builder; + + + /* execution context charstring zone */ + + typedef struct CID_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } CID_Decoder_Zone; + + + typedef struct CID_Decoder_ + { + CID_Builder builder; + + FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS]; + FT_Int* top; + + CID_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1]; + CID_Decoder_Zone* zone; + + FT_Matrix font_matrix; + CID_Subrs* subrs; + FT_UInt lenIV; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + } CID_Decoder; + + + LOCAL_DEF + void CID_Init_Builder( CID_Builder* builder, + CID_Face face, + CID_Size size, + CID_GlyphSlot glyph ); + + LOCAL_DEF + void CID_Done_Builder( CID_Builder* builder ); + + + LOCAL_DEF + void CID_Init_Decoder( CID_Decoder* decoder ); + + +#if 0 + + /* Compute the maximum advance width of a font through quick parsing */ + LOCAL_DEF + FT_Error CID_Compute_Max_Advance( CID_Face face, + FT_Int* max_advance ); + +#endif + + /* This function is exported, because it is used by the T1Dump utility */ + LOCAL_DEF + FT_Error CID_Parse_CharStrings( CID_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ); + + LOCAL_DEF + FT_Error CID_Load_Glyph( CID_GlyphSlot glyph, + CID_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDGLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/cidload.c b/reactos/subsys/win32k/freetype/cidload.c new file mode 100644 index 00000000000..1f7c7aea013 --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidload.c @@ -0,0 +1,537 @@ +/***************************************************************************/ +/* */ +/* cidload.c */ +/* */ +/* CID-keyed Type1 font loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "cidload.h" + +#else + +#include + +#endif + + +#include +#include /* 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 */ + LOCAL_FUNC + 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; + } + + + LOCAL_FUNC + void cid_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ) + { + while ( length > 0 ) + { + FT_Byte plain; + + + plain = ( *buffer ^ ( seed >> 8 ) ); + seed = ( *buffer + seed ) * 52845 + 22719; + *buffer++ = plain; + length--; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 1 SYMBOL PARSING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error cid_load_keyword( CID_Face face, + CID_Loader* loader, + const CID_Field_Rec* keyword ) + { + FT_Error error; + CID_Parser* parser = &loader->parser; + FT_Byte* object; + CID_Info* cid = &face->cid; + + + /* if the keyword has a dedicated callback, call it */ + if ( keyword->type == t1_field_callback ) + { + error = keyword->reader( face, parser ); + 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 = T1_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; + } + } + } + + /* 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( parser, keyword, object ); + else + error = CID_Load_Field( parser, keyword, object ); + + Exit: + return error; + } + + + static + FT_Error parse_font_bbox( CID_Face face, + CID_Parser* parser ) + { + FT_Short temp[4]; + FT_BBox* bbox = &face->cid.font_bbox; + + + (void)CID_ToCoordArray( parser, 4, temp ); + bbox->xMin = temp[0]; + bbox->yMin = temp[1]; + bbox->xMax = temp[2]; + bbox->yMax = temp[3]; + + return T1_Err_Ok; /* this is a callback function; */ + /* we must return an error code */ + } + + + static + FT_Error parse_font_matrix( CID_Face face, + CID_Parser* parser ) + { + FT_Matrix* matrix; + CID_FontDict* dict; + FT_Fixed temp[4]; + + + if ( parser->num_dict >= 0 ) + { + dict = face->cid.font_dicts + parser->num_dict; + matrix = &dict->font_matrix; + + (void)CID_ToFixedArray( parser, 4, temp, 3 ); + matrix->xx = temp[0]; + matrix->yx = temp[1]; + matrix->xy = temp[2]; + matrix->yy = temp[3]; + } + + return T1_Err_Ok; /* this is a callback function; */ + /* we must return an error code */ + } + + + static + 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 = T1_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 CID_Field_Rec t1_field_records[] = + { + +#ifdef FT_FLAT_COMPILE + +#include "cidtokens.h" + +#else + +#include + +#endif + + { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 } + }; + + + static + int is_alpha( char c ) + { + return ( isalnum( c ) || + c == '.' || + c == '_' ); + } + + + static + void skip_whitespace( CID_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + + + while ( cur < parser->limit && isspace( *cur ) ) + cur++; + + parser->cursor = cur; + } + + + static + FT_Error parse_dict( CID_Face face, + CID_Loader* loader, + FT_Byte* base, + FT_Long size ) + { + CID_Parser* parser = &loader->parser; + + + parser->cursor = base; + parser->limit = base + size; + parser->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 = cur2 - cur; + if ( len > 0 && len < 22 ) + { + /* now compare the immediate name to the keyword table */ + const CID_Field_Rec* keyword = t1_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->cursor = cur2; + skip_whitespace( parser ); + parser->error = cid_load_keyword( face, loader, keyword ); + if ( parser->error ) + return parser->error; + + cur = parser->cursor; + break; + } + } + keyword++; + } + } + } + } + } + return parser->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_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 */ + 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 ); + } + + + LOCAL_FUNC + 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 ); + if ( error ) + goto Exit; + + error = 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/reactos/subsys/win32k/freetype/cidload.h b/reactos/subsys/win32k/freetype/cidload.h new file mode 100644 index 00000000000..7495da0dc1e --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidload.h @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* cidload.h */ +/* */ +/* CID-keyed Type1 font loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "cidparse.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct CID_Loader_ + { + CID_Parser parser; /* parser used to read the stream */ + FT_Int num_chars; /* number of characters in encoding */ + + } CID_Loader; + + + LOCAL_DEF + FT_Long cid_get_offset( FT_Byte** start, + FT_Byte offsize ); + + LOCAL_DEF + void cid_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ); + + LOCAL_DEF + FT_Error CID_Open_Face( CID_Face face ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/cidobjs.c b/reactos/subsys/win32k/freetype/cidobjs.c new file mode 100644 index 00000000000..a75567b6bfc --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidobjs.c @@ -0,0 +1,380 @@ +/***************************************************************************/ +/* */ +/* cidobjs.c */ +/* */ +/* CID objects manager (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "cidgload.h" +#include "cidload.h" + +#else + +#include +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* 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 */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Face */ + /* */ + /* */ + /* Finalizes a given face object. */ + /* */ + /* */ + /* face :: A pointer to the face object to destroy. */ + /* */ + LOCAL_FUNC + 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Face */ + /* */ + /* */ + /* Initializes a given CID face object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + + 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; + } + + /* 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 = 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->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 = "Regular"; + } + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox = face->cid.font_bbox; + root->units_per_EM = 1000; + root->ascender = (FT_Short)face->cid.font_bbox.yMax; + root->descender = -(FT_Short)face->cid.font_bbox.yMin; + root->height = ( ( 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->max_points = 0; + root->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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Driver */ + /* */ + /* */ + /* Initializes a given CID driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error CID_Init_Driver( CID_Driver driver ) + { + FT_UNUSED( driver ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Driver */ + /* */ + /* */ + /* Finalizes a given CID driver. */ + /* */ + /* */ + /* driver :: A handle to the target CID driver. */ + /* */ + LOCAL_DEF + void CID_Done_Driver( CID_Driver driver ) + { + FT_UNUSED( driver ); + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/cidobjs.h b/reactos/subsys/win32k/freetype/cidobjs.h new file mode 100644 index 00000000000..c28c59be25e --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidobjs.h @@ -0,0 +1,141 @@ +/***************************************************************************/ +/* */ +/* cidobjs.h */ +/* */ +/* CID objects manager (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Driver */ + /* */ + /* */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct CID_DriverRec_* CID_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Size */ + /* */ + /* */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct CID_SizeRec_* CID_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_GlyphSlot */ + /* */ + /* */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct CID_GlyphSlotRec_* CID_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_CharMap */ + /* */ + /* */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* */ + /* 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; + + + LOCAL_DEF + FT_Error CID_Init_Face( FT_Stream stream, + CID_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void CID_Done_Face( CID_Face face ); + + + LOCAL_DEF + FT_Error CID_Init_Driver( CID_Driver driver ); + + LOCAL_DEF + void CID_Done_Driver( CID_Driver driver ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDOBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/cidparse.c b/reactos/subsys/win32k/freetype/cidparse.c new file mode 100644 index 00000000000..33d3d8af3c3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidparse.c @@ -0,0 +1,1024 @@ +/***************************************************************************/ +/* */ +/* cidparse.c */ +/* */ +/* CID-keyed Type1 parser (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "cidparse.h" + +#else + +#include + +#endif + + +#include /* 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 + + +#if 0 + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** IMPLEMENTATION OF CID_TABLE OBJECT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_New_Table */ + /* */ + /* */ + /* Initializes a CID_Table. */ + /* */ + /* */ + /* table :: The address of the target table. */ + /* */ + /* */ + /* count :: The table size, i.e., the maximal number of elements. */ + /* */ + /* memory :: The memory object to be used for all subsequent */ + /* reallocations. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error CID_New_Table( CID_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 = 0xDEADBEEFL; + table->num_elems = 0; + table->block = 0; + table->capacity = 0; + table->cursor = 0; + + Exit: + if ( error ) + FREE( table->elements ); + + return error; + } + + + static + void shift_elements( CID_Table* table, + FT_Byte* old_base ) + { + FT_Long delta = table->block - old_base; + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + if ( delta ) + for ( ; offset < limit; offset++ ) + { + if ( offset[0] ) + offset[0] += delta; + } + } + + + static + FT_Error reallocate_t1_table( CID_Table* table, + FT_Int new_size ) + { + FT_Memory memory = table->memory; + FT_Byte* old_base = table->block; + FT_Error error; + + + /* realloc the base block */ + if ( REALLOC( table->block, table->capacity, new_size ) ) + return error; + + table->capacity = new_size; + + /* shift all offsets when needed */ + if ( old_base ) + shift_elements( table, old_base ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Add_Table */ + /* */ + /* */ + /* Adds an object to a CID_Table, possibly growing its memory block. */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* index :: The index of the object in the table. */ + /* */ + /* object :: The address of the object to copy in the memory. */ + /* */ + /* length :: The length in bytes of the source object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. An error is returned if */ + /* reallocation fails. */ + /* */ + LOCAL_FUNC + FT_Error CID_Add_Table( CID_Table* table, + FT_Int index, + void* object, + FT_Int length ) + { + if ( index < 0 || index > table->max_elems ) + { + FT_ERROR(( "CID_Add_Table: invalid index\n" )); + return T1_Err_Syntax_Error; + } + + /* grow the base block if needed */ + if ( table->cursor + length > table->capacity ) + { + FT_Error error; + FT_Int new_size = table->capacity; + + + while ( new_size < table->cursor + length ) + new_size += 1024; + + error = reallocate_t1_table( table, new_size ); + if ( error ) + return error; + } + + /* 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 T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Table */ + /* */ + /* */ + /* Finalizes a CID_Table (reallocate it to its current cursor). */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* 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. */ + /* */ + LOCAL_FUNC + void CID_Done_Table( CID_Table* table ) + { + FT_Memory memory = table->memory; + FT_Error error; + FT_Byte* old_base; + + + /* should never fail, as rec.cursor <= rec.size */ + old_base = table->block; + if ( !old_base ) + return; + + (void)REALLOC( table->block, table->capacity, table->cursor ); + table->capacity = table->cursor; + + if ( old_base != table->block ) + shift_elements( table, old_base ); + } + + + LOCAL_FUNC + void CID_Release_Table( CID_Table* table ) + { + FT_Memory memory = table->memory; + + + if ( table->init == 0xDEADBEEFL ) + { + FREE( table->block ); + FREE( table->elements ); + FREE( table->lengths ); + table->init = 0; + } + } + +#endif /* 0 */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** INPUT STREAM PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define IS_CID_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' ) +#define IS_CID_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' ) + +#define IS_CID_SPACE( c ) ( IS_CID_WHITESPACE( c ) || IS_CID_LINESPACE( c ) ) + + + LOCAL_FUNC + void CID_Skip_Spaces( CID_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( !IS_CID_SPACE( c ) ) + break; + cur++; + } + + parser->cursor = cur; + } + + + LOCAL_FUNC + void CID_ToToken( CID_Parser* parser, + CID_Token_Rec* 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 */ + CID_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 is any token **********/ + default: + token->start = cur++; + token->type = t1_token_any; + while ( cur < limit && !IS_CID_SPACE( *cur ) ) + cur++; + + token->limit = cur; + } + + if ( !token->limit ) + { + token->start = 0; + token->type = t1_token_none; + } + + parser->cursor = cur; + } + } + + + LOCAL_FUNC + void CID_ToTokenArray( CID_Parser* parser, + CID_Token_Rec* tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ) + { + CID_Token_Rec master; + + + *pnum_tokens = -1; + + CID_ToToken( parser, &master ); + + if ( master.type == t1_token_array ) + { + FT_Byte* old_cursor = parser->cursor; + FT_Byte* old_limit = parser->limit; + CID_Token_Rec* cur = tokens; + CID_Token_Rec* limit = cur + max_tokens; + + + parser->cursor = master.start; + parser->limit = master.limit; + + while ( parser->cursor < parser->limit ) + { + CID_Token_Rec token; + + + CID_ToToken( parser, &token ); + if ( !token.type ) + break; + + if ( cur < limit ) + *cur = token; + + cur++; + } + + *pnum_tokens = 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, 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, read the integer part */ + result = t1_toint( &cur, limit ) << 16; + num = 0; + divider = 1; + + if ( result < 0 ) + { + sign = 1; + result = -result; + } + + 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 + int t1_tobool( FT_Byte** cursor, + FT_Byte* limit ) + { + FT_Byte* cur = *cursor; + FT_Bool result = 0; + + + /* return 1 if we find a "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; + } + + + 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; + } + + + /* Loads a simple field (i.e. non-table) into the current */ + /* list of objects */ + LOCAL_FUNC + FT_Error CID_Load_Field( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ) + { + CID_Token_Rec token; + FT_Byte* cur; + FT_Byte* limit; + FT_UInt count; + FT_UInt index; + FT_Error error; + + + CID_ToToken( parser, &token ); + if ( !token.type ) + goto Fail; + + count = 1; + index = 0; + cur = token.start; + limit = token.limit; + + { + FT_Byte* q = (FT_Byte*)object + 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, 0 ); + 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_Int32*)q = (FT_Int)val; + break; + + default: /* for 64-bit systems */ + *(FT_Long*)q = val; + } + break; + + case t1_field_string: + { + FT_Memory memory = parser->memory; + FT_UInt len = limit-cur; + + + if ( ALLOC( string, len + 1 ) ) + goto Exit; + + MEM_Copy( string, cur, len ); + string[len] = 0; + + *(FT_String**)q = string; + } + break; + + default: + /* an error occurred */ + goto Fail; + } + } + + error = 0; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + +#define T1_MAX_TABLE_ELEMENTS 32 + + + LOCAL_FUNC + FT_Error CID_Load_Field_Table( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ) + { + CID_Token_Rec elements[T1_MAX_TABLE_ELEMENTS]; + CID_Token_Rec* token; + FT_Int num_elements; + FT_Error error = 0; + FT_Byte* old_cursor; + FT_Byte* old_limit; + CID_Field_Rec fieldrec = *(CID_Field_Rec*)field; + + + fieldrec.type = t1_field_integer; + if ( field->type == t1_field_fixed_array ) + fieldrec.type = t1_field_fixed; + + CID_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 */ + if ( field->count_offset ) + *(FT_Byte*)( (FT_Byte*)object + field->count_offset ) = 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; + CID_Load_Field( parser, &fieldrec, object ); + fieldrec.offset += fieldrec.size; + } + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + + LOCAL_FUNC + FT_Long CID_ToInt( CID_Parser* parser ) + { + return t1_toint( &parser->cursor, parser->limit ); + } + + + LOCAL_FUNC + FT_Int CID_ToCoordArray( CID_Parser* parser, + FT_Int max_coords, + FT_Short* coords ) + { + return t1_tocoordarray( &parser->cursor, parser->limit, + max_coords, coords ); + } + + + LOCAL_FUNC + FT_Int CID_ToFixedArray( CID_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 + + /* 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; + } + +#endif /* 0 */ + + + LOCAL_FUNC + FT_Error CID_New_Parser( CID_Parser* parser, + FT_Stream stream, + FT_Memory memory ) + { + 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 ) ); + parser->stream = stream; + parser->memory = memory; + + 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 = FT_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; + + /* fill input buffer */ + buff_len -= 256; + if ( buff_len > 0 ) + MEM_Move( buffer, limit, buff_len ); + + if ( FILE_Read( buffer, 256 + 10 - buff_len ) ) + goto Exit; + + 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 = FILE_Pos() - ( 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->cursor = parser->postscript; + parser->limit = parser->cursor + ps_len; + parser->num_dict = -1; + + Exit: + return error; + } + + + LOCAL_FUNC + void CID_Done_Parser( CID_Parser* parser ) + { + /* always free the private dictionary */ + if ( parser->postscript ) + { + FT_Stream stream = parser->stream; + + + RELEASE_Frame( parser->postscript ); + } + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/cidparse.h b/reactos/subsys/win32k/freetype/cidparse.h new file mode 100644 index 00000000000..7a8211ad305 --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidparse.h @@ -0,0 +1,353 @@ +/***************************************************************************/ +/* */ +/* cidparse.h */ +/* */ +/* CID-keyed Type1 parser (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + +#if 0 + + /*************************************************************************/ + /* */ + /* */ + /* CID_Table */ + /* */ + /* */ + /* A CID_Table is a simple object used to store an array of objects */ + /* in a single memory block. */ + /* */ + /* */ + /* block :: The address in memory of the growheap's block. This */ + /* can change between two object adds, due to the use */ + /* of `realloc()'. */ + /* */ + /* cursor :: The current top of the growheap within its block. */ + /* */ + /* capacity :: The current size of the heap block. Increments by */ + /* blocks of 1 kByte. */ + /* */ + /* init :: A boolean. Set when the table has been initialized */ + /* (the table user should set this field). */ + /* */ + /* max_elems :: The maximal number of elements in the table. */ + /* */ + /* num_elems :: The current number of elements (in use) in the table. */ + /* */ + /* elements :: A table of element addresses within the block. */ + /* */ + /* lengths :: A table of element sizes within the block. */ + /* */ + /* memory :: The memory object used for memory operations */ + /* (allocation resp. reallocation). */ + /* */ + typedef struct CID_Table_ + { + FT_Byte* block; /* current memory block */ + FT_Int cursor; /* current cursor in memory block */ + FT_Int 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; + + } CID_Table; + + + LOCAL_DEF + FT_Error CID_New_Table( CID_Table* table, + FT_Int count, + CID_Memory memory ); + + LOCAL_DEF + FT_Error CID_Add_Table( CID_Table* table, + FT_Int index, + void* object, + FT_Int length ); + + LOCAL_DEF + void CID_Release_Table( CID_Table* table ); + +#endif /* 0 */ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Parser */ + /* */ + /* */ + /* A CID_Parser is an object used to parse a Type 1 fonts very */ + /* quickly. */ + /* */ + /* */ + /* stream :: The current input stream. */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* 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. */ + /* */ + /* cursor :: The current parser cursor. */ + /* */ + /* limit :: The current parser limit (i.e., the first byte */ + /* after the current dictionary). */ + /* */ + /* error :: The current parsing error. */ + /* */ + /* cid :: A structure which holds the information about */ + /* the current font. */ + /* */ + /* num_dict :: The number of font dictionaries. */ + /* */ + typedef struct CID_Parser_ + { + FT_Stream stream; + FT_Memory memory; + + FT_Byte* postscript; + FT_Int postscript_len; + + FT_ULong data_offset; + + FT_Byte* cursor; + FT_Byte* limit; + FT_Error error; + + CID_Info* cid; + FT_Int num_dict; + + } CID_Parser; + + + LOCAL_DEF + FT_Error CID_New_Parser( CID_Parser* parser, + FT_Stream stream, + FT_Memory memory ); + + LOCAL_DEF + void CID_Done_Parser( CID_Parser* parser ); + + + /*************************************************************************/ + /* */ + /* PARSING ROUTINES */ + /* */ + /*************************************************************************/ + + LOCAL_DEF + FT_Long CID_ToInt( CID_Parser* parser ); + + LOCAL_DEF + FT_Int CID_ToCoordArray( CID_Parser* parser, + FT_Int max_coords, + FT_Short* coords ); + + LOCAL_DEF + FT_Int CID_ToFixedArray( CID_Parser* parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ); + + LOCAL_DEF + void CID_Skip_Spaces( CID_Parser* parser ); + + + /* simple enumeration type used to identify token types */ + typedef enum CID_Token_Type_ + { + t1_token_none = 0, + t1_token_any, + t1_token_string, + t1_token_array, + + /* do not remove */ + t1_token_max + + } CID_Token_Type; + + + /* a simple structure used to identify tokens */ + typedef struct CID_Token_Rec_ + { + FT_Byte* start; /* first character of token in input stream */ + FT_Byte* limit; /* first character after the token */ + CID_Token_Type type; /* type of token */ + + } CID_Token_Rec; + + + LOCAL_DEF + void CID_ToToken( CID_Parser* parser, + CID_Token_Rec* token ); + + + /* enumeration type used to identify object fields */ + typedef enum CID_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 + + } CID_Field_Type; + + typedef enum CID_Field_Location_ + { + t1_field_cid_info, + t1_field_font_dict, + t1_field_font_info, + t1_field_private, + + /* do not remove */ + t1_field_location_max + + } CID_Field_Location; + + + typedef FT_Error (*CID_Field_Parser)( CID_Face face, + CID_Parser* parser ); + + /* structure type used to model object fields */ + typedef struct CID_Field_Rec_ + { + const char* ident; /* field identifier */ + CID_Field_Location location; + CID_Field_Type type; /* type of field */ + CID_Field_Parser reader; + FT_UInt offset; /* offset of field in object */ + FT_UInt 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 */ + } CID_Field_Rec; + + +#define CID_FIELD_REF( s, f ) ( ((s*)0)->f ) + +#define CID_NEW_SIMPLE_FIELD( _ident, _type, _fname ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \ + sizeof ( CID_FIELD_REF( T1TYPE, _fname ) ), \ + 0, 0 \ + }, + +#define CID_NEW_CALLBACK_FIELD( _ident, _reader ) \ + { \ + _ident, T1CODE, t1_field_callback, \ + _reader, \ + 0, 0, \ + 0, 0 \ + }, + +#define CID_NEW_TABLE_FIELD( _ident, _type, _fname, _max ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \ + sizeof ( CID_FIELD_REF( T1TYPE, _fname )[0] ), \ + _max, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, num_ ## _fname ) \ + }, + +#define CID_NEW_TABLE_FIELD2( _ident, _type, _fname, _max ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \ + sizeof ( CID_FIELD_REF( T1TYPE, _fname )[0] ), \ + _max, 0 \ + }, + + +#define CID_FIELD_BOOL( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_bool, _fname ) + +#define CID_FIELD_NUM( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_integer, _fname ) + +#define CID_FIELD_FIXED( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_fixed, _fname ) + +#define CID_FIELD_STRING( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_string, _fname ) + +#define CID_FIELD_NUM_TABLE( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD( _ident, t1_field_integer_array, \ + _fname, _fmax ) + +#define CID_FIELD_FIXED_TABLE( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD( _ident, t1_field_fixed_array, \ + _fname, _fmax ) + +#define CID_FIELD_NUM_TABLE2( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD2( _ident, t1_field_integer_array, \ + _fname, _fmax ) + +#define CID_FIELD_FIXED_TABLE2( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD2( _ident, t1_field_fixed_array, \ + _fname, _fmax ) + +#define CID_FIELD_CALLBACK( _ident, _name ) \ + CID_NEW_CALLBACK_FIELD( _ident, parse_ ## _name ) + + + LOCAL_DEF + FT_Error CID_Load_Field( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ); + + LOCAL_DEF + FT_Error CID_Load_Field_Table( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDPARSE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/cidriver.c b/reactos/subsys/win32k/freetype/cidriver.c new file mode 100644 index 00000000000..f1c6b6a012f --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidriver.c @@ -0,0 +1,259 @@ +/***************************************************************************/ +/* */ +/* cidriver.c */ +/* */ +/* CID driver interface (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "cidriver.h" +#include "cidgload.h" + +#else + +#include +#include + +#endif + + +#include +#include +#include + +#include /* 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 + FT_Module_Interface CID_Get_Interface( FT_Driver driver, + const FT_String* interface ) + { + FT_UNUSED( driver ); + FT_UNUSED( interface ); + + 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 T1_Err_Ok; + } + + +#endif /* 0 */ + + + /*************************************************************************/ + /* */ + /* */ + /* Cid_Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* 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; + } + + + 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 + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverClass */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ + EXPORT_FUNC( FT_Driver_Class* ) getDriverClass( void ) + { + return &t1cid_driver_class; + } + + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/cidriver.h b/reactos/subsys/win32k/freetype/cidriver.h new file mode 100644 index 00000000000..a9674eed441 --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidriver.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* cidriver.h */ +/* */ +/* High-level CID driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + FT_EXPORT_VAR( const FT_Driver_Class ) t1cid_driver_class; + +#endif /* CIDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/cidtokens.h b/reactos/subsys/win32k/freetype/cidtokens.h new file mode 100644 index 00000000000..a916cea3227 --- /dev/null +++ b/reactos/subsys/win32k/freetype/cidtokens.h @@ -0,0 +1,99 @@ +/***************************************************************************/ +/* */ +/* cidtokens.h */ +/* */ +/* CID token definitions (specification only). */ +/* */ +/* Copyright 1996-2000 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 T1TYPE +#undef T1CODE +#define T1TYPE CID_Info +#define T1CODE t1_field_cid_info + + CID_FIELD_STRING ( "CIDFontName", cid_font_name ) + CID_FIELD_NUM ( "CIDFontVersion", cid_version ) + CID_FIELD_NUM ( "CIDFontType", cid_font_type ) + CID_FIELD_STRING ( "Registry", registry ) + CID_FIELD_STRING ( "Ordering", ordering ) + CID_FIELD_NUM ( "Supplement", supplement ) + CID_FIELD_CALLBACK( "FontBBox", font_bbox ) + CID_FIELD_NUM ( "UIDBase", uid_base ) + CID_FIELD_CALLBACK( "FDArray", fd_array ) + CID_FIELD_NUM ( "CIDMapOffset", cidmap_offset ) + CID_FIELD_NUM ( "FDBytes", fd_bytes ) + CID_FIELD_NUM ( "GDBytes", gd_bytes ) + CID_FIELD_NUM ( "CIDCount", cid_count ) + + +#undef T1TYPE +#undef T1CODE +#define T1TYPE T1_FontInfo +#define T1CODE t1_field_font_info + + CID_FIELD_STRING( "version", version ) + CID_FIELD_STRING( "Notice", notice ) + CID_FIELD_STRING( "FullName", full_name ) + CID_FIELD_STRING( "FamilyName", family_name ) + CID_FIELD_STRING( "Weight", weight ) + CID_FIELD_FIXED ( "ItalicAngle", italic_angle ) + CID_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch ) + CID_FIELD_NUM ( "UnderlinePosition", underline_position ) + CID_FIELD_NUM ( "UnderlineThickness", underline_thickness ) + + +#undef T1TYPE +#undef T1CODE +#define T1TYPE CID_FontDict +#define T1CODE t1_field_font_dict + + CID_FIELD_CALLBACK( "FontMatrix", font_matrix ) + CID_FIELD_NUM ( "PaintType", paint_type ) + CID_FIELD_NUM ( "FontType", font_type ) + CID_FIELD_NUM ( "SubrMapOffset", subrmap_offset ) + CID_FIELD_NUM ( "SDBytes", sd_bytes ) + CID_FIELD_NUM ( "SubrCount", num_subrs ) + CID_FIELD_NUM ( "lenBuildCharArray", len_buildchar ) + CID_FIELD_FIXED ( "ForceBoldThreshold", forcebold_threshold ) + CID_FIELD_FIXED ( "ExpansionFactor", expansion_factor ) + CID_FIELD_NUM ( "StrokeWidth", stroke_width ) + + +#undef T1TYPE +#undef T1CODE +#define T1TYPE T1_Private +#define T1CODE t1_field_private + + CID_FIELD_NUM ( "UniqueID", unique_id ) + CID_FIELD_NUM ( "lenIV", lenIV ) + CID_FIELD_NUM ( "LanguageGroup", language_group ) + CID_FIELD_NUM ( "password", password ) + + CID_FIELD_FIXED ( "BlueScale", blue_scale ) + CID_FIELD_NUM ( "BlueShift", blue_shift ) + CID_FIELD_NUM ( "BlueFuzz", blue_fuzz ) + + CID_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 ) + CID_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 ) + CID_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 ) + CID_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 ) + + CID_FIELD_NUM_TABLE2( "StdHW", standard_width, 1 ) + CID_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 ) + CID_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 ) + + CID_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 ) + CID_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 ) + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ctype.c b/reactos/subsys/win32k/freetype/ctype.c new file mode 100644 index 00000000000..b9872a181c1 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ctype.c @@ -0,0 +1,703 @@ +/* $Id: ctype.c,v 1.1 2001/05/02 12:21:26 jfilby Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/ctype.c + * PURPOSE: Character type and conversion functions + * PROGRAMMERS: ??? + * Eric Kohl + * HISTORY: ???: Created + * 10/01/2000: Added missing functions and changed + * all functions to use ctype table + */ + +#include +#include + +#define upalpha ('A' - 'a') + + +unsigned short _ctype[] = { + 0, /* , 0xFFFF */ + _CONTROL, /* CTRL+@, 0x00 */ + _CONTROL, /* CTRL+A, 0x01 */ + _CONTROL, /* CTRL+B, 0x02 */ + _CONTROL, /* CTRL+C, 0x03 */ + _CONTROL, /* CTRL+D, 0x04 */ + _CONTROL, /* CTRL+E, 0x05 */ + _CONTROL, /* CTRL+F, 0x06 */ + _CONTROL, /* CTRL+G, 0x07 */ + _CONTROL, /* CTRL+H, 0x08 */ + _CONTROL | _SPACE, /* CTRL+I, 0x09 */ + _CONTROL | _SPACE, /* CTRL+J, 0x0a */ + _CONTROL | _SPACE, /* CTRL+K, 0x0b */ + _CONTROL | _SPACE, /* CTRL+L, 0x0c */ + _CONTROL | _SPACE, /* CTRL+M, 0x0d */ + _CONTROL, /* CTRL+N, 0x0e */ + _CONTROL, /* CTRL+O, 0x0f */ + _CONTROL, /* CTRL+P, 0x10 */ + _CONTROL, /* CTRL+Q, 0x11 */ + _CONTROL, /* CTRL+R, 0x12 */ + _CONTROL, /* CTRL+S, 0x13 */ + _CONTROL, /* CTRL+T, 0x14 */ + _CONTROL, /* CTRL+U, 0x15 */ + _CONTROL, /* CTRL+V, 0x16 */ + _CONTROL, /* CTRL+W, 0x17 */ + _CONTROL, /* CTRL+X, 0x18 */ + _CONTROL, /* CTRL+Y, 0x19 */ + _CONTROL, /* CTRL+Z, 0x1a */ + _CONTROL, /* CTRL+[, 0x1b */ + _CONTROL, /* CTRL+\, 0x1c */ + _CONTROL, /* CTRL+], 0x1d */ + _CONTROL, /* CTRL+^, 0x1e */ + _CONTROL, /* CTRL+_, 0x1f */ + _SPACE | _BLANK, /* ` ', 0x20 */ + _PUNCT, /* `!', 0x21 */ + _PUNCT, /* 0x22 */ + _PUNCT, /* `#', 0x23 */ + _PUNCT, /* `$', 0x24 */ + _PUNCT, /* `%', 0x25 */ + _PUNCT, /* `&', 0x26 */ + _PUNCT, /* 0x27 */ + _PUNCT, /* `(', 0x28 */ + _PUNCT, /* `)', 0x29 */ + _PUNCT, /* `*', 0x2a */ + _PUNCT, /* `+', 0x2b */ + _PUNCT, /* `,', 0x2c */ + _PUNCT, /* `-', 0x2d */ + _PUNCT, /* `.', 0x2e */ + _PUNCT, /* `/', 0x2f */ + _DIGIT | _HEX, /* `0', 0x30 */ + _DIGIT | _HEX, /* `1', 0x31 */ + _DIGIT | _HEX, /* `2', 0x32 */ + _DIGIT | _HEX, /* `3', 0x33 */ + _DIGIT | _HEX, /* `4', 0x34 */ + _DIGIT | _HEX, /* `5', 0x35 */ + _DIGIT | _HEX, /* `6', 0x36 */ + _DIGIT | _HEX, /* `7', 0x37 */ + _DIGIT | _HEX, /* `8', 0x38 */ + _DIGIT | _HEX, /* `9', 0x39 */ + _PUNCT, /* `:', 0x3a */ + _PUNCT, /* `;', 0x3b */ + _PUNCT, /* `<', 0x3c */ + _PUNCT, /* `=', 0x3d */ + _PUNCT, /* `>', 0x3e */ + _PUNCT, /* `?', 0x3f */ + _PUNCT, /* `@', 0x40 */ + _UPPER | _HEX, /* `A', 0x41 */ + _UPPER | _HEX, /* `B', 0x42 */ + _UPPER | _HEX, /* `C', 0x43 */ + _UPPER | _HEX, /* `D', 0x44 */ + _UPPER | _HEX, /* `E', 0x45 */ + _UPPER | _HEX, /* `F', 0x46 */ + _UPPER, /* `G', 0x47 */ + _UPPER, /* `H', 0x48 */ + _UPPER, /* `I', 0x49 */ + _UPPER, /* `J', 0x4a */ + _UPPER, /* `K', 0x4b */ + _UPPER, /* `L', 0x4c */ + _UPPER, /* `M', 0x4d */ + _UPPER, /* `N', 0x4e */ + _UPPER, /* `O', 0x4f */ + _UPPER, /* `P', 0x50 */ + _UPPER, /* `Q', 0x51 */ + _UPPER, /* `R', 0x52 */ + _UPPER, /* `S', 0x53 */ + _UPPER, /* `T', 0x54 */ + _UPPER, /* `U', 0x55 */ + _UPPER, /* `V', 0x56 */ + _UPPER, /* `W', 0x57 */ + _UPPER, /* `X', 0x58 */ + _UPPER, /* `Y', 0x59 */ + _UPPER, /* `Z', 0x5a */ + _PUNCT, /* `[', 0x5b */ + _PUNCT, /* 0x5c */ + _PUNCT, /* `]', 0x5d */ + _PUNCT, /* `^', 0x5e */ + _PUNCT, /* `_', 0x5f */ + _PUNCT, /* 0x60 */ + _LOWER | _HEX, /* `a', 0x61 */ + _LOWER | _HEX, /* `b', 0x62 */ + _LOWER | _HEX, /* `c', 0x63 */ + _LOWER | _HEX, /* `d', 0x64 */ + _LOWER | _HEX, /* `e', 0x65 */ + _LOWER | _HEX, /* `f', 0x66 */ + _LOWER, /* `g', 0x67 */ + _LOWER, /* `h', 0x68 */ + _LOWER, /* `i', 0x69 */ + _LOWER, /* `j', 0x6a */ + _LOWER, /* `k', 0x6b */ + _LOWER, /* `l', 0x6c */ + _LOWER, /* `m', 0x6d */ + _LOWER, /* `n', 0x6e */ + _LOWER, /* `o', 0x6f */ + _LOWER, /* `p', 0x70 */ + _LOWER, /* `q', 0x71 */ + _LOWER, /* `r', 0x72 */ + _LOWER, /* `s', 0x73 */ + _LOWER, /* `t', 0x74 */ + _LOWER, /* `u', 0x75 */ + _LOWER, /* `v', 0x76 */ + _LOWER, /* `w', 0x77 */ + _LOWER, /* `x', 0x78 */ + _LOWER, /* `y', 0x79 */ + _LOWER, /* `z', 0x7a */ + _PUNCT, /* `{', 0x7b */ + _PUNCT, /* `|', 0x7c */ + _PUNCT, /* `}', 0x7d */ + _PUNCT, /* `~', 0x7e */ + _CONTROL, /* 0x7f */ + 0, /* 0x80 */ + 0, /* 0x81 */ + 0, /* 0x82 */ + 0, /* 0x83 */ + 0, /* 0x84 */ + 0, /* 0x85 */ + 0, /* 0x86 */ + 0, /* 0x87 */ + 0, /* 0x88 */ + 0, /* 0x89 */ + 0, /* 0x8a */ + 0, /* 0x8b */ + 0, /* 0x8c */ + 0, /* 0x8d */ + 0, /* 0x8e */ + 0, /* 0x8f */ + 0, /* 0x90 */ + 0, /* 0x91 */ + 0, /* 0x92 */ + 0, /* 0x93 */ + 0, /* 0x94 */ + 0, /* 0x95 */ + 0, /* 0x96 */ + 0, /* 0x97 */ + 0, /* 0x98 */ + 0, /* 0x99 */ + 0, /* 0x9a */ + 0, /* 0x9b */ + 0, /* 0x9c */ + 0, /* 0x9d */ + 0, /* 0x9e */ + 0, /* 0x9f */ + 0, /* 0xa0 */ + 0, /* 0xa1 */ + 0, /* 0xa2 */ + 0, /* 0xa3 */ + 0, /* 0xa4 */ + 0, /* 0xa5 */ + 0, /* 0xa6 */ + 0, /* 0xa7 */ + 0, /* 0xa8 */ + 0, /* 0xa9 */ + 0, /* 0xaa */ + 0, /* 0xab */ + 0, /* 0xac */ + 0, /* 0xad */ + 0, /* 0xae */ + 0, /* 0xaf */ + 0, /* 0xb0 */ + 0, /* 0xb1 */ + 0, /* 0xb2 */ + 0, /* 0xb3 */ + 0, /* 0xb4 */ + 0, /* 0xb5 */ + 0, /* 0xb6 */ + 0, /* 0xb7 */ + 0, /* 0xb8 */ + 0, /* 0xb9 */ + 0, /* 0xba */ + 0, /* 0xbb */ + 0, /* 0xbc */ + 0, /* 0xbd */ + 0, /* 0xbe */ + 0, /* 0xbf */ + 0, /* 0xc0 */ + 0, /* 0xc1 */ + 0, /* 0xc2 */ + 0, /* 0xc3 */ + 0, /* 0xc4 */ + 0, /* 0xc5 */ + 0, /* 0xc6 */ + 0, /* 0xc7 */ + 0, /* 0xc8 */ + 0, /* 0xc9 */ + 0, /* 0xca */ + 0, /* 0xcb */ + 0, /* 0xcc */ + 0, /* 0xcd */ + 0, /* 0xce */ + 0, /* 0xcf */ + 0, /* 0xd0 */ + 0, /* 0xd1 */ + 0, /* 0xd2 */ + 0, /* 0xd3 */ + 0, /* 0xd4 */ + 0, /* 0xd5 */ + 0, /* 0xd6 */ + 0, /* 0xd7 */ + 0, /* 0xd8 */ + 0, /* 0xd9 */ + 0, /* 0xda */ + 0, /* 0xdb */ + 0, /* 0xdc */ + 0, /* 0xdd */ + 0, /* 0xde */ + 0, /* 0xdf */ + 0, /* 0xe0 */ + 0, /* 0xe1 */ + 0, /* 0xe2 */ + 0, /* 0xe3 */ + 0, /* 0xe4 */ + 0, /* 0xe5 */ + 0, /* 0xe6 */ + 0, /* 0xe7 */ + 0, /* 0xe8 */ + 0, /* 0xe9 */ + 0, /* 0xea */ + 0, /* 0xeb */ + 0, /* 0xec */ + 0, /* 0xed */ + 0, /* 0xee */ + 0, /* 0xef */ + 0, /* 0xf0 */ + 0, /* 0xf1 */ + 0, /* 0xf2 */ + 0, /* 0xf3 */ + 0, /* 0xf4 */ + 0, /* 0xf5 */ + 0, /* 0xf6 */ + 0, /* 0xf7 */ + 0, /* 0xf8 */ + 0, /* 0xf9 */ + 0, /* 0xfa */ + 0, /* 0xfb */ + 0, /* 0xfc */ + 0, /* 0xfd */ + 0, /* 0xfe */ + 0 /* 0xff */ +}; + +unsigned short *_pctype = _ctype + 1; +unsigned short *_pwctype = _ctype + 1; + +int _isctype (int c, int ctypeFlags) +{ + return (_pctype[(unsigned char)(c & 0xFF)] & ctypeFlags); +} + +int iswctype(wint_t wc, wctype_t wctypeFlags) +{ + return (_pwctype[(unsigned char)(wc & 0xFF)] & wctypeFlags); +} + +int isalpha(int c) +{ + return(_isctype(c, _ALPHA)); +} + +int isalnum(int c) +{ + return(_isctype(c, _ALPHA | _DIGIT)); +} + +int __isascii(int c) +{ + return ((unsigned char)c <= 0x7f); +} + +int iscntrl(int c) +{ + return(_isctype(c, _CONTROL)); +} + +int __iscsym(int c) +{ + return(isalnum(c)||(c == '_')); +} + +int __iscsymf(int c) +{ + return(isalpha(c)||(c == '_')); +} + + +int isdigit(int c) +{ + return(_isctype(c, _DIGIT)); +} + +/* +int isgraph(int c) +{ + return (_isctype (c, _PUNCT | _ALPHA | _DIGIT)); +} +*/ + +int islower(int c) +{ + return (_isctype (c, _LOWER)); +} + +int isprint(int c) +{ + return (_isctype (c, _BLANK | _PUNCT | _ALPHA | _DIGIT)); +} + +/* +int ispunct(int c) +{ + return (_isctype (c, _PUNCT)); +} +*/ + +int isspace(int c) +{ + return (_isctype (c, _SPACE)); +} + +int isupper(int c) +{ + return (_isctype (c, _UPPER)); +} + +int isxdigit(int c) +{ + return (_isctype (c, _HEX)); +} + +/* +int iswalpha(wint_t c) +{ + return (iswctype (c, _ALPHA)); +} +*/ + +int iswdigit(wint_t c) +{ + return (iswctype (c, _DIGIT)); +} + +int iswlower(wint_t c) +{ + return (iswctype (c, _LOWER)); +} + +int iswxdigit(wint_t c) +{ + return (iswctype (c, _HEX)); +} + + +/* +int __toascii(int c) +{ + return((unsigned)(c) & 0x7f); +} + +int _tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +int _toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + upalpha); + return(c); +} +*/ + +int tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +int toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + upalpha); + return(c); +} + +wchar_t towlower(wchar_t c) +{ + if (iswctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +wchar_t towupper(wchar_t c) +{ + if (iswctype (c, _LOWER)) + return (c + upalpha); + return(c); +} + +/* EOF */ + +int strcmp(const char *s1, const char *s2) +{ + while (*s1 == *s2) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + + return *(unsigned const char *)s1 - *(unsigned const char *)(s2); +} + +int strncmp(const char *s1, const char *s2, size_t n) +{ + if (n == 0) + return 0; + do + { + if (*s1 != *s2++) + return *(unsigned const char *)s1 - *(unsigned const char *)--s2; + if (*s1++ == 0) + break; + } + while (--n != 0); + + return 0; +} + +char *strncpy(char *dst, const char *src, size_t n) +{ + if (n != 0) + { + char *d = dst; + const char *s = src; + + do + { + if ((*d++ = *s++) == 0) + { + while (--n != 0) + *d++ = 0; + break; + } + } + while (--n != 0); + } + + return dst; +} + +void * memmove(void *dest,const void *src,size_t count) +{ + char *char_dest = (char *)dest; + char *char_src = (char *)src; + + if ((char_dest <= char_src) || (char_dest >= (char_src+count))) + { + /* non-overlapping buffers */ + while(count > 0) + { + *char_dest = *char_src; + char_dest++; + char_src++; + count--; + } + } + else + { + /* overlaping buffers */ + char_dest = (char *)dest + count - 1; + char_src = (char *)src + count - 1; + + while(count > 0) + { + *char_dest = *char_src; + char_dest--; + char_src--; + count--; + } + } + + return dest; +} + +/* FIXME: these types should be from the default includes */ + +typedef int (* _pfunccmp_t) (char *, char *); + +#define min(a,b) ((a)<(b)?(a):(b)) + +/* + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + */ +#define swapcode(TYPE, parmi, parmj, n) { \ + long i = (n) / sizeof (TYPE); \ + register TYPE *pi = (TYPE *) (parmi); \ + register TYPE *pj = (TYPE *) (parmj); \ + do { \ + register TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} + +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + +static inline void +swapfunc ( + char * a, + char * b, + int n, + int swaptype + ) +{ + if(swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} + +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +static inline char * +med3 ( + char * a, + char * b, + char * c, + _pfunccmp_t cmp + ) +{ + return cmp(a, b) < 0 ? + (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) + :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); +} + + +/* EXPORTED */ +void +qsort ( + void * a, + size_t n, + size_t es, + _pfunccmp_t cmp + ) +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + int d, r, swaptype, swap_cnt; + +loop: SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) + { + for ( pm = (char *) a + es; + pm < (char *) a + n * es; + pm += es + ) + { + for ( pl = pm; + pl > (char *) a && cmp(pl - es, pl) > 0; + pl -= es + ) + { + swap(pl, pl - es); + } + } + return; + } + pm = (char *) a + (n / 2) * es; + if (n > 7) + { + pl = (char *) a; + pn = (char *) a + (n - 1) * es; + if (n > 40) + { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp); + pm = med3(pm - d, pm, pm + d, cmp); + pn = med3(pn - 2 * d, pn - d, pn, cmp); + } + pm = med3(pl, pm, pn, cmp); + } + swap(a, pm); + pa = pb = (char *) a + es; + + pc = pd = (char *) a + (n - 1) * es; + for (;;) + { + while (pb <= pc && (r = cmp(pb, a)) <= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (r = cmp(pc, a)) >= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + { + break; + } + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) /* Switch to insertion sort */ + { + for ( pm = (char *) a + es; + pm < (char *) a + n * es; + pm += es + ) + { + for ( pl = pm; + pl > (char *) a && cmp(pl - es, pl) > 0; + pl -= es + ) + { + swap(pl, pl - es); + } + } + return; + } + + pn = (char *) a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > es) + { + qsort(a, r / es, es, cmp); + } + if ((r = pd - pc) > es) + { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } +/* qsort(pn - r, r / es, es, cmp);*/ +} diff --git a/reactos/subsys/win32k/freetype/docs/build b/reactos/subsys/win32k/freetype/docs/build new file mode 100644 index 00000000000..93c74633dd8 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/build @@ -0,0 +1,264 @@ +FreeType 2 compilation how-to + + +Introduction: + +Welcome to this new beta of the FreeType 2 library. You'll find in this +document instructions on how to compile the library on your favorite +platform. + + *** UNIX USERS : Even though the FT2 build system doesn't + ************** : use the Autoconf/Automake tools, these will + ************** : be introduced in the Unix-specific parts of + ************** : the build in our final release.. + + +I. QUICK COMMAND-LINE GUIDE: +---------------------------- + + Install GNU Make, then try the following on Unix or any system with gcc: + + make // this will setup the build + make // this will build the library + + On Win32+Visual C++: + + make setup visualc // setup the build for VisualC++ on Win32 + make // build the library + + Then, go to the "demos" directory and type + + make + + To compile the demo programs.. + + If this doesn't work, read the following.. + + + +II. COMMAND-LINE COMPILATION: +----------------------------- + + Note that if you do not want to compile FreeType 2 from a command line + shell, please skip to section III below (DETAILED COMPILATION) + + FreeType 2 includes a powerful and flexible build system that allows you + to easily compile it on a great variety of platforms from the command + line. To do so, just follow these simple instructions: + + a/ Install GNU Make: + + Because GNU Make is the only Make tool supported to compile FreeType 2, + you should install it on your machine. + + Because the FT2 build system relies on many important features of GNU + Make, trying to build the library with any other Make tool will *fail*. + + + b/ Invoke "make": + + Go to the root FT2 directory, then simply invoke GNU Make from the + command line, this will launch the FreeType 2 Host Platform detection + routines. A summary will be displayed, for example, on Win32: + + ======================================================================== + FreeType build system -- automatic system detection + + The following settings are used: + + platform win32 + compiler gcc + configuration directory ./builds/win32 + configuration rules ./builds/win32/w32-gcc.mk + + If this does not correspond to your system or settings please remove + the file 'config.mk' from this directory then read the INSTALL file + for help. + + Otherwise, simply type 'make' again to build the library. + ========================================================================= + + If the detected settings correspond to your platform and compiler, + skip to step e/. Note that if your platform is completely alien to + the build system, the detected platform will be "ansi". + + + c/ Configure the build system for a different compiler: + + If the build system correctly detected your platform, but you want to + use a different compiler than the one specified in the summary (for + most platforms, gcc is the defaut compiler), simply invoke GNU Make + like : + + make setup + + For example: + + to use Visual C++ on Win32, type: "make setup visualc" + to use LCC-Win32 on Win32, type: "make setup lcc" + + The name to use is platform-dependent. The list of available + compilers for your system is available in the file + "builds//detect.mk" (note that we hope to make the list + displayed at user demand in the final release).. + + If you're satisfying by the new configuration summary, skip to step e/ + + + d/ Configure the build system for an unknown platform/compiler: + + What the auto-detection/setup phase of the build system does is simply + copy a file to the current directory under the name "config.mk". + + For example, on OS/2+gcc, it would simply copy "builds/os2/os2-gcc.mk" + to "./config.mk" + + If for some reason your platform isn't correctly detected, simply copy + manually the configuration sub-makefile to "./config.mk" and go to + step e/. + + Note that this file is a sub-Makefile used to specify Make variables + used to invoke the compiler and linker during the build, you can easily + create your own version from one of the existing configuration files, + then copy it to the current directory under the name "./config.mk". + + + e/ Build the library: + + The auto-detection/setup phase should have copied a file in the current + directory, called "./config.mk". This file contains definitions of various + Make variables used to invoke the compiler and linker during the build. + + To launch the build, simply invoke GNU Make again: the top Makefile will + detect the configuration file and run the build with it.. + + + f/ Build the demonstration programs: + + Once the library is compiled, go to "demos", then invoke GNU Make. + + Note that the demonstration programs include a tiny graphics sub-system + that includes "drivers" to display Windows on Win32, X11 and OS/2. The + build system should automatically detect which driver to use based on + the current platform. + + UNIX USERS TAKE NOTE: XXXXXX + + When building the demos, the build system tries to detect your X11 path + by looking for the patterns "X11R5/bin", "X11R6/bin" or "X11/bin" in + your current path. If no X11 path is found, the demo programs will not + be able to display graphics and will fail. Change your current path + if you encounter this problem. + + Note that the release version will use Autoconf to detect everything + on Unix, so this will not be necessary !! + + +II. DETAILED COMPILATION PROCEDURE: +----------------------------------- + + If you don't want to compile FreeType 2 from the command-line (for example + from a graphical IDE on a Mac or Windows), you'll need to understand how the + FreeType files are organized. + + FreeType 2 has a very module design, and it is made of several components. + Each component must be compiled as a stand-alone object file, even when it + is really made of several C source files. For example, the "base layer" + component is made of the following C files: + + src/ + base/ + ftcalc.c - computations + ftobjs.c - object management + ftstream.c - stream input + ftlist.c - simple list management + ftoutln.c - simple outline processing + ftextend.c - extensions support + + However, you can create a single object file by compiling the file + "src/base/ftbase.c", whose content is basically: + + #include + #include + #include + #include + #include + #include + + Similarly, each component has a single "englobing" C file to compile it + as a stand-alone object, i.e. : + + src/base/ftbase.c - the base layer, high-level interface + src/sfnt/sfnt.c - the "sfnt" module + src/psnames/psnames.c - the Postscript Names module + src/truetype/truetype.c - the TrueType font driver + src/type1/type1.c - the Type 1 font driver + + + To compile one component, do the following: + + - add the top-level "include" directory to your compilation include path + + - add the "src" directory to your compilation include path. + + - compile the component "source" file (see list below), you don't need + to be in the component's directory.. + + For example, the following line can be used to compile the truetype driver + on Unix: + + cd freetype2/ + cc -c -Iinclude -Isrc src/truetype/truetype.c + + Alternatively: + + cd freetype2/src/truetype + cc -c -I../../include -I.. truetype.c + + The complete list of files to compile for a feature-complete build of + FreeType 2 is: + + src/base/ftsystem.c - system-specific memory and i/o support + src/base/ftinit.c - initialisation layer + src/base/ftdebug.c - debugging component (empty in release build) + src/base/ftbase.c - the "base layer" component + src/base/ftglyph.c - optional convenience functions + src/raster1/raster1.c - the monochrome bitmap renderer + src/smooth/smooth.c - the anti-aliased bitmap renderer + src/sfnt/sfnt.c - the "sfnt" module + src/psnames/psnames.c - the "psnames" module + src/truetype/truetype.c - the TrueType font driver + src/type1/type1.c - the Type 1 font driver (incl. Multiple Masters) + src/cid/type1cid.c - the Type 1 CID-keyed font driver + src/cff/cff.c - the OpenType/CFF/CEF font driver + src/winfonts/winfnt.c - the Windows FNT/FON font driver + + All font drivers are optional. the "sfnt" and "psnames" modules are + mandatory for certain drivers. + + +III. Support for flat-directory compilation: +---------------------------------------- + + It is now possible to put all FreeType 2 source files into a single + directory, with the exception of the "include" hierarchy. + + Note that you'll still need to only compile the 'wrapper' sources described + above. Define the "FT_FLAT_COMPILE" macro when compiling. Here's an + example: + + 1/ Copy all files in current directory: + + cp freetype2/src/base/*.[hc] . + cp freetype2/src/raster1/*.[hc] . + cp freetype2/src/smooth/*.[hc] . + etc... + + 2/ Compile sources: + + cc -c -DFT_FLAT_COMPILE -Ifreetype/include ftsystem.c + cc -c -DFT_FLAT_COMPILE -Ifreetype/include ftinit.c + cc -c -DFT_FLAT_COMPILE -Ifreetype/include ftdebug.c + cc -c -DFT_FLAT_COMPILE -Ifreetype/include ftbase.c + etc... + diff --git a/reactos/subsys/win32k/freetype/docs/design/build-system.html b/reactos/subsys/win32k/freetype/docs/design/build-system.html new file mode 100644 index 00000000000..b548b4566a6 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/build-system.html @@ -0,0 +1,910 @@ + + + + + + + FreeType 2 Internals - I/O Frames + + + + + + +
+

FreeType 2.0 Build System

+ +
+

+© 2000 David Turner (david@freetype.org)
+© 2000 The FreeType Development Team +(devel@freetype.org) +

+ +
+ +


+ +

Table of Content

+ +
+

Introduction

+

I. Features & Background

+ +

II. Overview of the build process

+ +

III. Build setup details

+

IV. Library compilation details

+ + +
+ +
+

Introduction:

+ +

This document describes the new build system that was introduced + with FreeType 2.

+ +


+
+

I. Features and Background:

+ +

The FreeType 2 build system is a set of Makefiles and sub-Makefiles that + are used to build the library on a very large variety of systems easily. + One of its main features are the following:

+ +
+

1. Convenience, not Requirement

+
    +

    Even though the build system is rather sophisticated, it simply is a + convenience that was written simply to allow the compilation of the + FreeType 2 library on as many platforms as possible, as easily as + possible. However, it is not a requirement and the library can be + compiled manually or in a graphical IDE without using it, with minimal + efforts

    + +

    (for more information on this topic, see the BUILD + document that comes with your release of FreeType, in its Detailed + Compilation Guide section).

    +
+ +
+

2. Compiler and platform independence

+
    +

    The FreeType 2 build system can be used with any compiler, on any platform. + It is independent of object file suffix, executable file suffix, directory + separator convention (i.e. "/" or "\"), and compiler flags for path + inclusion, macro definition, output naming, ansi compliance, etc..

    + +

    Supporting a new compiler is trivial and only requires writing a minimal + configuration sub-makefile that contains several Makefile variables + definitions that are later used by the rest of the build system. This is + described in details later in the document.

    +
+ +
+

3. Uses GNU Make

+
    +

    The build system works exclusively with GNU Make. Reason + is that it is the only make utility that has all the features required to + implement the build system as described below. Moreover, it is already + ported to hundreds of various distinct platforms and is widely and + freely available.

    + +

    It also uses the native command line shell. You thus + don't need a Unix-like shell on your platform. + For example, FreeType 2 already compiles on Unix, Dos, Windows + and OS/2 right "out of the box" (assuming you have GNU Make + installed).

    + +

    Finally, note that the build system is specifically designed + for gnu make and will fail with any other make tool. We have + no plans to support a different tools, as you'll rapidly + understand by reading this document or looking at the sub-makefiles + themselves.

    +
+ +
+

4. Automatic host platform detection

+
    +

    When you launch the build system for the first time, by simply invoking + GNU make in the top-level directory, it automatically tries to detect + your current platform in order to choose the best configuration + sub-makefile available. It then displays what it found. If everything + is ok, you can then launch compilation of the library, by invoking make + a second time.

    + +

    The following platforms are currently automatically detected:

    +
      +
    • Dos (plain-dos, windows in Dos mode, or Dos session under OS/2) +
    • Windows 95, 98 + Windows NT (a.k.a win32) +
    • OS/2 +
    • Unix (uses Autoconf/Automake) +
    + +

    Note that adding support for a new platform requires writing a minimal + number of very small files, and simply putting them in a new sub-directory + of freetype2/config.

    +
+ +
+

5. User-selectable builds

+
    +

    The platform auto-detection rules try to setup the build for a default + compiler (gcc for most platforms), with default build options + for the library (which normally is + "all features enable, no debugging"), as well as the default + list of modules (which is "all modules in freetype2/src")

    + +

    There are cases where it is important to specify a different compiler, + different build options or simply a different module list. The FreeType 2 + build system is designed in such a way that all of this is easily possible + from the command line, without having to touch a single file. + The latter is crucial when dealing with projects that need specific + builds of the library without modifying a single file from the FreeType + distribution.

    + +

    The exact mechanism and implementation to do this is described later in + this document. It allows, for example, to compile FreeType with any of + the following compilers on Win32: gcc, Visual C++, Win32-LCC.

    +
+ +
+

6. Robustness

+
+ + +

7. Simple Module Management

+
    +

    FreeType 2 has a very modular design, and is made of a core + base layer that provides its high-level API as well as + generic services used by one or more modules. + + Most modules are used to support a specific font format (like TrueType + or Type 1), and they are called font drivers. However, some of + them do not support font files directly, but rather provide helper + services to the font drivers.

    + +

    FreeType 2 is designed so that adding modules at run-time is possible + and easy. Similarly, we expect many more modules to come in the near + future and wanted a build system that makes such additions to the + source package itself dead easy. + + Indeed, all source code (base + modules) is located in the + freetype2/src directory hierarchy. And the build system is + capable of re-generating automatically the list of known modules + from the contents of this directory. Hence, adding a new font driver + to the FreeType sources simply requires to:

    + +
      +
    • Add a new sub-directory to freetype2/src +

    • Re-launch the build system

      +
    + +

    There is thus no need to edit a source file

    +
+ +


+ +

II. Overview of the build process(es):

+ +

Before describing in details how the build system works, it is essential + to give a few examples of how it's used. This section presents + what's the build process is to the typical developer:

+ +

Compiling the library is normally done in two steps: the first one + configures the build according to the current platform and possible + additional parameters, while the second simply compiles the library with + the information gathered in the configuration step.

+ +
+

1. Build Setup

+ +
+

a. Default build setup

+
    +

    To configure the build, simply invoke gnu make from the top-level FreeType + directory. This will launch a series of rules that will detect your current + host platform, and choose a configuration file for you. It will then display + what it found. For example, here's the output of typing the command "make" + on a win32 platform (assuming this calls GNU make):

    + +
    
    +    C:\FreeType> make
    +
    +    FreeType build system -- automatic system detection
    +
    +    The following settings are used:
    +
    +      platform                     win32
    +      compiler                     gcc
    +      configuration directory      ./config/win32
    +      configuration rules          ./config/win32/w32-gcc.mk
    +
    +    If this does not correspond to your system or settings please remove the file
    +    'config.mk' from this directory then read the INSTALL file for help.
    +
    +    Otherwise, simply type 'make' again to build the library.
    +
    +    C:\FreeType>
    +
    + +

    Note that this step copies the selected configuration file (here + ./config/win32/w32-gcc.mk) to the current directory, under + the name config.mk. This file contains data that is used + to drive the library compilation of the second step. It correspond to + the platform and compiler selected by the auto-detection phase.

    + +

    Note that you can re-generate the config.mk file anytime + by invoking make setup whenever you need it, even when the file is + already present in the current directory.

    + +

    Finally, if your platform is not correctly detected, the build system will + display and use configuration information for the virtual "ansi" platform. +

    +
+
+

b. Selecting another build configuration

+
    +

    You may not be really satisfied by the configuration file selected by the + auto-detection routines. Typically, you might be using a compiler that is + not the default one for your platform. It is however possible to re-launch + the build setup phase with an additional argument, used to specify a + different compiler/config file. For example, you can type the following + commands on Win32 systems:

    + +

    +

    make setup

    +
    +

    re-run the platform detection phase, and select the default compiler for it. + On Win32, this is gcc.

    +
    +

    make setup visualc

    +
    +

    re-run the platform detection phase, and select a config file that + corresponds to the Visual C++ compiler

    +
    +

    make setup lcc

    +
    +

    re-run the platform detection phase, and select a config file that + corresponds to the Win32-LCC compiler

    +
    +

    + +

    Note that a specific configuration is selected with a command that + looks like : make setup compiler, + where the compiler keywords depends on the platform. + Moreover, each one of them corresponds to a specific configuration + sub-makefile that is copied as config.mk in the current + directory.

    +
+ + +
+

2. Library compilation

+ +

Once you're satisfied with the version of config.mk that + has been copied to your current directory, you can simply re-invoke + gnu make with no arguments. The top-level Makefile will + automatically detect the config sub-makefile in the current directory, + and use it to drive the library compilation. The latter can be seen + as a series of different steps decribed here:

+ +
    +
  • Compiling the ftsystem component

      + It encapsulates all low-level operations (memory management + + i/o access) for the library. Its default version, located in + ./src/base/ftsystem.c uses the ANSI C library but + system-specific implementations are also available to + improve performance (e.g. memory-mapped files on Unix). +

    + +
  • Compiling the base layer and optional components

      + They provide the library's high-level API as well as various useful + routines for client applications. Many features of the base layer can + be activated or not depending on a configuration file named + ftoption.h +

    + +
  • Compiling the modules

      + Each module is used to support a specific font format (it is then + called a font driver), or to provide helper services to + the drivers (e.g. the auto-hinter). They are all located in + sub-directories of ./src, like ./src/truetype, + ./src/type1. +

    + +
  • Compiling the ftinit component

      + This one is in charge of implementing FT_Init_FreeType, + the library initialisation routine. It also selects what modules + are activated when a new library instance is created. +

    +
+


+ +

II. Details of the build setup.

+ +

When the top-level Makefile is invoked, it looks for a + file named config.mk in the current directory. + If this file is found, it is used directly to build the library + (skip to Section III for details then).

+ +

Otherwise, the file ./config/detect.mk is included + by the top-level Makefile and parsed. Its purpose is to drive the + platform-detection phase, by:

+ +
    +
  • Defining the PLATFORM variable, which indicates + what the currently detected platform is. It is initially + set to the default value "ansi". +

    + +
  • Searching for a detect.mk file in all + subdirectories of ./config. + Each such file is included and parsed. Each of these files must + try to detect if the host platform is a system it knows + about. If so, it changes the value of the PLATFORM variable + accordingly.

    + +
  • Copying the selected configuration submakefile to the current directory + under the name config.mk.

    +
+

This is illustrated by the following graphics :

+

+ +

+ +

Each system-specific detect.mk works as follows:

+
    +
  • It checks that the value of PLATFORM is currently set + to ansi, which indicates that no platform was detected + for now. If this isn't true, it doesn't do anything

    + +
  • Otherwise, it runs a series of test to see wether it is on a + system it knows about. Here are a few examples of tests:

    + +

    + Unix + +

    checks for a file named /sbin/init, and runs, when it found + it, a 'configure' script to generate the relevant config sub-makefile

    +
    + Dos + +

    checks for the COMSPEC environment variable, then tries to + run the "ver" command on the current shell to check that there + is a "Dos" substring in its output; if not, it tries to find the + substring "MDOS\COMMAND" in COMSPEC, which indicates + a Dos session under OS/2.

    +
    + Win32 + +

    if the environment variable OS is defined and has the value + Windows_NT, or if COMSPEC is defined and the + "ver" returns a string that contains Windows in it, + we're on a Win32 system.

    +
    +

    + +
  • It sets the value of PLATFORM to a new value corresponding + to its platform.

    + +
  • It then tries to select a configuration + sub-makefile, depending on the current platform and any optional + make target (like "visualc" or "devel", etc..). Note that it can + even generate the file, as on Unix through Autoconf/Automake.

    + +
  • It copies the selected configuration sub-makefile to the current + directory, under the name config.mk +

+ +

If one wants to support a new platform in the build system, it simply needs + to provide:

+ +
    +
  • A new subdirectory, in ./config, with a file named + detect.mk in it, containing relevant checks for the system. + +
  • One or more configuration sub-makefiles that will get copied to + config.mk at build setup time. You can use the one in + ./config/ansi/config.mk as a template. +
+ +

Similary, supporting a new compiler on an existing system simply means:

+
    +
  • Writing a new config sub-makefile that contains definitions used to + specify the compiler and flags for the build. + +
  • Change your ./config/system/detect.mk to recognize + a new optional build target that will copy your new config sub-makefile + instead of the default one. +
+ + +


+

III. Details of the library compilation.

+ +

When the top-level Makefile is invoked, it looks for a file named + config.mk in the current directory. If one is found, it + defines the BUILD_FREETYPE variable, then includes and parses it. + The structure of this file is the following: +

+ +
    +
  • First, it defines a series of Make variables that describe + the host environment, like the compiler, compilation flags, + object file suffix, the directory where all object files are + placed, etc..

    + +
  • If BUILD_FREETYPE is defined, it includes the file + ./config/freetype.mk, which is in charge of + defining all the rules used to build the library object files. + (The test is useful to use the config.mk file to + compile other projects that rely on FreeType 2, like its + demonstration programs).

    + +
  • Finally, it defines the rule(s) used to link FreeType 2 object files + into a library file (e.g. libfreetype.a, freetype.lib, + freetype.dll, ...). Unfortunately, the command line interface of link tools is + a lot less standardized than those of compilers, which + explains why this rule must be defined in the system-specific + config.mk.

    +
+ +

The following is an explanation of what ./config/freetype.mk + does to build the library objects: +

+ +

a. Include paths

+
    +

    To avoid namespace pollution, the freetype directory prefix + is used to include all public header files of the library. This means + that a client application will typically use lines like:

    + +
    
    +    #include <freetype/freetype.h>
    +    #include <freetype/ftglyph.h>
    +
    + +

    to include one the FreeType 2 public header files. freetype.mk + uses a variable named INCLUDES to hold the inclusion + paths list, and thus starts by adding ./include to it. However, + nothing prevents + +

    freetype.mk uses a variable named INCLUDES + to hold directory inclusion-path to be used when compiling the library. + It always add ./include to this variable, which means + +

+ +

b. Configuration header files:

+
    +

    Three header files used to configure the compilation of the + FreeType 2 library. Their default versions are all located in the + directory ./include/freetype/config/, even though + project specific versions can be provided on a given build, as + described later:

    + +
      +

      #include <freetype/config/ftoption.h>

        + This file contains a set of configuration macro definitions that + can be toggled to activate or deactivate certain features of the + library. By changing one of these definitions, it is possible to + compile only the features that are needed for a specific + project. Note that by default, all options are enabled. +

        + You might need to provide an alternative version of ftoption.h + for one of your own projects. +

      + +

      #include <freetype/config/ftconfig.h>

        + This file includes ftoption.h but also contains some automatic + macro definitions used to indicate some important system-specific + features (e.g: word size in bytes, DLL export prefix macros, etc..). +

        + You shouldn't normally need to change or provide an alternative + version of this file. +

      + + +

      #include <freetype/config/ftmodule.h>

        + This file is very special, as it is normally machine-generated, and + used by the ftinit component that is described below. To + understand it, one must reminds that FreeType 2 has an extremely + modular design and that it's possible to change, at run-time, + the modules it's using. The ftmodule.h file simply contains + the list of modules that are registered with each new instance of + the library. +

        + Note that the file can be re-generated automatically by invoking + make setup from the top-level directory. The re-generated + list contains all the modules that were found in subdirectories of + ./src. +

      +
    + +

    Note that we strongly advise you to avoid modifying the config files + within the FreeType 2 source directory hierarchy. Rather, it's possible + to specify alternative versions through the help of a build-specific + include path that is include before ./include in the inclusion + path.

    + +

    For example, imagine that your platform, named foo, needs a + specific version of ftoption.h +

+ +

a. Compiling the ftsystem component:

+
    +

    FreeType 2 encapsulates all low-level operations (i.e. memory management + and i/o access) within a single component called ftsystem. + Its default implementation uses the ANSI C Library and is located + in ./src/base/ftsystem.c.

    + +

    However, some alternate, system-specific, implementations of + ftsystem are provided with the library in order to support more + efficient and advanced features. As an example, the file + ./config/unix/ftsystem.c is an implementation that + uses memory-mapped files rather than the slow ANSI fopen, + fread and fseek, boosting performance significantly.

    + +

    The build system is thus capable of managing alternate implementations + of ftsystem

    +
+ +

b. Compiling the base layer and optional components:

+
    +

    The high-level API of the library is provided by a component called the + base layer, whose source is located in ./src/base. This + directory also contains one or more components that are optional, i.e. + that are not required by the library but provide valuable routines to + client applications.

    + +

    The features of the base library and other components are selected through + a single configuration file named + ./include/freetype/config/ftoption.h. It contains a list + of commented configuration macro definitions, that can be toggled to + activate or de-activate a certain feature or component at build time.

    + +

    For example, the code in ./src/base/ftdebug.c will be compiled + only if one of these two macros are defined in ftoption.h: + FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE

    +
+ +

c. Compiling the modules:

+
    +

    Once the base layer is completed, the build system starts to compile each + additional module independently. These are simply defined as all source + code located in a sub-directory of ./src that contains a file + named rules., for example: + src/sfnt, src/truetype, src/type1, ...

    + +

    The rules. file simply contains directives used by the + build system to compile the corresponding module into a single object + file.

    +
+ +

d. Compiling the ftinit component:

+
    +

    The file ./src/base/ftinit.c is special because it is used + to implement the library initialisation function FT_Init_FreeType. +

    +
+ +

Typically, you will end up with all object files, as well as the + corresponding library file, residing in the freetype2/obj + directory.

+ + +

1. Purpose of the configuration sub-makefile

+ +

2. Managing module dependencies

+ +

3.

+ +


+ +

IV. Managing the modules list

+ +


+ The build system features some important points, which are all detailed + in the following sections:

+

    +
  • Automatic host platform detection
    + The first time the top Makefile is invoked, it will + run a series of rules to detect your platform. It will then + create a system-specific configuration sub-Makefile in the + current directory, called config.mk. You can now + invoke the top Makefile a second time to compile the + library directly. +

    + The configuration sub-makefile can be regenerated any time + by invoking "make setup", which will re-run the + detection rules even if a config.mk is already present. +

    + + +

  • User-selectable builds
    +

    + + + +

  • Automatic detection of font drivers
    + FreeType is made of a "base" layer that invokes several + separately-compiled modules. Each module is a given + font driver, in charge of supporting a given font format. +

    + The list of font drivers is located in the file + "freetype2/config/system/ftmodule.h", however + it can be regenerated on-demand. Adding a new module to the + FreeType source tree is thus as easy as:

    +

      +
    • create a new directory in "freetype2/src" and + put the new driver's source code and sub-makefiles there. +

      + +

    • invoke the top Makefile with target + "modules" (as in "make modules"), + as this will automatically regenerate the list of + available drivers by detecting the new directory and + its content. +
    +

    +

+ + +


+ +

II. Host Platform Detection

+
    + When the top-level Makefile is invoked, it looks for a + file named config.mk in the current directory. If this + file is found, it is used to build the library + (see Section III). +

    + Otherwise, the file freetype2/config/detect.mk is included + and parsed. Its purpose is to:

    +

      +
    • Define the PLATFORM variable, which indicates + what is the currently detected platform. It is initially + set to the default value "ansi". +

      + +

    • It searches for a detect.mk file in all + subdirectories of freetype2/config. Each such + file is included and parsed. Each of these files must + try to detect if the host platform is a system it knows + about. If so, it changes the value of the PLATFORM + accordingly. +
    +

    + This is illustrated by the following graphics :

    +

    + +
    +

    + Note that each system-specific detect.mk is in charge + of copying a valid configuration makefile to the current directory + (i.e. the one where make was invoked), depending on the + current targets. For example, the Win32 detect.mk will + be able to detect a "visualc" or "lcc" target, + as described in section I. Similarly, the OS/2 detect.mk + can detect targets like "borlandc", "watcom" + or "visualage", etc.. +

+ +


+ +

III. Building the library

+
    + When the top-level Makefile is invoked and that it finds + a config.mk file in the current directory, it defines + the variable BUILD_FREETYPE, then includes and parses the + configuration sub-makefile. +

    + The latter defines a number of important variables that describe + the compilation process to the build system. Among other things:

    +

      +
    • the extension to be used for object files and library files + (i.e. .o and .a on Unix, .obj + and .lib on Dos-Windows-OS/2, etc..). +

      + +

    • the directory where all object files will be stored + (usually freetype2/obj), as well as the one + containing the library file (usually the same as for + objects). +

      + +

    • the command line compiler, and its compilation flags for + indicating a new include path (usually "-I"), + a new macro declaration (usually "-D") or + the target object file (usually "-o ") +
    +

    + Once these variable are defined, config.mk test for the + definition of the BUILD_FREETYPE variable. If it exists, + the makefile then includes "freetype2/config/freetype.mk" + which contains the rules required to compile the library. +

    + Note that freetype.mk also scans the subdirectories of + "freetype2/src" for a file called "rules.mk". + Each rules.mk contains, as it names suggests, the rules + required to compile a given font driver or module. +

    + Once all this parsing is done, the library can be compiled. Usually, + each font driver is compiled as a standalone object file (e.g. + sfnt.o, truetype.o and type1.o). +

    + This process can be illustrated by the following graphics:

    +

    + +
    +

    +

+ +


+ +

IIV. Managing the list of modules

+
    + The makefile freetype.mk only determines how to compile + each one of the modules that are located in the sub-directories of + freetype2/src. +

    + However, when the function FT_Init_FreeType is invoked at + the start of an application, it must create a new FT_Library + object, and registers all known font drivers to it by + repeatly calling FT_Add_Driver. +

    + The list of known drivers is located in the file + "freetype2/config/system/ftmodule.h", and is used + exclusively by the internal function FT_Default_Drivers. The + list in ftmodule.h must be re-generated each time you add + or remove a module from freetype2/src. +

    + This is normally performed by invoking the top-level Makefile + with the modules target, as in:

    +

      + make modules +
    +

    + This will trigger a special rule that will re-generate + ftmodule.h. To do so, the Makefile will parse all module + directories for a file called "module.mk". Each + module.mk is a tiny sub-Makefile used to add a single + module to the driver list. +

    + This is illustrated by the following graphics:

    +

    + +
    +

    + Note that the new list of modules is displayed in a very human-friendly + way after a "make modules". Here's an example with the current + source tree (on 11 Jan 2000):

    +

      +Regenerating the font drivers list in ./config/unix/ftmodule.h
      +* driver:  sfnt      ( pseudo-driver for TrueType & OpenType formats )
      +* driver:  truetype  ( Windows/Mac font files with extension *.ttf or *.ttc )
      +* driver:  type1     ( Postscript font files with extension *.pfa or *.pfb )
      +-- done --
      +    
    + +
+ +


+ +

V. Building the demonstration programs

+
    + Several demonstration programs are located in the + "freetype2/demos" directory hierarchy. This directory also + includes a tiny graphics sub-system that is able to blit glyphs to + a great variety of surfaces, as well as display these in various + graphics libraries or windowed environments. +

    + This section describes how the demonstration programs are compiled, + using the configuration freetype2/config.mk and their own + freetype2/demos/Makefile. +

    + To compile the demonstration programs, after the library, + simply go to freetype2/demos then invoke GNU make with no + arguments. +

    + The top-level Makefile will detect the config.mk in the + upper directory and include it. Because it doesn't define + the BUILD_FREETYPE variable, this will not force the + inclusion of freetype2/config/freetype.mk as described in + the previous section. +

    + the Makefile will then include the makefile called + "freetype2/demos/graph/rules.mk". The graphics rules.mk + defines the rules required to compile the graphics sub-system. +

    + Because the graphics syb-system is also designed modularly, it is able + to use any number of "modules" to display surfaces on the screen. + The graphics modules are located in the subdirectories of + freetype2/demos/config. Each such directory contains a file + named rules.mk which is in charge of:

    +

      +
    • detecting wether the corresponding graphics library is + available at the time of compilation. +

      +

    • if it is, alter the compilation rules to include the graphics + module in the build of the graph library. +
    +

    + When the graph library is built in demos/obj, the + demonstration programs executables are generated by the top-level + Makefile. +

    + This is illustrated by the following graphics:

    +

    + +
    +
+ +


+
+ + + diff --git a/reactos/subsys/win32k/freetype/docs/design/demo-programs.png b/reactos/subsys/win32k/freetype/docs/design/demo-programs.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/demo-programs.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/design/drivers-list.png b/reactos/subsys/win32k/freetype/docs/design/drivers-list.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/drivers-list.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/design/index.html b/reactos/subsys/win32k/freetype/docs/design/index.html new file mode 100644 index 00000000000..50f7f290a79 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/index.html @@ -0,0 +1,791 @@ + + + + + + + FreeType 2 Internals + + + + + +
+

+FreeType 2.0 Internals

+ +
+

+Version 1.2

+ +
+

+© 1999-2000 David Turner (david@freetype.org)
+© 1999-2000 The FreeType Development Team (devel@freetype.org)

+ +


+


+
  +

Introduction:

+ +

This document describes in great deatils the internals of FreeType 2. + It is a must read for porters and developers alike. Its purpose is to + + present the +

This document describes in great details the internals of the +FreeType 2.0 library. It is a must read for porters and developers alike. +Its purpose is to present the engine's objects, their roles and interactions. +It is assumed that the FreeType Glyph Conventions document +has been read. +

We advise porters to also read the FreeType Porting Guide +after this document. Would-be hackers and maintainers are of course encouraged +to read the FreeType Coding Conventions document too. The +development of a new driver is described in more details in the FreeType +Driver HowTo document.

+ +


+


+

+I. Overview :

+ +
+

+1. Features (and what's new) :

+ +
FreeType 2.0 has a number of important new features that were +not found in the 1.x releases : +
  +
font-format independent API +
FreeType 2.0 is able to support any kind of font format, be it fixed +or scalable, through the use of pluggable "font drivers". These drivers +can be added or replaced at run time, while applications use a new font +format-independent API. +

advanced stream caching +
2.0 is able to control the number of concurrently opened streams when +using fonts. It is thus possible to open dozens or hundreds of font faces +without running out of system resources. +

real reentrancy support +
It is now possible to use FreeType as a shared library with no static +data in a multi-threaded environment. The synchronization model has also +been simplified in order to make font driver writing easier. Of course, +you can build FreeType with no thread support to get a smaller library. +

support for cubic beziers and 17-levels anti-aliasing +
The FreeType scan-line converter (a.k.a. raster) now supports cubic +bezier arcs seamlessly. It also provides a new anti-aliasing mode which +uses a palette of 17 levels of grays. +
 

+It also features the following : +
performance improvements : +
The FreeType raster has been optimized, and the generation of anti-aliased +pixmaps is now 60% faster than in the 1.x release. Moreover, the TrueType +bytecode interpreter has been profiled and greatly optimised. +

easier portability +
Porting and configuring FreeType is now much easier. A single file +must be provided for system-specific operations (like memory, i/o, thread +management), and a single configuration header is used to select the build +you need. +
 

+
+ +

+2. Architecture :

+ +
The engine is now split in several parts, which are : +

+a. The base layer :

+ +
This part contains all the font-format independent features +of the engine which are : +
    +
  • +computations/scaling
  • + +
  • +list processing
  • + +
  • +outline processing
  • + +
  • +scan-line converter
  • + +
  • +stream manager
  • + +
  • +base object classes
  • + +
  • +debugging & traces
  • + +
  • +high-level API functions
  • + +
  • +low-level system object (memory, i/o, threads)
  • +
+
+ +

+b. The font drivers :

+ +
Each font format is managed with the use of a single font driver +object. The base layer is able to manage several drivers, and these can +be easily added, removed or upgraded at runtime. Each driver has the following +features and functions : +
    +
  • +auto-check font format when opening a font resource (i.e. file)
  • + +
  • +access, load and/or extract all tables and data from the font file
  • + +
  • +grid-fit/hint the glyph outlines (in the case of scalable formats like +TrueType or Type1)
  • + +
  • +provide extensions to access font format-specific data and tables from +the font file
  • +
+Note that FreeType 2.0 is a font service. Its purpose is to provide a unified +API for all kinds of fonts and extract individual glyph images and metrics. +However, it does not render text itself, as this operation is left to the +developer, or to higher-level libraries built on top of FreeType. Here +are a few features that are thus not implemented : +
1) Text string rendering +
2) Glyph bitmap/outline caching for improved performance +
3) Synthetic fonts (i.e. italicising, emboldening, underlining) +
4) Contextual glyph substitution and other advanced layout processes
+Note that features 1 through 3 should be provided by the SemTex library, +which may soon become part of the standard FreeType distribution.
+
+
+ +


+


+

+II. Design :

+ +
+

+1. Objects :

+ +
They are several kinds of objects in FreeType, which can be +described as follows : +
Base objects +
These objects do not relate directly to font data, but to the way it +is organised and managed. It is the basic core and provides functions that +are heavily used by each font driver. Examples are the resource objects, +used to describe font files, the system object used to manage low-level +system operations, or the raster object, used to convert vector outlines +into bitmaps or anti-aliased pixmaps. Most of the base objects are not +directly visible for client applications of FreeType. +

Font objects +
The font objects directly model the data as it is found in font files. +The root classes implemented in the base layer like FT_Face, FT_Size, +FT_GlyphSlot, +must be derived in each font driver.

+Objects are defined in the files "base/freetype.h" and "base/ftobjs.h". +The former contains all the public object definitions usable by client +applications. The latter contains private definitions used by the rest +of the base layer and each font driver.
+ +

+2. List management

+ +
The "base/ftlist.c" component a very simple doubly-linked +list facility which is used by the rest of the engine to create and process +lists, including iteration and finalisation. The definition of the list +node and functions are placed in the "base/freetype.h" to let +client applications access listed objects as they like. +

The base list type is FT_List, which links nodes of type FT_ListNode +together. +
 

+ +

+3. Limited encapsulation

+ +
Unlike what happened in the 1.x releases, the FT_Face, +FT_Size, +FT_GlyphSlot and FT_CharMap types are no longer blind +pointers to opaque types. Rather, the corresponding structures are now +public (and defined in "base/freetype.h", see FT_FaceRec, +FT_SizeRec, +etc..) in order to let client applications read directly the various object +attributes they're interested in. +

This breaks encapsulation of implementation, famed by OOP, but was chosen +because: +
  +

    +
  • +it simplifies a lot the work of client applications and libraries which +don't need to perform a function call everytime they want to read one important +object attribute (nor does it force them to cache these attributes in their +own structures).
  • +
+ +
    +
  • +It reduces greatly the API, as many FT_Get_XXX functions are avoided.
  • +
+ +
    +
  • +Higher-level libraries are able to  access data directly. When it +is used frequently, they don't need to cache it in their own structures.
  • +
+ +
    +
  • +It is possible to tightly link FreeType objects with higher-level ones, +in a clearer and more efficient way. This is very important when one wants +to write a C++ wrapper or a text rendering library on top of FreeType (actually, +both projects were performed in an earlier version of FreeType 2.0 which +featured classic encapsulation through get/set methods. The resulting code +was ugly and slow. Moving to a limited encapsulation approach simplified +so many things that the compiled code size was reduced by a factor of two +!).
  • +
+ +
    +
  • +Finally, the API and font object structures were designed after the creation +of two scalable font drivers and one bitmap font driver. They are now very +stable and the public (visible) attributes are not going to change.
  • +
+
+
+ +


+


+

+III. Base objects :

+ +
This section describes the FreeType base object classes : +
  +

+1. System objects :

+ +
The system class is in charge of managing all low-level and +system-specific operations. This means simply memory management, i/o access +and thread synchronisation. It is implemented by the "ftsys.c" +component, whose source must be located in the configuration directory +when building FreeType. (e.g. "lib/arch/ansi/ftsys.c" for an ANSI +build, "lib/arch/unix/ftsys.c" for a Unix one, etc..). +

Porting FreeType 2.0 really means providing a new implementation of +ftsys +(along with a few configuration file changes). Note however that its interface +is common to all ports, and located in "base/ftsys.h".

+ +

+2. Resources and Streams:

+ +
The concepts of files as storages, and files as streams has +been separated for FreeType 2.0. The "resource" concept was +introduced while the "stream" one has been redefined. Here +is how they work together : +
    +
  • +a "resource" is an object which models a file, seen as a storage. +There are several classes of resources, which differ usually in two ways +: the way their data is accessed by applications, and the way they're named +within the system.
  • +
+ +
    For example, when parsing files with the ANSI C library, data has to +be read (through fseek/fread) into intermediate buffers before it can be +decoded. This scheme is highly portable, but rather inefficient; when using +it, we'll describe the file as a disk-based resource. +

    As most modern operating systems now provide memory-mapped files, which +allow direct access while improving performance and reducing memory usage. +Because data can be read directly in memory, we'll speak of a memory-based +resource in this case. For embedded systems (like printers, PDAs, etc..), +ROM-fonts fit into this category as well. +

    Regarding naming, most systems use a string to name files in their storage +hierarchy. Though a typical pathname is an ASCII string ('c:\windows\fonts\times.ttf' +on Windows, '/home/fonts/times.ttf' on Unix), some OSes use different +schemes, varying from Unicode character strings to file i-node numbers. +These details are platform-specific and must be hidden to the rest of the +library in resource objects. +

    A resource encapsulates the lowest details regarding a file, though +it should have NO STATE. Note that the nature or type of a resource (i.e. +disk or memory based) is important to the "stream" component only. The +rest of the library and font drivers work transparently from their implementation. +

    Note also that it is perfectly possible to mix resources of distinct +natures in a single build

+ +
    +
  • +a "stream" is an object which is used to extract bytes from a resource. +Only resource objects can create streams, through its Open_Stream() +method. A stream has state, which typically consist of a file "cursor", +some intermediate buffers, a "current frame" and, of course, methods used +to extract the data from streams, resolving endianess and alignement issues.
  • +
+Data can be extracted from streams through direct reads, or through the +use of frames. A frame models a run of contiguous bytes starting +from the current stream position, and of liberal size. +

Methods exist to extract successive integers of any sizes, while resolving +endianess and alignement issues. Rather than a long rethorical explanation, +here's how frames are typically used : +

{ +
  … +
  FT_Error  error; +

  error = FT_Access_Frame( stream, 14 ); +
  if (error) goto Fail; +

  val1 = FT_Get_Short(stream); +
  val2 = FT_Get_Long(stream); +
  val3 = FT_Get_Long(stream); +
  val4 = FT_Get_Long(stream); +

  FT_Forget_Frame(stream); +
  … +
}

+This code does the following : +
+
    +
  1. + first, it "loads" the next 14 bytes from the current cursor position +into the stream's frame, using the FT_Access_Frame API. An error +is returned if, for example, less than 14 bytes are left in the stream +when the call occurs..
  2. +
+ +
    +
  1. + it extract four integers (one 16-bit short, three 32-bit longs) from +the frame using FT_Get_Short and FT_Get_Long. These function +increment the frame's cursor finally, it "releases" the stream's frame.
  2. +
+ +
    +
  1. + Each stream has its own frame which can be accessed independently, +however, nested frame accesses are not allowed. Note also that the bytes +are effectively read from the stream on the call to FT_Access_Frame. +Any subsequent read will occur after these 14 bytes, even if less are extracted +through FT_Get_xxxx functions.
  2. +
+
+The implementation of the resource class is located in the system component +(i.e. "arch/<system>/ftsys.c") and can thus be tailored +for a specific port of the engine. +

A resource can be created through the FT_New_Resource API; +however this function only accepts an 8-bit pathname to name the target +font file, which may be inappropriate for systems using a different naming +scheme (e.g. UTF-16 pathname, i-node number, etc..). It's up to the porter +then to provide its own resource creation function (like. FT_New_UTF16_Resource, +for example) in its version of "ftsys.c". +

Note that FT_New_Resource will fail and return an error code +if the font file cannot be found, or when its font format isn't recognized +by one of the drivers installed in the library. The list or resources created +for a given library instance is thus the list of "installed font files". +
 

+ +

+3. Stream Manager :

+ +
As said before, resources do not bear states, while streams +do. Stream creation is also a very lengthy process, depending on the target +operating system (e.g. "fopen" is usually very slow). +

Because a typical font driver will want to use a new stream on each +access to individual glyphs, being able to cache the most recently used +streams is a requirement in order to avoid considerable performance penalties. +

Stream caching is thus implemented in the "ftstream" component. +It maintains a simple LRU list of the least recently used streams. Each +stream in the cache is still opened and available for immediate processing. +When a resource is destroyed, the stream cache is parsed to remove all +related cached streams. +

Stream caching can also be disabled with a configuration macro when +using only ROM based resources (where stream opening is really quick). +It is implemented through a Stream Manager object (see ftstream.c). +
 

+ +

+4. Raster :

+ +
The raster is the component is charge of generating bitmaps +and anti-aliased pixmaps from vectorial outline definitions. It is also +sometimes called the scan-line converter. It has been completely rewritten +for FreeType 2.0 in order to support third-order bezier arcs, 17-levels +anti-aliasing (through 4x4 sub-sampling), improved performance, as well +as stand-alone compilation (in order to include it in other graphics package +without requiring the rest of the FreeType engine). +

Because it was designed for easy re-use and embedded systems, the raster +is a rtaher 'unusual' piece of code, because it doesn't perform a single +memory allocation, nor contain any static or global variable. Rather, it +is up to client applications to allocate a raster object in their own heap +or memory space. +

Each raster object also needs a rather large block of memory called +its render pool. The pool is used during rendering (and only during it) +in order to perform the scan-line conversion. Because it accesses and manages +data directly within the pool, the raster yelds impressive performance +as well as bounded memory consumption. It can also automatically decompose +large requests into smaller individual sub-tasks. +

Finally, it never creates bitmaps or pixmaps, but simply renders into +them (providing clipping too). These must be described to the raster with +the help of a FT_Raster_Map structure (a very simple bitmap/pixmap +descriptor). +

Note that when rendering anti-aliased pixmaps, the raster doesn't use +an intermediate bitmap buffer, as filtering is part of the scan-line conversion +process. +
 

+ +

+5. Library objects :

+ +
A library object models a single instance of the FreeType engine. +This is useful when FreeType is compiled as a shared object (DLL), as it +can then be used by several applications, each with its own resources and +objects. +

The FT_Library type is an opaque handle to a library object. +Such an object is created through a call  to FT_Init_FreeType. +Once you don't need it anymore, one can destroy a library object through +FT_Done_FreeType. +

Note that in reentrant builds, several threads can access a single library +object concurrently. Such a build can be chosen by switching one configuration +macro in the file 'arch/<system>/ftconfig.h'

+ +

+6. Driver objects :

+ +
A driver object models an instance of a given font driver, +i.e. an element of FreeType code in charge of handling a given font format, +like TrueType, Type1, FNT, PCF, etc.. +

Each library object contains a given set of driver objects when it is +created through FT_Init_FreeType, this set being determined at compile +time (see the file 'base/ftapi.c'). However, removing or adding drivers +is possible at run-time, in order to make upgrades easy.

+ +

+7. Diagram

+ +
This diagram show the object relationships for the sole base +layer. The library object is the root of the object graph : +
+

+ +

It can be read as follows : +
  +

    +
  • +Each library object has one system, one raster and one stream manager objects. +These objects can only belong to one given library.
  • +
+ +
    +
  • +Each library contains one list of 0 or more resources, as well as one list +of 0 or more driver objects.
  • +
+ +
    +
  • +Each stream manager holds a bounded list ("0..n" where 'n' is the stream +cache's size) of stream objects. Each stream is related to one given resource +object. Each resource may be related to zero or one stream.
  • +
+ +
    +
  • +Each resource is related to one driver object. A driver is related to 0 +or more resources.
  • +
+
+
+ +


+


+

+IV. Font objects :

+ +
Font objects are used to directly map the information found +in font files into several categories : +
  +

+1. Face objects :

+ +
Face objects are used to model individual font faces. They +encapsulate data which isn't related to a specific character size, or a +specific glyph or glyph set. Usually, this means : +
    +
  • +the font face's family and style names (e.g. "Palatino" + "Regular")
  • + +
  • +some flags indicating which kind of font this is (scalable or fixed ? fixed-width +or proportional ? horizontal or vertical ? etc…)
  • + +
  • +the number of glyphs, charmaps and eventually fixed character sizes (for +bitmap formats) found in the font face.
  • + +
  • +for scalable formats, some important metrics like the ascender, descender, +global font bounding box, maximum advance width, etc.. expressed in notional +font/grid units (as well as the number of units on the EM grid).
  • +
+A face is created from a resource object, with the FT_New_Face +API. Each driver contains a list of opened face objects for the resources +it manages. When a driver is removed or destroyed, all its child faces +are discarded automatically with it.
+ +

+2. Size objects :

+ +
Size objects are used to model a given character dimension +for a given device resolution (which really means a given character pixel +dimensions). +

Each size object is created from a parent face object. The object can +be reset to new dimensions at any time. Each face object holds a list of +all its child sizes, these are destroyed automatically when the face object +is discarded. +

The metrics contains metrics, expressed in pixels, for the ascender, +descender, maximum advance width, etc.. +
 

+ +

+3. Glyph Slot objects :

+ +
A glyph slot is a container where one can load individual glyphs, +be they in vector of bitmap format. Each slot also contains metrics for +the glyph it contains. +

Each face object contains one or more glyph slot object : the first +glyph slot is created automatically with its parent face, and it is possible +to add new glyph slots (this is rarely used outside of debugging purposes). +
 

+ +

+4. CharMap objects :

+ +
A charmap object is a sort of dictionary whose task is to translate +character codes in a given character encoding (like ShiftJIS, Unicode, +ANSI, etc..) into glyph indexes in a given font face. +

A face object contains one or more charmap objects. All charmap objects +are created when the parent face is created, though they're not directly +visible to client applications (rather, they can be enumerated through +FT_Get_First_CharMap and FT_Get_Next_CharMap, or more simply picked adequately +with FT_Find_CharMap for a set of given encodings). +
 

+ +

+5. Diagram

+ +
The following diagram illustrates the relationships between +font objects : +
+

+ +

Which can be read as : +
  +

    +
  • +each resource may have zero or more child face objects "opened" for it. +The number of faces is bounded by the number of font faces within the font +resource.
  • +
+ +
    +
  • +each driver holds a list of all the faces opened for the resources it manages. +When the driver is removed, its child faces are discarded automatically.
  • +
+ +
    +
  • +each face object has one single parent resource, and one single driver.
  • +
+ +
    +
  • +each face has one or more charmaps, and one or more glyph slots
  • +
+ +
    +
  • +each face holds a list of zero or more child size objects
  • +
+ +
    +
  • +each charmap, glyph slot and size is related to one given parent face. +These objects are destroyed automatically when the parent face is discarded.
  • +
+
+
+ +


+


+

+V. Driver Interface :

+ +
A font driver is added to a given library object through the +FT_Add_Driver +API. This function receives a structure known as a FT_DriverInterface, +which describes the driver's basic properties. +

The FT_DriverInterface contains a set of function pointers +used for the base FreeType functionalities. However, each driver can also +provide a font-format-specific extended interface to allow client applications +to use more advanced features. +
  +

+1. Common Interface

+ +
The structure of FT_DriverInterface is rather simple, +and defined in "base/ftdriver.h". It must be well known by any +developer who wants to write a new driver for the engine. We advise reading +the FreeType Driver HowTo as well as the source code of existing +drivers. Source comments.
+ +

+2. Driver-specific extensions

+ +
The field of the FT_DriverInterface structure is a +typeless pointer to a format-specific interface. This extended interface +is usually a structure containing function pointers as well as other kind +of information related to the driver. +

It is assumed that client applications that wish to use the driver-specific +extensions are able to #include the relevant header files to understand +the format-specific interface structure.

+
+ +
+

+VI. Configuration:

+ +
This section relates to the configuration of the FreeType library. +By configuration, we mean selection of build options as well as the choice +of font drivers to be used for each new library object. +
  +

+1. Configuration files :

+ +
A single file is used to configure the FreeType base engine. +As it is considered system-specific, it is located in the architecture +directories of the library, under the name "arch/<system>/ftconfig.h". +Note that the same directory should also contain a platform-specific implementation +of "ftsys.c". +

The configuration files is a simple C header which is included by the +engine's sources during compilation. It is not included in "freetype.h", +and hence doesn't need to be copied when installing the FreeType headers +on your system. +

It is made of a series of #define or #undef statements, which are used +to select or turn off a specific option. Each option is documented with +heavy comments, and some of them are explained below.

+ +

+2. Building and Makefiles :

+ +
FreeType 2.0 is more complex than its 1.x release. In order +to facilitate maintenance, as well as ease considerably the writing of +new font drivers, only GNU Make is supported with FreeType 2.0. +However, it is possible to use any compiler, as well as any object or library +prefix (.o, .obj, .a, .lib etc..) with them. +

To build FreeType 2.0, one has to be in the library directory, then +invoke its platform-specific makefile. For a Unix system, this would be +: +

+
% cd freetype2/lib +
% make -f arch/unix/Makefile +

where 'make' is really GNU Make !

+
+The system-specific Makefile located in 'arch/<system>' +is a tiny file used to define several variables. It then includes the file +freetype2/lib/Makefile.lib, +which contains all the gory details about library compilation. The system-specific +Makefile can be very easily modified to accomodate a new compiler/platform +(see the comments within one of these files). +

Each font driver is located in a directory like "freetype2/lib/drivers/<formatdir>". +For example, the TrueType driver is located in "drivers/truetype". +Each driver directory must contain a Makefile which will be included +by Makefile.lib. The former is used to define and build driver +object files. +
  +


+

+

+
+ +

+3. Make options :

+ +
The base layer, as well as each font driver, are made up of +several C sources. Traditionally, one compiles each source (i.e. '.c' +file) into an object ('.o' or '.obj') file, and all of +them are grouped into a library file (i.e. '.a' or '.lib'). +

By default, FreeType takes a slightly different approach when it comes +to compiling each part of the engine. Usually, a single tiny source is +compiled, which includes all other component sources. This results in a +single object files, with the benefits or reduced code size, usually better +compilation as well as a drastic reduction of the number of symbols exported +by the library. Of course, it is made possible through the use of specific +declaration macros in the FreeType source (see the definition of LOCAL_DEF +and LOCAL_FUNC in ftconfig.h for details). +

For a concrete example, see the source code in "base/ftbase.c" +which generates the whole base layer in a single object file. The same +build process is applied to font drivers, in order to generate one single +object file per given font format (e.g. truetype.o, type1.o, +etc..). +

Compiling the library and drivers in "normal" mode is possible, through +the use of the 'multi' target (which really means « multiple +objects »). For example, calling : +

% make -f arch/ansi/Makefile multi
+Will build the FreeType library by compiling each source file to an individual +object, then linking them together. You'll notice that the library is significantly +bigger in this case. Creating a shared dll from a 'multi' build is certainly +a very poor idea, as this will export a huge quantity of symbols that aren't +useful to any client application.
+ +

+4. Adding a driver at compile time

+ +
A driver can be included very easily in the build process by +including its Makefile in Makefile.lib. For example, +the TrueType driver is simply included with the following lines (see Makefile.lib): +
# TrueType driver rules +
# +
include $(DRIVERS_DIR)/truetype/Makefile
+ +


Where DRIVERS_DIR really is "freetype2/lib/drivers", +though this can be redefined. You can, of course specify a different path +if you want to place your driver sources in another location. +

Note that this only adds the driver's object files to the generated +library file. A few more steps are needed to make your FT_Library +objects use the driver. They consist in modifying the file "base/ftinit.c", +whose sole purpose is to define the set of driver objects that are to be +created with each new library object. +
 

+ +

+5. Adding a driver at run time

+ +
New driver objects can be added at run-time through the FT_Add_Driver +API. This function takes a handle to an existing library object, as well +as a pointer to a given driver interface. This interface is used to create +a new driver object and register it within the library. +

Similarly, a single driver can be removed from a library anytime through +FT_Remove_Driver. +This will automatically discard the resources and face objects managed +by the driver.

+ +

+6. Custom library objects :

+ +
Finally, it is possible to build custom library objects. You +need to pass a handle to a valid FT_System object to the FT_Build_Library +API. The function will return a handle to the new fresh library object. +Note that the library has no registered drivers after the call, developers +have to add them by hand with FT_Add_Driver. +

It is thus possible to create two distinct library objects with distinct +FT_System +implementations in the same session, which can be useful for debugging +purpose.

+ +
 
+ + + diff --git a/reactos/subsys/win32k/freetype/docs/design/io-frames.html b/reactos/subsys/win32k/freetype/docs/design/io-frames.html new file mode 100644 index 00000000000..a5c6de7cdbf --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/io-frames.html @@ -0,0 +1,343 @@ + + + + + + FreeType 2 Internals - I/O Frames + + + + +

+ FreeType 2.0 I/O Frames +

+ +

+ © 2000 David Turner + (david@freetype.org)
+ © 2000 The FreeType Development Team + (www.freetype.org) +

+ +
+ + +
+ +
+ +

+ Introduction +

+ +

This document explains the concept of I/O frames as used in the + FreeType 2 source code. It also enumerates the various functions and + macros that can be used to read them.

+ +

It is targeted to FreeType hackers, or more simply to developers who + would like a better understanding of the library's source code.

+ +
+ +

+ I. What frames are +

+ +

Simply speaking, a frame is an array of bytes in a font file that is + `preloaded' into memory in order to be rapidly parsed. Frames are useful + to ensure that every `load' is checked against end-of-file overruns, and + provides nice functions to extract data in a variety of distinct + formats.

+ +

But an example is certainly more meaningful than anything else. The + following code

+ + +
+    error = read_short( stream, &str.value1 );
+    if ( error ) goto ...
+
+    error = read_ulong( stream, &str.value2 );
+    if ( error ) goto ...
+
+    error = read_ulong( stream, &str.value3 );
+    if ( error ) goto ...
+
+ +

can easily be replaced with

+ + +
+    error = FT_Access_Frame( stream, 2 + 4 + 4 );
+    if ( error ) goto ...
+
+    str.value1 = FT_Get_Short( stream );
+    str.value2 = FT_Get_ULong( stream );
+    str.value3 = FT_Get_ULong( stream );
+
+    FT_Forget_Frame( stream );
+
+ +

Here, the call to FT_Access_Frame() will

+ +
    +
  • +

    Ensure that there are at least 2+4+4=10 bytes left in the + stream.

    +
  • +
  • +

    `Preload' (for disk-based streams) 10 bytes from the current + stream position.

    +
  • +
  • +

    Set the frame `cursor' to the first byte in the frame.

    +
  • +
+ +

Each FT_Get_Short() or FT_Get_ULong() call + will read a big-endian integer from the stream (2 bytes for + FT_Get_Short(), 4 bytes for FT_Get_ULong) + and advance the frame cursor accordingly.

+ +

FT_Forget_Frame() `releases' the frame from memory.

+ +

There are several advantages to using frames:

+ +
    +
  • +

    Single-check when loading tables.

    +
  • +
  • +

    Making code clearer by providing simple parsing functions + while keeping code safe from file over-runs and invalid + offsets.

    +
  • +
+ +
+ +

+ II. Accessing and reading a frame with macros +

+ +

By convention in the FreeType source code, macros are able to use two + implicit variables named error and stream. This is + useful because these two variables are extremely often used in the + library, and doing this only reduces our typing requirements and make the + source code much clearer.

+ +

Note that error must be a local variable of type + FT_Error, while stream must be a local variable or + argument of type FT_Stream.

+ +

The macro used to access a frame is ACCESS_Frame(_size_), it will + translate to

+ + +
+    ( error = FT_Access_Frame( stream, _size_ ) )
+        != FT_Err_Ok
+
+ +

Similarly, the macro FORGET_Frame() translates to

+ + +
+    FT_Forget_Frame( stream )
+
+ +

Extracting integers can be performed with the GET_xxx() + macros, like

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Macro name + + Translation + + Description +
+ GET_Byte() + + FT_Get_Byte(stream) + +

Reads an 8-bit unsigned byte.

+
+ GET_Char() + + (FT_Char)
+ FT_Get_Byte(stream)
+
+

Reads an 8-bit signed byte.

+
+ GET_Short() + + FT_Get_Short(stream) + + Reads a 16-bit signed big-endian integer. +
+ GET_UShort() + + (FT_UShort)
+ FT_Get_Short(stream)
+
+ Reads a 16-bit unsigned big-endian integer. +
+ GET_Offset() + + FT_Get_Offset(stream) + + Reads a 24-bit signed big-endian integer. +
+ GET_UOffset() + + (FT_UOffset)
+ FT_Get_Offset(stream)
+
+ Reads a 24-bit unsigned big-endian integer. +
+ GET_Long() + + FT_Get_Long(stream) + + Reads a 32-bit signed big-endian integer. +
+ GET_ULong() + + (FT_ULong)
+ FT_Get_Long(stream)
+
+ Reads a 32-bit unsigned big-endian integer. +
+ +

(Note that an Offset is an integer stored with 3 bytes on + the file.)

+ +

All this means that the following code

+ + +
+    error = FT_Access_Frame( stream, 2 + 4 + 4 );
+    if ( error ) goto ...
+
+    str.value1 = FT_Get_Short( stream );
+    str.value2 = FT_Get_ULong( stream );
+    str.value3 = FT_Get_ULong( stream );
+
+    FT_Forget_Frame( stream );
+
+ +

can be simplified with macros:

+ + +
+    if ( ACCESS_Frame( 2 +4 + 4 ) ) goto ...
+
+    str.value1 = GET_Short();
+    str.value2 = GET_ULong();
+    str.value3 = GET_ULong();
+
+    FORGET_Frame();
+
+ +

Which is clearer. Notice that error and stream + must be defined locally though for this code to work!

+ +
+ +

+ III. Alternatives +

+ +

It is sometimes useful to read small integers from a font file without + using a frame. Some functions have been introduced in FreeType 2 to + do just that, and they are of the form FT_Read_xxxx.

+ +

For example, FT_Read_Short(stream, + &error) reads and returns a 2-byte big-endian integer from a + stream, and places an error code in the error + variable.

+ +

Thus, reading a single big-endian integer is shorter than using a frame + for it.

+ +

Note that there are also macros READ_xxx() which translate to

+ + +
+    FT_Read_xxx( stream, &error ), error != FT_Err_Ok
+
+ +

and can be used as in

+ + +
+    if ( READ_UShort( variable1 ) ||
+         READ_ULong ( variable2 ) )
+      goto Fail;
+
+ +

if error and stream are already defined + locally.

+ +
+
+ + + diff --git a/reactos/subsys/win32k/freetype/docs/design/library-compilation.png b/reactos/subsys/win32k/freetype/docs/design/library-compilation.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/library-compilation.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/design/logo1.png b/reactos/subsys/win32k/freetype/docs/design/logo1.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/logo1.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/design/objects_diagram.png b/reactos/subsys/win32k/freetype/docs/design/objects_diagram.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/objects_diagram.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/design/objects_diagram2.png b/reactos/subsys/win32k/freetype/docs/design/objects_diagram2.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/objects_diagram2.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/design/platform-detection.png b/reactos/subsys/win32k/freetype/docs/design/platform-detection.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/platform-detection.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/design/system-interface.html b/reactos/subsys/win32k/freetype/docs/design/system-interface.html new file mode 100644 index 00000000000..c505bbe5923 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/design/system-interface.html @@ -0,0 +1,258 @@ + + + + + + + FreeType 2 Internals + + + + + +
+

+FreeType 2.0 System Interface

+ +
+

+© 2000 David Turner (david@freetype.org)
+© 2000 The FreeType Development Team (devel@freetype.org)

+ +


+


+
  +

Introduction:

+
    + This document explains how the FreeType 2 library performs the low-level and + system-specific operations of memory management and i/o access. It is targetted + to FreeType hackers, porters and "advanced" developers who want special + features like providing their own memory manager or streams. +

    + Note that the only system-specific part of the library is a file + named "ftsystem.c", normally located in the directory + "freetype2/config/<system>" where <system> designates + your platform (e.g. "config/ansi/ftsystem.c" or + "config/unix/ftsystem.c"). +

    +

+ +

+


+

+ +

I. Memory Management

+
    + Memory allocation and releases are performed through a FT_Memory object in + FreeType. A FT_Memory is nothing more than a table of functions plus + an arbitrary user data field. It is defined in the file + "freetype2/include/ftsystem.h" and has the following structure: +

    +

      + typedef struct
      + { +
        + +
        void* user // a user-defined pointer. This is zero by default +
        void* (*alloc)( FT_System, int) // a function used to allocate a new block +
        void* (*realloc)( FT_System, int, int, void* ) // a function used to reallocate a given block +
        void (*free)( FT_System, void*) // a function used to release a given block +
        +
      + } FT_MemoryRec, *FT_Memory;
      +
    +

    + You'll notice that:

    +

      +
    • The FT_Memory type is really a pointer to a FT_MemoryRec. + This is a normal convention for the FreeType code. +
    • The realloc takes two integer arguments. The first one is the + current block size, the second one its new size. +
    +

    + + All current implementations of "ftsystem.c" provide a very simple + implementation of the FT_Memory interface by calling directly the + standard C alloc, realloc and free. +

    + The FreeType source code never invokes directly the function pointers. Rather, + it calls FT_Alloc, FT_Realloc and FT_Free functions + which are defined in "freetype2/src/base/ftobjs.c". These will not be + discussed here. +

    + If you want to use your own memory allocator rather than the one provided + by your build of FreeType, follow these simple steps:

    +

      +
    1. Create your own FT_Memory object, with pointers that map to + your own memory management routines (beware function signatures though). +

      +

    2. Call FT_Build_Library(memory,&library). This will create a new + FT_Library object that uses your own FT_Memory exclusively. + Note however that this library has no font drivers loaded in !! +

      +

    3. Load the default font drivers into the new library, either by + calling FT_Default_Drivers(library), or by adding them manually + through repeated calls to FT_Add_Driver(library,&driver_interface) +

      +

    + This will replace the FT_Init_FreeType(&library) call that an application + must do to initialise one library instance. +

    + Notice that you don't need to recompile FreeType 2 to use your own memory + manager !!. +

    +

+ +

+


+

+ +

II. Streams

+
    +

    1. Basic Stream Structure

    +

    + A stream models the array of bytes found in a font file. FreeType 2 separates + streams into two families :

    +

      +
    • memory-based streams:
      + when the stream's content is entirely found in memory. This is the + case for ROM font files, or memory-mapped files. +

      +

    • disk-based streams:
      + when the stream isn't directly accessible in memory. This is the + case for local or remote files. +

      +

    +

    + Note that a stream's nature only determines how FreeType accesses its content, not + the way it is effectively stored. For example, in the case of a compressed font file, + one implementation may choose to uncompress the font in memory, then provide a memory + based stream to access it. Another one might chose a disk based stream to perform + on-the-fly decompression of the font data. Similarly, the font file can be stored + on a local disk, or obtained from a network. This will be completely transparent to + FreeType. +

    + The stream structure is: +

    +

      + typedef struct
      + {
      +
        +
        char* base for memory-based streams, the address + of its first byte. + +
        ulong size the stream's size in bytes. + +
        ulong pos the current stream position in the file + +
        descriptor a union field used to hold either an + integer file descriptor or pointer. + This field is not used by FreeType + itself, but is left to implementations + of "ftsystem" +
        pathname a union field that can hold either an + integer or pointer. It is not used by + FreeType itself, but is left to + implementations. These can put the + file pathname's during debugging for + example. + +
        read a pointer to a function used to seek the + stream and/or read a run of bytes from it. + +
        close a pointer to a function called when the + stream is closed. + +
        memory a FT_Memory object, which is used + to allocate frames for disk-based streams. + This field is set and used by FreeType. + +
        cursor a pointer in memory used when accessing + frames. This is set and used by FreeType. + +
        limit a pointer in memory used when accessing + frames. This is set and used by FreeType. +
      + } FT_StreamRec, *FT_Stream +
    +

    + + The following important things must be noticed here:

    +

      +
    • The FT_Stream type is really a pointer to a FT_StreamRec. + This is a normal convention for the FreeType source. +

      + +

    • When the read field is non NULL, the stream is considered to be + disk-based. Otherwise, the stream is memory-based, and the base + field must be set by "ftsystem.c" when the stream is + created. +

      + +

    • The base field must be set to 0 when a disk-based stream is created. + However, this field will later be set and used by the FreeType library when + accessing frames of bytes within the font file (of course, this doesn't + happen with memory-based streams). +
    + +

    2. Stream lifecyles

    +

    + Each FT_Face needs its own stream to access font data. The most common + way to create a new FT_Stream object is to call the function + FT_New_Face. This function takes a file pathname argument that + is used to create a new stream object. +

    + This is possible because each implementation of "ftsystem.c" provides + a function called FT_New_Stream which takes a file pathname and a + FT_Stream pointer as an argument. The function simply opens the file + and initialises the stream structure accordingly. It is called by FT_New_Face + to create the face's stream object. +

    + A stream is only closed when the face is destroyed through FT_Done_Face. + Its close field function will then be called. Note that the function should + never destroy the FT_Stream. +

    + + +

    3. Using your own streams

    +

    + There are cases where it is interesting to provide your own stream to create + a new face object, rather than rely on the default implementation. For example, + a filepathname, which is a C string, might not be useful on a system where files + are named with a UTF-16 string or via an i-node number of memory address (for ROM files). +

    + For this purpose, the FT_Open_Face is defined. It simply takes a + FT_Stream pointer as its second argument, instead of a file pathname (the + stream must be allocated and initialised by you, so be careful). +

    + Actually, the only thing that FT_New_Face does is create a new stream + through FT_New_Stream, then call FT_Open_Face to create the + face with it. +

    + Note also that you can use the function FT_New_Memory_Face to create + a new font face for a memory-based font file, whose address and size can be passed + as arguments. The function automatically creates the corresponding memory-based + stream and use it to create the face. +

    + +

+ + +

+


+

+ +

III. Thread synchronisation

+
    + The FreeType library uses no static data. It can be used concurrently by two + thread as long as each one uses its own FT_Library instance. Otherwise, + one can very simply synchronize access to a single library instance by using a + mutex to protect each call to one of FreeType's API functions. +

    +

+ + diff --git a/reactos/subsys/win32k/freetype/docs/docmaker.py b/reactos/subsys/win32k/freetype/docs/docmaker.py new file mode 100644 index 00000000000..5a6ea0e7baa --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/docmaker.py @@ -0,0 +1,516 @@ +#!/usr/bin/env python +# +# DocMaker is a very simple program used to generate HTML documentation +# from the source files of the FreeType packages. +# + +import fileinput, sys, string + +# This function is used to parse a source file, and extract comment blocks +# from it. The following comment block formats are recognized : +# +# /************************** +# * +# * FORMAT1 +# * +# * +# * +# * +# *************************/ +# +# /**************************/ +# /* */ +# /* FORMAT2 */ +# /* */ +# /* */ +# /* */ +# /* */ +# +# /**************************/ +# /* */ +# /* FORMAT3 */ +# /* */ +# /* */ +# /* */ +# /* */ +# /**************************/ +# +# Each block is modeled as a simple list of text strings +# The function returns a list of blocks, i.e. a list of strings lists +# + +def make_block_list(): + """parse a file and extract comments blocks from it""" + + list = [] + block = [] + format = 0 + + for line in fileinput.input(): + + line = string.strip(line) + l = len(line) + + if format == 0: + if l > 3 and line[0:3] == '/**': + i = 3 + while (i < l) and (line[i] == '*'): + i = i+1 + + if i == l: + # this is '/**' followed by any number of '*', the + # beginning of a Format 1 block + # + block = []; + format = 1; + + elif (i == l-1) and (line[i] == '/'): + # this is '/**' followed by any number of '*', followed + # by a '/', i.e. the beginning of a Format 2 or 3 block + # + block = []; + format = 2; + + ############################################################## + # + # FORMAT 1 + # + elif format == 1: + + # if the line doesn't begin with a "*", something went + # wrong, and we must exit, and forget the current block.. + if (l == 0) or (line[0] != '*'): + block = [] + format = 0 + + # otherwise, we test for an end of block, which is an + # arbitrary number of '*', followed by '/' + else: + i = 1 + while (i < l) and (line[i] == '*'): + i = i+1 + + # test for the end of the block + if (i < l) and (line[i] == '/'): + if block != []: list.append( block ) + format = 0 + block = [] + + else: + block.append( line[1:] ) + + ############################################################## + # + # FORMAT 2 + # + elif format == 2: + + # if the line doesn't begin with '/*' and end with '*/', + # this is the end of the format 2 format.. + if (l < 4 ) or (line[:2] != '/*') or (line[-2:] != '*/'): + if block != []: list.append(block) + block = [] + format = 0 + continue + + # remove the start and end comment delimiters, then right-strip + # the line + line = string.rstrip(line[2:-2]) + + # check for end of a format2 block, i.e. a run of '*' + if string.count(line,'*') == l-4: + if block != []: list.append(block) + block = [] + format = 0 + else: + # otherwise, add the line to the current block + block.append(line) + + return list + + +# This function is only used for debugging +# +def dump_block_list( list ): + """dump a comment block list""" + for block in list: + print "----------------------------------------" + for line in block: + print line + print "---------the end-----------------------" + + + + + +###################################################################################### +# +# +# The DocParagraph is used to store either simple text paragraph or +# source code lines +# +# +# If the paragraph contains source code (use code=1 when initializing the +# object), self.lines is a list of source code strings +# +# Otherwise, self.lines is simply a list of words for the paragraph +# +class DocParagraph: + + def __init__(self,code=0,margin=0): + self.lines = [] + self.code = code + self.margin = margin + + def add(self,line): + + if self.code==0: + # get rid of unwanted spaces in the paragraph + self.lines.extend( string.split(line) ) + + else: + # remove margin whitespace + if string.strip( line[:self.margin] ) == "": line = line[self.margin:] + self.lines.append(line) + + + def dump(self): + + max_width = 50 + + if self.code == 0: + cursor = 0 + line = "" + + for word in self.lines: + + if cursor+len(word)+1 > max_width: + print line + cursor = 0 + line = "" + + line = line + word + " " + cursor = cursor + len(word) + 1 + + if cursor > 0: + print line + + else: + for line in self.lines: + print "--" + line + + print "" + + +###################################################################################### +# +# +# The DocContent class is used to store the content of a given marker +# Each DocContent can have its own text, plus a list of fields. Each field +# has its own text too +# +# Hence, the following lines : +# +# """ +# Some arbitraty text: +# +# fieldone :: some arbitraty text for this field, +# note that the text stretches to several lines +# +# fieldtwo :: some other text +# +# """ +# +# will be stored as (each text is a list of string: +# +# self.fields = [ "", "fieldone", "fieldtwo" ] +# self.texts = [ +# [ "some arbitraty text for this field," , +# "note that the text stretches to several lines" ], +# +# [ "some other text" ] +# ] +# +# +class DocContent: + + def __init__(self, paragraph_lines=[]): + + self.fields = [] + self.texts = [] + + code_mode = 0 + code_margin = 0 + + field = "" + text = [] + paragraph = None + + for aline in paragraph_lines: + + if code_mode == 0: + line = string.lstrip(aline) + l = len(line) + margin = len(aline) - l + + # if the line is empty, this is the end of the current + # paragraph + if line == "": + if paragraph: + text.append(paragraph) + paragraph = None + continue + + # test for the beginning of a code block, i.e.'{' is the first + # and only character on the line.. + # + if line == '{': + code_mode = 1 + code_margin = margin + if paragraph: + text.append(paragraph) + paragraph = DocParagraph( 1, margin ) + continue + + words = string.split(line) + + # test for a field delimiter on the start of the line, i.e. + # the oken `::' + # + if len(words) >= 2 and words[1] == "::": + if paragraph: + text.append(paragraph) + paragraph = None + + self.fields.append(field) + self.texts.append(text) + + field = words[0] + text = [] + words = words[2:] + + if len(words) > 0: + line = string.join(words) + if not paragraph: + paragraph = DocParagraph() + paragraph.add( line ) + + else: + line = aline + + # the code block ends with a line that has a single '}' on it + if line == " "*code_margin+'}': + text.append(paragraph) + paragraph = None + code_mode = 0 + code_margin = 0 + + # otherwise, add the line to the current paragraph + else: + paragraph.add(line) + + if paragraph: + text.append(paragraph) + + self.fields.append( field ) + self.texts.append( text ) + + + + def dump(self): + for i in range(len(self.fields)): + field = self.fields[i] + if field: print "" + + for paras in self.texts[i]: + paras.dump() + + if field: print " " + + def dump_html(self): + n = len(self.fields) + for i in range(n): + field = self.fields[i] + if field==[]: + print "

" + for paras in self.texts[i]: + print "

" + paras.dump() + print "

" + else: + if i==1: + print "" + if n > 1: + print "
" + else: + print "
" + + print ""+field+"" + + for paras in self.texts[i]: + print "

" + paras.dump() + print "

" + + print "
" + + +###################################################################################### +# +# +# The DocBlock class is used to store a given comment block. It contains +# a list of markers, as well as a list of contents for each marker. +# +# +class DocBlock: + + def __init__(self, block_line_list=[]): + self.markers = [] + self.contents = [] + + marker = "" + content = [] + alphanum = string.letters + string.digits + "_" + + for line in block_line_list: + line2 = string.lstrip(line) + l = len(line2) + margin = len(line) - l + + if l > 3 and line2[0] == '<': + i = 1 + while i < l and line2[i] in alphanum: i = i+1 + if i < l and line2[i] == '>': + if marker or content: + self.add( marker, content ) + marker = line2[1:i] + content = [] + line2 = string.lstrip(line2[i+1:]) + l = len(line2) + line = " "*margin + line2 + + content.append(line) + + if marker or content: + self.add( marker, content ) + + + def add( self, marker, lines ): + + # remove the first and last empty lines from the content list + l = len(lines) + if l > 0: + i = 0 + while l > 0 and string.strip(lines[l-1]) == "": l = l-1 + while i < l and string.strip(lines[i]) == "": i = i+1 + lines = lines[i:l] + l = len(lines) + + # add a new marker only if its marker and its content list aren't empty + if l > 0 and marker: + self.markers.append(marker) + self.contents.append(lines) + + def dump( self ): + for i in range( len(self.markers) ): + print "["+self.markers[i]+"]" + for line in self.contents[i]: + print "-- "+line + + def doc_contents(self): + contents = [] + for item in self.contents: + contents.append( DocContent(item) ) + return contents + + +def dump_doc_blocks( block_list ): + for block in block_list: + docblock = DocBlock(block) + docblock.dump() + print "<<------------------->>" + + +# +# +# +def dump_single_content( block_list ): + + block = block_list[0] + docblock = DocBlock(block) + + print "" + for i in range(len(docblock.markers)): + marker = docblock.markers[i] + contents = docblock.contents[i] + + print "" + doccontent = DocContent( contents ) + + doccontent.dump() + + print "" + + print "" + +def dump_doc_contents( block_list ): + + for block in block_list: + docblock = DocBlock(block) + print "" + + for i in range(len(docblock.markers)): + print "" + content = DocContent( docblock.contents[i] ) + content.dump() + print "" + print "" + +def dump_html_1( block_list ): + + print "" + types = [ 'Type', 'Struct', 'FuncType', 'Function', 'Constant', 'Enumeration' ] + for block in block_list: + docblock = DocBlock(block) + print "
" + for i in range(len(docblock.markers)): + marker = docblock.markers[i] + content = docblock.contents[i] + dcontent = DocContent( content ) + + if marker=="Description": + print "

    " + dcontent.dump() + print "

" + + elif marker in types: + print "

"+content[0]+"

" + else: + print "

"+marker+"

" + print "

    " + dcontent.dump_html() + print "

" + + print "" + + print "
" + + +def main(argv): + """main program loop""" + print "extracting comment blocks from sources .." + list = make_block_list() + +# dump_block_list( list ) + +# dump_doc_blocks( list ) + +# print "dumping block contents .." +# dump_doc_contents(list) + + dump_html_1(list) + +# dump_single_content(list) + +# If called from the command line +if __name__=='__main__': main(sys.argv) diff --git a/reactos/subsys/win32k/freetype/docs/freetype2.html b/reactos/subsys/win32k/freetype/docs/freetype2.html new file mode 100644 index 00000000000..3cc94c9719c --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/freetype2.html @@ -0,0 +1,352 @@ + + +FreeType 2 Introduction + + + + + + + +http://www.freetype.org

+ +

+ + The FreeType Project +

An Introduction to FreeType 2

+
+ +
+

+ +DOCUMENT INDEX:
+

+ + +


+ +
+

What is FreeType 2 ?

+
+ +

The FreeType project is a team of volunteers who develop free, portable +and high-quality software solutions for digital typography. We specifically +target embedded systems and focus on bringing small, efficient and +ubiquitous products.

+ +

the FreeType 2 library is our new software font engine. It has been + designed to provide the following important features:

+ +
    +
  • + A universal and simple API to manage font files:
    +

      +

      The FreeType 2 API is simple and easy to use. It supports both + bitmapped and scalable fonts and is well-suited to manage font + files of all formats. Unlike other font libraries, FreeType 2 + returns and manages outline font data (images & metrics).

      +
    +

  • + +
  • + Support for several font formats through loadable modules:
    +

      +

      FreeType 2 uses "font drivers". Each driver is a loadable + module used to support one specific font format. Each driver can also + provide specific extensions used to access format-specific features of + the font.

      +
    +

  • + + +
  • + High-quality anti-aliasing:
    +

      +

      FreeType 2 produces etremely smooth outlines at small sizes, with its new + anti-aliasing renderer, which produces bitmaps with 256-levels of gray. + It uses a new algorithm that has been specifically designed to render + small complex shapes (like glyphs) at high speed. Indeed, it's even + faster than the monochrome renderer for small character sizes (under + 20 pixels) !! +

      +
    + + +
  • High portability & performance:
    +
      +

      The FreeType 2 source code is written in ANSI C and runs on any + platform with a compliant compiler. Client applications can + provide their own memory manager or input stream to the library + (which means that font files can come from any place: disk, + memory, compressed file, network, etc..). +

      +
    + +
+ +

Note that the beta of FreeType 2 is available now. For more + info, check our Download page or see the source + and its diffs through our CVS Web interface. +

+ + +
+ +
+

Features

+
+ +

Supported font formats

+ +

FreeType 2 readily supports the following font formats:

+ +
    +
  • TrueType files (.ttf) and collections (.ttc)
  • +
  • Type 1 font files both in ASCII (.pfa) or binary (.pfb) format
  • +
  • Type 1 Multiple Master fonts. The FreeType 2 API also provides + routines to manage design instances easily
  • +
  • Type 1 CID-keyed fonts
  • +
  • OpenType/CFF (.otf) fonts
  • +
  • CFF/Type 2 fonts
  • +
  • Adobe CEF fonts (.cef), used to embed fonts in SVG documents + with the Adobe SVG viewer plugin.
  • +
  • Windows FNT/FON bitmap fonts
  • +
+ +

Note that Apple's TrueType GX fonts are supported as normal TTFs, + (the advanced tables are ignored).

+ +

Besides, it's possible to add support for new font formats by providing + a specific font driver module. Modules can be added either at + build time (when recompiling the library), or at run-time; + this allows, for example, applications to register their own + font driver to support program-specific formats.

+ + +

Patent-free automatic hinter

+ +

TrueType fonts are normally renderered (hinted) with the help of a + specific bytecode where the behaviour of a few opcodes is patented by + Apple. We're currently in contact with Apple to discuss the importance + of such patents and their use in open source projects like FreeType. +

+ +

In the meantime, we have developped our own alternative technology that + is capable of automatically hinting scalable glyph images. It is + now part of the FreeType 2 source tree as the "autohint" module, + and is used to hint glyphs when the bytecode interpreter is disabled + (through a configuration macro when building the engine). Note that + the auto-hinter is also used to handle glyphs in other formats like + CFF and Type 1.

+ +

The auto-hinter provides pretty good results (in some cases, it even + significantly improves the output of poorly hinted fonts) but we'll + continue to improve it with each new release of FreeType to achieve + the highest possible quality.

+ + +

Modular design:

+ +

The design of FreeType 2 is extremely modular as most features are + supported through optional modules. This means it's easily possible to + only compile the features you need. As each module is between + 10 and 20 Kb in size, it's possible to build a bare-bones + font engine that supports anti-aliasing in about 30 Kb !!

+ +

Configuration is performed by modifications of only two header + files (one to select global features, another one to select modules) + and don't need tweaking of source code. Note that it is however + possible to provide your own implementation of certain components.

+ +

For example, when building on Unix, the engine will automatically + use memory-mapped files when available on the target platform, + thus significantly increasing font file i/o.

+ + +

Due to its very flexible design, it is possible to add, remove and + upgrade modules at run-time.

+ + + +

Advanced glyph management

+ +

The API comes with a standard extension used to extract individual + glyph images from font files. These images can be bitmaps, scalable + bezier outlines or even anything else. (e.g. bi-color or metafont + glyphs, as long as they're supported by a module).

+ +

Each scalable glyph image can be transformed, measured and + rendered into a monochrome or anti-aliased bitmaps easily + through a uniform interface. + + This allows client applications to easily cache glyphs or + perform text rendering effects with minimal difficulty + (look at the FreeType 2 Tutorial to see how to render + rotated text with very few lines of code). +

+ + + +

Advanced font access

+ +

The FreeType 2 API is useful to retrieve advanced information from + various fonts:

+ +
    +
  • vertical metrics are available whenever found in the font file
  • + +
  • kerning distances are available when found in the font file. It + is also possible to "attach" a given additional file to a given + font face. This is useful to load kerning distances from an + .afm file into a Type 1 face for example.
  • + +
  • provides ASCII glyph names whenever available in the font + (TrueType, OpenType, Type1, etc..)
  • + +
  • provides access to important tables for SFNT-based font formats + (i.e. TrueType, OpenType, CEF, etc..), like the name table, + font header, maximum profile, etc...
  • + +
  • automatic synthesis of Unicode-based character maps for + those fonts or formats that do not provide one. This is + extremely useful with Type 1 fonts which are normally + limited to a stupid 256-characters encoding.
  • +
+ + +

Simple & clean API

+ +

The FreeType 2 high-level API is simple and straightforward, as it + has been specifically designed to make the most commmon font operations + easy

+ +

As a comparison, the number of function calls needed to perform a + the tasks of font face creation/opening and glyph loading/rendering + has been reduced by a factor of 4 !!

+ +

The API is also independent of any font-format specific issue, though + it provides standard extensions to access format-specific tables and + information. More extensions can also be easily added through new + modules

+ + +

Robust & Portable code

+ +

Because it is written in industry-standard ANSI C, FreeType 2 compiles + on all platforms with a compliant compiler. Because the default build + only relies on the C library, it is free of any system-specific + dependencies, even if it is possible to "enhance" certain components + by providing a specific implementation.

+ +

The code doesn't use global or static variables. Client applications + can provide their own memory manager. Font files can be read from + a disk file, memory, or through a client-provided input stream. This + allows to support compressed font files, remote fonts, fonts embedded + in other streams (e.g. Type42 fonts), etc..

+ +

An advanced i/o sub-system is used to optimise file access, as well + as reduce memory usage of the library when the file is memory-based + ( ROM, RAM, memory-mapped ).

+ + +

Open Source & Vendor Independence

+ +

Finally, FreeType 2 is released under its own BSD-like open source + license, one of the less restricting licenses available, and this + means that:

+ +
    +
  • + It can be included in all kinds of products, be they proprietary + or not. +

  • + +
  • + As any module can be added or replaced anytime, any third party + vendor has the ability to provide its own set of modules (under + its own license) in order to support proprietary font formats or + more advanced features (e.g. a new auto-hinter, or a new + anti-aliasing renderer for LCDs or TV screens). +

  • +
+ +

One could even imagine an application using the FreeType 2 API with + a "wrapper" module used to access system-specific fonts (like through + the Windows GDI). This would mean native font support with more portable + application code (as simply changing the wrapper module would be required + to port the application to another system).

+ +
+ +
+

Requirements

+
+ +

FreeType 2 is written in ANSI C and should compile with no problems + on a great variety of platforms. We have taken care of removing all + compilation warnings from major compliant compilers. Detailed compilation + instructions are provided in the software archive.

+ +

This version of the library has been succesfully compiled and run + under the following systems: Dos, OS/2, Windows, Macintosh, Unix + (including the 64-bits DEC Unix, a.k.a. "True64"). You should not + encounter major problems compiling it on any other kind of platform. + In all cases, contact us if you do.

+ +

Note that a small set of demonstration programs is also separately + available. They include a tiny graphics sub-system that is used to + display and show-off the library's capabilities on the following + platforms: X11, MacOS, OS/2 & Windows.

+ +

Please visit our + Download section to access the software archives.

+ + + +
+ +
+

Patents issues

+
+ +

The FreeType 2 source code includes a TrueType bytecode interpreter that + is covered by the Apple patents. However, this piece of code is never + compiled by default in this release (unlike in previous betas) making + a default build of the library entirely patent-free !!

+ +

Note that in order to compile the interpreter, one needs to define + the configuration macro TT_CONFIG_OPTION_BYTECODE_INTERPRETER configuration + macro in the file "ftoption.h". More details are available in + the software archive. Note that the use of the interpreter is normally + protected by US, UK and French patents. In the event you'd absolutely + need it, you may have to contact + Apple legal department for licensing conditions, depending on your + location and the places you distribute/sell your products.

+ +

Please do not ask us any detailed information regarding licensing, as + we're still discussing with Apple this issue, we're unable to inform + the public of what's currently going on..

+ +
+ +


+

+Back to FreeType homepage

+ +

+ + diff --git a/reactos/subsys/win32k/freetype/docs/ft2faq.html b/reactos/subsys/win32k/freetype/docs/ft2faq.html new file mode 100644 index 00000000000..6b9cc9bdb9e --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/ft2faq.html @@ -0,0 +1,502 @@ + + +FreeType 2 FAQ + + + + + + + +http://www.freetype.org

+ +

+ + The FreeType Project +

The FreeType 2 FAQ

+
+ +
+

+ +DOCUMENT INDEX:
+

+ + +


+ +
+

General questions & answers

+
+ + +

I.1. I though the FreeType project was dead. Is this true?

+
    +

    Well, not exactly :-) It's true that the TrueType patents issues + have been less than a graceful event to handle but it didn't not + really killed the project per se, as Apple hasn't made an official + statement yet regarding the use of the patented "technology" in + open source projects (or other products).

    + +

    We have thus continued updating FreeType 1.x, and started developping + FreeType 2 with the idea of providing this time a completely patent + free font engine. However, we largely preferred not to broadly + communicate about it until we've got a satisfying implementation + to show.

    +
+ + +
+

I.2. Why did it take so long to release FreeType 2?

+
+ + +

I.3. Is FreeType 2 a Unix-only project?

+
+ + +

I.4. When will X11/XFree support anti-aliased text?

+
    +

    This question isn't exactly related to FreeType as we have no direct + connection to the XFree people, but we've been asked so frequently + about it that it deserves a prominent place in this FAQ :-)

    + +

    FreeType has been capable of anti-aliasing since version 1.0. The + reason why XFree doesn't support it is directly related to the + limitations of the design and specification of X11. More specifically:

    + +
      +
    • + X11 assumes that all glyph images are monochrome bitmaps, + hence the X font library and server are unable to send anything + else to the X server. +

    • + +
    • + Even if the X font library/server was able to generate anti-aliased + bitmaps (and this has been already done through extensions), the X + rendering model doesn't allow translucent composition of "gray" pixmaps + onto an arbitrary drawable. +

    • +
    + +

    As both the font and rendering models of X11 are limited, it's basically + impossible to draw anti-aliased glyphs without performing huge + hacks within the server.

    + +

    Note that Keith Packard, from XFree fame, has recently started working + on a new rendering model for X11 in order to support new features + (mainly transparency and anti-aliased fonts). This will be provided + through protocol extensions. The question of knowing wether legacy X + applications will be able to display anti-aliased text is still very + uncertain. +

    +
+ +
+

I.5. Is FreeType 2 backwards compatible with FreeType 1.x?

+
    +

    Not directly, though we had the project to provide an optional binary + compatibility layer on top of it in order to easily re-link applications + with the new version. However, this idea has been dropped as it is + possible to install and use the two versions independtly on any + system (read: no namespace conflicts).

    + +

    The FreeType 2 API is a lot simpler than the one in 1.x while being + much more powerful. We thus encourage you to adapt your source code + to it as this should not involve much work.

    + +
+ +
+

I.6. Can I use FreeType 2 to edit fonts or create new ones?

+
    +

    The answer is a definitive NO, because the library was specifically + designed to read font files with small code size and very + low memory usage.

    + +

    We thus do not plan to support editing or creation in the font + engine in any way, as this would imply a complete rewrite. This + doesn't mean that we won't introduce a font editing/creation library + in the future, as this really depends on how many people are asking + for it (or how much they would be willing to pay for it), as well as + the time of the FreeType developers.

    + +

    Do not expect anything in this direction until we officially announce + something though. There are other axis of development for this project + (like text-layout capabilities, glyph caching, etc..) that may be more + important to us at the moment..

    +
+ +
+ +
+

Compilation & Configuration

+
+ + +

II.1. How do I compile the FreeType 2 library?

+
    +

    The library can be compiled in various ways, and a detailed documentation + is available in the file "freetype2/docs/BUILD". However, we'll + summarize the process to a few cases:

    + +

    a. by using the command-line 2 build system

    + +

    The engine comes with a sophisticated build system that is used + to configure and compile a build of the library. You'll need + GNU Make installed on your platform (NOTE: It will not + work with other Make tools).

    + +

    Basically, you'll need to invoke make a first time in the + top-level FreeType 2 directory in order to setup the build. This will + detect your current platform and choose a configuration sub-makefile to + drive the build. A specific compiler can be selected on some platforms + by providing an additional target. For example, on Win32:

    + +
      +
    • make visualc will select the Visual C++ compiler
    • +
    • make lcc will select the Win32-lcc compiler
    • +
    + +

    Note that on Unix, the first time make is called, a configure script + located in "freetype2/builds/unix" will be run in order to + automatically detect the platform & compiler.

    + +

    A summary will be displayed showing the detected platform and compiler + selected. You'll then be able to start the build by invoking make + a second time. In case of problem, consult the BUILD document.

    + + +

    b. by direct compilation

    + +

    You can also directly compile the library from the command line by + using these simple rules:

    + +
      +
    • + You should place the directories "freetype2/include" and + "freetype2/src" in your include path in order to compile + any component of the library. You can also add the system-specific + build directory (i.e. "builds/system/") in the + case where an alternate implementation of some of the components + is available there (e.g. the memory-mapped i/o implementation + on some Unix systems). +

    • + +
    • + The components of the library are located in sub-directories of + "src", for example: "src/base", + "src/truetype", etc.. +

    • + +
    • + Each component is normally compiled through a single C file that + "wraps" other sources in the component's directory. For example, + your should compile the TrueType font driver by compiling the + file "src/truetype/truetype.c". The list of C files to + compile for a feature-complete build of the library is given in + the BUILD document. +

    • +
    + +

    c. in a graphical IDE

    +
      +

      Well, the process is vastly similar to the one described in b., + except that you need to set the include paths, source code paths, + etc.. in dialog boxes before running the compilation. +

      +
    + +
+ +
+

II.2. How do I configure my build of the library?

+
    +

    Each build of the library is configured through two header files + located in "include/freetype/config":

    + +
      +
    • ftoption.h
      + This file contains various configuration macros whose definition + can be toggled on a per-build basis. Each macro is heavily + commented in this file's comment, and we invite you to refer + to it directly.

    • + +
    • ftmodule.h
      + This file contains the list of all the modules that are initially + registered (added) when the function FT_Init_FreeType + is called. See the next answer to know how to change it and + why it may be important.

    • +
    + +

    Alternatively, some specific implementations of some FT2 components + can be provided in a "builds/system/" directory + (e.g. the Unix-specific ftsystem.c that uses memory-mapped + file for i/o).

    +
+ +
+

II.3. How do I select the modules I need in my build?

+
    +

    The function FT_Init_FreeType creates a new instance + of the FT2 library and registers a set of "default" modules before + returning to the calling application. Its default implementation + is in the file "src/base/ftinit.c".

    + +

    The list of default modules used by ftinit.c is located in + the configuration file "include/freetype/config/ftmodule.h". + It is normally automatically generated by the build system by + invoking the "make modules" command in the top + level FT2 directory (note: only works with GNU Make, you can + edit the file by hand otherwise). It does so by parsing all + sub-directories of "src" that contain a file named + module.mk.

    + +

    Note that a specific port or project is free to provide its own + implementation of ftinit.c in order to ensure a different + initialisation sequence. For example, one could do something like:

    + +
      +
    • compile each module as a shared library (DLL or .so) with + a common "entry point" to retrieve a pointer to its + module class (there is already some code that allows this + when compiling each module).

    • + +
    • place these modules in a directory like + "/usr/lib/freetype2/modules/"

    • + +
    • provide an implementation of ftinit.c that would + scan the directory for valid modules.

    • +
    + +

    This example only emphasize the flexibility that is left to + developers when building the library.

    + +
+ +
+

II.4. How do I compile all FreeType 2 files in a single directory?

+
    +

    Some projects may need, for the sake of simplicity or ease of + building, to compile the FT2 library with all source files + copied to a single directory. This is possible.

    + +

    To do so, you'll need to copy all source files located under + "src" to your own directory (you must retain the + include files in a distinct hierarchy though), then compile + each of the FreeType 2 component with the macro + FT_FLAT_COMPILE. This will change the way + #include works during the build.

    +
+ +
+ +
+

Using the FreeType 2 library

+
+ +
+ +
+

The FreeType 2 auto-hinter

+
+ + +

IV.1. Under which license is the FreeType 2 auto-hinter released

+
    +

    The auto-hinter was initially designed and implemented under contract + for Catharon Productions, Inc + which gladly accepted to released it under an open-source license + compatible with the FreeType one.

    + +

    This license can be found in "src/autohint/CatharonLicense.txt" + and requires that you cite Catharon Productions in your documentation + (just like you do with FreeType) when using the auto-hinting module.

    + +

    Other than that, you still have the same freedom than with the good old + FreeType license. Enjoy !

    +
+ + +

IV.2. How does the auto-hinter works ?

+
    +

    Well, a complete description would be difficult. Have a look at the + dedicated auto-hinter pages on the FreeType + site, as they describe most of its details with graphics and explanations. + You could also look at the source code if you want to :-)

    + +

    To give a few details, the auto-hinter is used to perform grid-fitting + on scalable font formats that use bezier outlines as their primary glyph + image format (this means nearly all scalable font formats today). When + a given font driver doesn't provide its own hinter, the auto-hinter is + used by default. When a format-specific hinter is provided, it is still + possible to use the auto-hinter using the + FT_LOAD_FORCE_AUTOHINT bit flag when calling + FT_Load_Glyph.

    + +

    The auto-hinter currently doesn't use external hints to do its job, + as it automatically computes global metrics (when it "opens" a font + for the first time) and glyph "hints" from their outline. Note that + we plan the ability to specify external hints, given that it is based + on a constraint system. That could be used to support native hints + in Type 1/Type 2 fonts, for example.

    +
+ + +

IV.3. Why does the auto-hinter doesn't work correctly with CJK fonts ?

+
    +

    The auto-hinter was first designed to manage and hint latin-based fonts, + as they consist of most of the fonts available today. It doesn't hint + asian fonts, as well as a few other complex scripts, because we didn't + put enough research on the topic yet. Hinting CJK isn't really more + difficult than latin, just different with a set of different constraints + (basically, more distortion of glyphs is acceptable as long as certain + features like triple-stem positions are respected more strictly..).

    + +

    We thus plan to handle such a case rather rapidly.. Please be patient.

    +
+ + +
+ +
+

Other questions

+
+ + +

V.1. What is the anti-aliasing algorithm used by FreeType 2 ?

+
    +

    The algorithm has been specifically designed for FreeType. It is + based on ideas that were originally found in the implementation + of the libArt graphics + library to compute the exact pixel coverage of a vector + image with absolutely now sub-sampling/filtering. +

    + +

    However, these two implementations are radically distinct and use + vastly different models. The FreeType 2 renderer is optimized + specifically for rendering small complex shapes, like glyphs, at + very high speed while using very few memory; while libArt shines + at general shape/polygon processing, especially large ones.

    + +

    The FT2 anti-aliasing renderer is indeed faster than the + monochrome renderer for small character sizes (typically < 20 pixels). + This is explained because the monochrome renderer must perform two + passes on the outline in order to perform drop-out control according + to the TrueType spec (we could drop this requirement later though).

    + +

    We'll try to document its design in a later document, though this is + not a priority for now.

    +
+ + +

V.2. When will FreeType 2 support OpenType ?

+
    +

    Well, the engine already reads OpenType/CFF files perfectly. What it + doesn't do is handle "OpenType Layout" tables yet.

    + +

    FreeType 1 comes with a set of extensions that are used to load + and manage OpenType Layout tables. It even has a demonstration program + named "ftstrtto" used to demonstrate its capabilities that + runs pretty smooth.

    + +

    For FreeType 2, we have decided that the layout operations provided + through these tables is better placed in a specific text-layout library, + (many people having asked for such a thing). This new engine would not + depend on FT2 explicitely and will be developed as a separate project. + We plan to announce it in a few weeks with all gory details, + once the definitive 2.0 release of FreeType has been made.

    +
+ +
+ +


+

+Back to FreeType homepage

+ +

+ + diff --git a/reactos/subsys/win32k/freetype/docs/glnames.py b/reactos/subsys/win32k/freetype/docs/glnames.py new file mode 100644 index 00000000000..7b72669c331 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glnames.py @@ -0,0 +1,1706 @@ +#!/usr/bin/env python +# + +# +# FreeType 2 glyph name builder +# + + +# Copyright 1996-2000 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. + + +"""\ + +usage: %s + + This very simple python script is used to generate the glyph names + tables defined in the PSNames module. + + Its single argument is the name of the header file to be created. +""" + + +import sys, string + + +# This table is used to name the glyph according to the Macintosh +# specification. It is used by the TrueType Postscript names table +# +mac_standard_names = \ +[ + # 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" +] + + +t1_standard_strings = \ +[ + # 0 + ".notdef", "space", "exclam", "quotedbl", "numbersign", + "dollar", "percent", "ampersand", "quoteright", "parenleft", + + # 10 + "parenright", "asterisk", "plus", "comma", "hyphen", + "period", "slash", "zero", "one", "two", + + # 20 + "three", "four", "five", "six", "seven", + "eight", "nine", "colon", "semicolon", "less", + + # 30 + "equal", "greater", "question", "at", "A", + "B", "C", "D", "E", "F", + + # 40 + "G", "H", "I", "J", "K", + "L", "M", "N", "O", "P", + + # 50 + "Q", "R", "S", "T", "U", + "V", "W", "X", "Y", "Z", + + # 60 + "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", + "quoteleft", "a", "b", "c", "d", + + # 70 + "e", "f", "g", "h", "i", + "j", "k", "l", "m", "n", + + # 80 + "o", "p", "q", "r", "s", + "t", "u", "v", "w", "x", + + # 90 + "y", "z", "braceleft", "bar", "braceright", + "asciitilde", "exclamdown", "cent", "sterling", "fraction", + + # 100 + "yen", "florin", "section", "currency", "quotesingle", + "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", + + # 110 + "fl", "endash", "dagger", "daggerdbl", "periodcenter", + "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", + + # 120 + "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", + "acute", "circumflex", "tilde", "macron", "breve", + + # 130 + "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", + "ogonek", "caron", "emdash", "AE", "ordfeminine", + + # 140 + "Lslash", "Oslash", "OE", "ordmasculine", "ae", + "dotlessi", "Islash", "oslash", "oe", "germandbls", + + # 150 + "onesuperior", "logicalnot", "mu", "trademark", "Eth", + "onehalf", "plusminus", "Thorn", "onequarter", "divide", + + # 160 + "brokenbar", "degree", "thorn", "threequarters", "twosuperior", + "registered", "minus", "eth", "multiply", "threesuperior", + + # 170 + "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", + "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", + + # 180 + "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", + "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", + + # 190 + "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", + "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", + + # 200 + "aacute", "acircumflex", "adieresis", "agrave", "aring", + "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", + + # 210 + "egrave", "iacute", "icircumflex", "idieresis", "igrave", + "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", + + # 220 + "otilde", "scaron", "uacute", "ucircumflex", "udieresis", + "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", + + # 230 + "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", + "Acutesmall", + "parenleftsuperior", "parenrightsuperior", "twodotenleader", + "onedotenleader", "zerooldstyle", + + # 240 + "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", + "commasuperior", + + # 250 + "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", + "bsuperior", + "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", + + # 260 + "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", + "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", + + # 270 + "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", + "Asmall", + "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", + + # 280 + "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", + "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", + + # 290 + "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", + "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", + + # 300 + "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", + "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", + "Dieresissmall", + + # 310 + "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", + "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", + "questiondownsmall", + + # 320 + "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", + "twothirds", "zerosuperior", "foursuperior", "fivesuperior", + "sixsuperior", + + # 330 + "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", + "oneinferior", + "twoinferior", "threeinferior", "fourinferior", "fiveinferior", + "sixinferior", + + # 340 + "seveninferior", "eightinferior", "nineinferior", "centinferior", + "dollarinferior", + "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", + "Acircumflexsmall", + + # 350 + "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", + "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", + "Igravesmall", + + # 360 + "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", + "Ntildesmall", + "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", + "Odieresissmall", + + # 370 + "OEsmall", "Oslashsmall", "Ugravesmall", "Uacautesmall", + "Ucircumflexsmall", + "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", + "001.000", + + # 380 + "001.001", "001.002", "001.003", "Black", "Bold", + "Book", "Light", "Medium", "Regular", "Roman", + + # 390 + "Semibold" +] + + +t1_standard_encoding = \ +[ + 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 +] + + +t1_expert_encoding = \ +[ + 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 +] + + +# This data has been taken literally from the file `glyphlist.txt', +# version 1.2, 22 Oct 1998. It is available from +# +# http://partners.adobe.com/asn/developer/typeforum/unicodegn.html +# +adobe_glyph_list = """\ +0041;A;LATIN CAPITAL LETTER A +00C6;AE;LATIN CAPITAL LETTER AE +01FC;AEacute;LATIN CAPITAL LETTER AE WITH ACUTE +F7E6;AEsmall;LATIN SMALL CAPITAL LETTER AE +00C1;Aacute;LATIN CAPITAL LETTER A WITH ACUTE +F7E1;Aacutesmall;LATIN SMALL CAPITAL LETTER A WITH ACUTE +0102;Abreve;LATIN CAPITAL LETTER A WITH BREVE +00C2;Acircumflex;LATIN CAPITAL LETTER A WITH CIRCUMFLEX +F7E2;Acircumflexsmall;LATIN SMALL CAPITAL LETTER A WITH CIRCUMFLEX +F6C9;Acute;CAPITAL ACUTE ACCENT +F7B4;Acutesmall;SMALL CAPITAL ACUTE ACCENT +00C4;Adieresis;LATIN CAPITAL LETTER A WITH DIAERESIS +F7E4;Adieresissmall;LATIN SMALL CAPITAL LETTER A WITH DIAERESIS +00C0;Agrave;LATIN CAPITAL LETTER A WITH GRAVE +F7E0;Agravesmall;LATIN SMALL CAPITAL LETTER A WITH GRAVE +0391;Alpha;GREEK CAPITAL LETTER ALPHA +0386;Alphatonos;GREEK CAPITAL LETTER ALPHA WITH TONOS +0100;Amacron;LATIN CAPITAL LETTER A WITH MACRON +0104;Aogonek;LATIN CAPITAL LETTER A WITH OGONEK +00C5;Aring;LATIN CAPITAL LETTER A WITH RING ABOVE +01FA;Aringacute;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE +F7E5;Aringsmall;LATIN SMALL CAPITAL LETTER A WITH RING ABOVE +F761;Asmall;LATIN SMALL CAPITAL LETTER A +00C3;Atilde;LATIN CAPITAL LETTER A WITH TILDE +F7E3;Atildesmall;LATIN SMALL CAPITAL LETTER A WITH TILDE +0042;B;LATIN CAPITAL LETTER B +0392;Beta;GREEK CAPITAL LETTER BETA +F6F4;Brevesmall;SMALL CAPITAL BREVE +F762;Bsmall;LATIN SMALL CAPITAL LETTER B +0043;C;LATIN CAPITAL LETTER C +0106;Cacute;LATIN CAPITAL LETTER C WITH ACUTE +F6CA;Caron;CAPITAL CARON +F6F5;Caronsmall;SMALL CAPITAL CARON +010C;Ccaron;LATIN CAPITAL LETTER C WITH CARON +00C7;Ccedilla;LATIN CAPITAL LETTER C WITH CEDILLA +F7E7;Ccedillasmall;LATIN SMALL CAPITAL LETTER C WITH CEDILLA +0108;Ccircumflex;LATIN CAPITAL LETTER C WITH CIRCUMFLEX +010A;Cdotaccent;LATIN CAPITAL LETTER C WITH DOT ABOVE +F7B8;Cedillasmall;SMALL CAPITAL CEDILLA +03A7;Chi;GREEK CAPITAL LETTER CHI +F6F6;Circumflexsmall;SMALL CAPITAL MODIFIER LETTER CIRCUMFLEX ACCENT +F763;Csmall;LATIN SMALL CAPITAL LETTER C +0044;D;LATIN CAPITAL LETTER D +010E;Dcaron;LATIN CAPITAL LETTER D WITH CARON +0110;Dcroat;LATIN CAPITAL LETTER D WITH STROKE +2206;Delta;INCREMENT +0394;Delta;GREEK CAPITAL LETTER DELTA;Duplicate +F6CB;Dieresis;CAPITAL DIAERESIS +F6CC;DieresisAcute;CAPITAL DIAERESIS ACUTE ACCENT +F6CD;DieresisGrave;CAPITAL DIAERESIS GRAVE ACCENT +F7A8;Dieresissmall;SMALL CAPITAL DIAERESIS +F6F7;Dotaccentsmall;SMALL CAPITAL DOT ABOVE +F764;Dsmall;LATIN SMALL CAPITAL LETTER D +0045;E;LATIN CAPITAL LETTER E +00C9;Eacute;LATIN CAPITAL LETTER E WITH ACUTE +F7E9;Eacutesmall;LATIN SMALL CAPITAL LETTER E WITH ACUTE +0114;Ebreve;LATIN CAPITAL LETTER E WITH BREVE +011A;Ecaron;LATIN CAPITAL LETTER E WITH CARON +00CA;Ecircumflex;LATIN CAPITAL LETTER E WITH CIRCUMFLEX +F7EA;Ecircumflexsmall;LATIN SMALL CAPITAL LETTER E WITH CIRCUMFLEX +00CB;Edieresis;LATIN CAPITAL LETTER E WITH DIAERESIS +F7EB;Edieresissmall;LATIN SMALL CAPITAL LETTER E WITH DIAERESIS +0116;Edotaccent;LATIN CAPITAL LETTER E WITH DOT ABOVE +00C8;Egrave;LATIN CAPITAL LETTER E WITH GRAVE +F7E8;Egravesmall;LATIN SMALL CAPITAL LETTER E WITH GRAVE +0112;Emacron;LATIN CAPITAL LETTER E WITH MACRON +014A;Eng;LATIN CAPITAL LETTER ENG +0118;Eogonek;LATIN CAPITAL LETTER E WITH OGONEK +0395;Epsilon;GREEK CAPITAL LETTER EPSILON +0388;Epsilontonos;GREEK CAPITAL LETTER EPSILON WITH TONOS +F765;Esmall;LATIN SMALL CAPITAL LETTER E +0397;Eta;GREEK CAPITAL LETTER ETA +0389;Etatonos;GREEK CAPITAL LETTER ETA WITH TONOS +00D0;Eth;LATIN CAPITAL LETTER ETH +F7F0;Ethsmall;LATIN SMALL CAPITAL LETTER ETH +20AC;Euro;EURO SIGN +0046;F;LATIN CAPITAL LETTER F +F766;Fsmall;LATIN SMALL CAPITAL LETTER F +0047;G;LATIN CAPITAL LETTER G +0393;Gamma;GREEK CAPITAL LETTER GAMMA +011E;Gbreve;LATIN CAPITAL LETTER G WITH BREVE +01E6;Gcaron;LATIN CAPITAL LETTER G WITH CARON +011C;Gcircumflex;LATIN CAPITAL LETTER G WITH CIRCUMFLEX +0122;Gcommaaccent;LATIN CAPITAL LETTER G WITH CEDILLA +0120;Gdotaccent;LATIN CAPITAL LETTER G WITH DOT ABOVE +F6CE;Grave;CAPITAL GRAVE ACCENT +F760;Gravesmall;SMALL CAPITAL GRAVE ACCENT +F767;Gsmall;LATIN SMALL CAPITAL LETTER G +0048;H;LATIN CAPITAL LETTER H +25CF;H18533;BLACK CIRCLE +25AA;H18543;BLACK SMALL SQUARE +25AB;H18551;WHITE SMALL SQUARE +25A1;H22073;WHITE SQUARE +0126;Hbar;LATIN CAPITAL LETTER H WITH STROKE +0124;Hcircumflex;LATIN CAPITAL LETTER H WITH CIRCUMFLEX +F768;Hsmall;LATIN SMALL CAPITAL LETTER H +F6CF;Hungarumlaut;CAPITAL DOUBLE ACUTE ACCENT +F6F8;Hungarumlautsmall;SMALL CAPITAL DOUBLE ACUTE ACCENT +0049;I;LATIN CAPITAL LETTER I +0132;IJ;LATIN CAPITAL LIGATURE IJ +00CD;Iacute;LATIN CAPITAL LETTER I WITH ACUTE +F7ED;Iacutesmall;LATIN SMALL CAPITAL LETTER I WITH ACUTE +012C;Ibreve;LATIN CAPITAL LETTER I WITH BREVE +00CE;Icircumflex;LATIN CAPITAL LETTER I WITH CIRCUMFLEX +F7EE;Icircumflexsmall;LATIN SMALL CAPITAL LETTER I WITH CIRCUMFLEX +00CF;Idieresis;LATIN CAPITAL LETTER I WITH DIAERESIS +F7EF;Idieresissmall;LATIN SMALL CAPITAL LETTER I WITH DIAERESIS +0130;Idotaccent;LATIN CAPITAL LETTER I WITH DOT ABOVE +2111;Ifraktur;BLACK-LETTER CAPITAL I +00CC;Igrave;LATIN CAPITAL LETTER I WITH GRAVE +F7EC;Igravesmall;LATIN SMALL CAPITAL LETTER I WITH GRAVE +012A;Imacron;LATIN CAPITAL LETTER I WITH MACRON +012E;Iogonek;LATIN CAPITAL LETTER I WITH OGONEK +0399;Iota;GREEK CAPITAL LETTER IOTA +03AA;Iotadieresis;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA +038A;Iotatonos;GREEK CAPITAL LETTER IOTA WITH TONOS +F769;Ismall;LATIN SMALL CAPITAL LETTER I +0128;Itilde;LATIN CAPITAL LETTER I WITH TILDE +004A;J;LATIN CAPITAL LETTER J +0134;Jcircumflex;LATIN CAPITAL LETTER J WITH CIRCUMFLEX +F76A;Jsmall;LATIN SMALL CAPITAL LETTER J +004B;K;LATIN CAPITAL LETTER K +039A;Kappa;GREEK CAPITAL LETTER KAPPA +0136;Kcommaaccent;LATIN CAPITAL LETTER K WITH CEDILLA +F76B;Ksmall;LATIN SMALL CAPITAL LETTER K +004C;L;LATIN CAPITAL LETTER L +F6BF;LL;LATIN CAPITAL LETTER LL +0139;Lacute;LATIN CAPITAL LETTER L WITH ACUTE +039B;Lambda;GREEK CAPITAL LETTER LAMDA +013D;Lcaron;LATIN CAPITAL LETTER L WITH CARON +013B;Lcommaaccent;LATIN CAPITAL LETTER L WITH CEDILLA +013F;Ldot;LATIN CAPITAL LETTER L WITH MIDDLE DOT +0141;Lslash;LATIN CAPITAL LETTER L WITH STROKE +F6F9;Lslashsmall;LATIN SMALL CAPITAL LETTER L WITH STROKE +F76C;Lsmall;LATIN SMALL CAPITAL LETTER L +004D;M;LATIN CAPITAL LETTER M +F6D0;Macron;CAPITAL MACRON +F7AF;Macronsmall;SMALL CAPITAL MACRON +F76D;Msmall;LATIN SMALL CAPITAL LETTER M +039C;Mu;GREEK CAPITAL LETTER MU +004E;N;LATIN CAPITAL LETTER N +0143;Nacute;LATIN CAPITAL LETTER N WITH ACUTE +0147;Ncaron;LATIN CAPITAL LETTER N WITH CARON +0145;Ncommaaccent;LATIN CAPITAL LETTER N WITH CEDILLA +F76E;Nsmall;LATIN SMALL CAPITAL LETTER N +00D1;Ntilde;LATIN CAPITAL LETTER N WITH TILDE +F7F1;Ntildesmall;LATIN SMALL CAPITAL LETTER N WITH TILDE +039D;Nu;GREEK CAPITAL LETTER NU +004F;O;LATIN CAPITAL LETTER O +0152;OE;LATIN CAPITAL LIGATURE OE +F6FA;OEsmall;LATIN SMALL CAPITAL LIGATURE OE +00D3;Oacute;LATIN CAPITAL LETTER O WITH ACUTE +F7F3;Oacutesmall;LATIN SMALL CAPITAL LETTER O WITH ACUTE +014E;Obreve;LATIN CAPITAL LETTER O WITH BREVE +00D4;Ocircumflex;LATIN CAPITAL LETTER O WITH CIRCUMFLEX +F7F4;Ocircumflexsmall;LATIN SMALL CAPITAL LETTER O WITH CIRCUMFLEX +00D6;Odieresis;LATIN CAPITAL LETTER O WITH DIAERESIS +F7F6;Odieresissmall;LATIN SMALL CAPITAL LETTER O WITH DIAERESIS +F6FB;Ogoneksmall;SMALL CAPITAL OGONEK +00D2;Ograve;LATIN CAPITAL LETTER O WITH GRAVE +F7F2;Ogravesmall;LATIN SMALL CAPITAL LETTER O WITH GRAVE +01A0;Ohorn;LATIN CAPITAL LETTER O WITH HORN +0150;Ohungarumlaut;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE +014C;Omacron;LATIN CAPITAL LETTER O WITH MACRON +2126;Omega;OHM SIGN +03A9;Omega;GREEK CAPITAL LETTER OMEGA;Duplicate +038F;Omegatonos;GREEK CAPITAL LETTER OMEGA WITH TONOS +039F;Omicron;GREEK CAPITAL LETTER OMICRON +038C;Omicrontonos;GREEK CAPITAL LETTER OMICRON WITH TONOS +00D8;Oslash;LATIN CAPITAL LETTER O WITH STROKE +01FE;Oslashacute;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE +F7F8;Oslashsmall;LATIN SMALL CAPITAL LETTER O WITH STROKE +F76F;Osmall;LATIN SMALL CAPITAL LETTER O +00D5;Otilde;LATIN CAPITAL LETTER O WITH TILDE +F7F5;Otildesmall;LATIN SMALL CAPITAL LETTER O WITH TILDE +0050;P;LATIN CAPITAL LETTER P +03A6;Phi;GREEK CAPITAL LETTER PHI +03A0;Pi;GREEK CAPITAL LETTER PI +03A8;Psi;GREEK CAPITAL LETTER PSI +F770;Psmall;LATIN SMALL CAPITAL LETTER P +0051;Q;LATIN CAPITAL LETTER Q +F771;Qsmall;LATIN SMALL CAPITAL LETTER Q +0052;R;LATIN CAPITAL LETTER R +0154;Racute;LATIN CAPITAL LETTER R WITH ACUTE +0158;Rcaron;LATIN CAPITAL LETTER R WITH CARON +0156;Rcommaaccent;LATIN CAPITAL LETTER R WITH CEDILLA +211C;Rfraktur;BLACK-LETTER CAPITAL R +03A1;Rho;GREEK CAPITAL LETTER RHO +F6FC;Ringsmall;SMALL CAPITAL RING ABOVE +F772;Rsmall;LATIN SMALL CAPITAL LETTER R +0053;S;LATIN CAPITAL LETTER S +250C;SF010000;BOX DRAWINGS LIGHT DOWN AND RIGHT +2514;SF020000;BOX DRAWINGS LIGHT UP AND RIGHT +2510;SF030000;BOX DRAWINGS LIGHT DOWN AND LEFT +2518;SF040000;BOX DRAWINGS LIGHT UP AND LEFT +253C;SF050000;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL +252C;SF060000;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL +2534;SF070000;BOX DRAWINGS LIGHT UP AND HORIZONTAL +251C;SF080000;BOX DRAWINGS LIGHT VERTICAL AND RIGHT +2524;SF090000;BOX DRAWINGS LIGHT VERTICAL AND LEFT +2500;SF100000;BOX DRAWINGS LIGHT HORIZONTAL +2502;SF110000;BOX DRAWINGS LIGHT VERTICAL +2561;SF190000;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE +2562;SF200000;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE +2556;SF210000;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE +2555;SF220000;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE +2563;SF230000;BOX DRAWINGS DOUBLE VERTICAL AND LEFT +2551;SF240000;BOX DRAWINGS DOUBLE VERTICAL +2557;SF250000;BOX DRAWINGS DOUBLE DOWN AND LEFT +255D;SF260000;BOX DRAWINGS DOUBLE UP AND LEFT +255C;SF270000;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE +255B;SF280000;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE +255E;SF360000;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE +255F;SF370000;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE +255A;SF380000;BOX DRAWINGS DOUBLE UP AND RIGHT +2554;SF390000;BOX DRAWINGS DOUBLE DOWN AND RIGHT +2569;SF400000;BOX DRAWINGS DOUBLE UP AND HORIZONTAL +2566;SF410000;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL +2560;SF420000;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT +2550;SF430000;BOX DRAWINGS DOUBLE HORIZONTAL +256C;SF440000;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL +2567;SF450000;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE +2568;SF460000;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE +2564;SF470000;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE +2565;SF480000;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE +2559;SF490000;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE +2558;SF500000;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE +2552;SF510000;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE +2553;SF520000;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE +256B;SF530000;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE +256A;SF540000;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE +015A;Sacute;LATIN CAPITAL LETTER S WITH ACUTE +0160;Scaron;LATIN CAPITAL LETTER S WITH CARON +F6FD;Scaronsmall;LATIN SMALL CAPITAL LETTER S WITH CARON +015E;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA +F6C1;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA;Duplicate +015C;Scircumflex;LATIN CAPITAL LETTER S WITH CIRCUMFLEX +0218;Scommaaccent;LATIN CAPITAL LETTER S WITH COMMA BELOW +03A3;Sigma;GREEK CAPITAL LETTER SIGMA +F773;Ssmall;LATIN SMALL CAPITAL LETTER S +0054;T;LATIN CAPITAL LETTER T +03A4;Tau;GREEK CAPITAL LETTER TAU +0166;Tbar;LATIN CAPITAL LETTER T WITH STROKE +0164;Tcaron;LATIN CAPITAL LETTER T WITH CARON +0162;Tcommaaccent;LATIN CAPITAL LETTER T WITH CEDILLA +021A;Tcommaaccent;LATIN CAPITAL LETTER T WITH COMMA BELOW;Duplicate +0398;Theta;GREEK CAPITAL LETTER THETA +00DE;Thorn;LATIN CAPITAL LETTER THORN +F7FE;Thornsmall;LATIN SMALL CAPITAL LETTER THORN +F6FE;Tildesmall;SMALL CAPITAL SMALL TILDE +F774;Tsmall;LATIN SMALL CAPITAL LETTER T +0055;U;LATIN CAPITAL LETTER U +00DA;Uacute;LATIN CAPITAL LETTER U WITH ACUTE +F7FA;Uacutesmall;LATIN SMALL CAPITAL LETTER U WITH ACUTE +016C;Ubreve;LATIN CAPITAL LETTER U WITH BREVE +00DB;Ucircumflex;LATIN CAPITAL LETTER U WITH CIRCUMFLEX +F7FB;Ucircumflexsmall;LATIN SMALL CAPITAL LETTER U WITH CIRCUMFLEX +00DC;Udieresis;LATIN CAPITAL LETTER U WITH DIAERESIS +F7FC;Udieresissmall;LATIN SMALL CAPITAL LETTER U WITH DIAERESIS +00D9;Ugrave;LATIN CAPITAL LETTER U WITH GRAVE +F7F9;Ugravesmall;LATIN SMALL CAPITAL LETTER U WITH GRAVE +01AF;Uhorn;LATIN CAPITAL LETTER U WITH HORN +0170;Uhungarumlaut;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE +016A;Umacron;LATIN CAPITAL LETTER U WITH MACRON +0172;Uogonek;LATIN CAPITAL LETTER U WITH OGONEK +03A5;Upsilon;GREEK CAPITAL LETTER UPSILON +03D2;Upsilon1;GREEK UPSILON WITH HOOK SYMBOL +03AB;Upsilondieresis;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA +038E;Upsilontonos;GREEK CAPITAL LETTER UPSILON WITH TONOS +016E;Uring;LATIN CAPITAL LETTER U WITH RING ABOVE +F775;Usmall;LATIN SMALL CAPITAL LETTER U +0168;Utilde;LATIN CAPITAL LETTER U WITH TILDE +0056;V;LATIN CAPITAL LETTER V +F776;Vsmall;LATIN SMALL CAPITAL LETTER V +0057;W;LATIN CAPITAL LETTER W +1E82;Wacute;LATIN CAPITAL LETTER W WITH ACUTE +0174;Wcircumflex;LATIN CAPITAL LETTER W WITH CIRCUMFLEX +1E84;Wdieresis;LATIN CAPITAL LETTER W WITH DIAERESIS +1E80;Wgrave;LATIN CAPITAL LETTER W WITH GRAVE +F777;Wsmall;LATIN SMALL CAPITAL LETTER W +0058;X;LATIN CAPITAL LETTER X +039E;Xi;GREEK CAPITAL LETTER XI +F778;Xsmall;LATIN SMALL CAPITAL LETTER X +0059;Y;LATIN CAPITAL LETTER Y +00DD;Yacute;LATIN CAPITAL LETTER Y WITH ACUTE +F7FD;Yacutesmall;LATIN SMALL CAPITAL LETTER Y WITH ACUTE +0176;Ycircumflex;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX +0178;Ydieresis;LATIN CAPITAL LETTER Y WITH DIAERESIS +F7FF;Ydieresissmall;LATIN SMALL CAPITAL LETTER Y WITH DIAERESIS +1EF2;Ygrave;LATIN CAPITAL LETTER Y WITH GRAVE +F779;Ysmall;LATIN SMALL CAPITAL LETTER Y +005A;Z;LATIN CAPITAL LETTER Z +0179;Zacute;LATIN CAPITAL LETTER Z WITH ACUTE +017D;Zcaron;LATIN CAPITAL LETTER Z WITH CARON +F6FF;Zcaronsmall;LATIN SMALL CAPITAL LETTER Z WITH CARON +017B;Zdotaccent;LATIN CAPITAL LETTER Z WITH DOT ABOVE +0396;Zeta;GREEK CAPITAL LETTER ZETA +F77A;Zsmall;LATIN SMALL CAPITAL LETTER Z +0061;a;LATIN SMALL LETTER A +00E1;aacute;LATIN SMALL LETTER A WITH ACUTE +0103;abreve;LATIN SMALL LETTER A WITH BREVE +00E2;acircumflex;LATIN SMALL LETTER A WITH CIRCUMFLEX +00B4;acute;ACUTE ACCENT +0301;acutecomb;COMBINING ACUTE ACCENT +00E4;adieresis;LATIN SMALL LETTER A WITH DIAERESIS +00E6;ae;LATIN SMALL LETTER AE +01FD;aeacute;LATIN SMALL LETTER AE WITH ACUTE +2015;afii00208;HORIZONTAL BAR +0410;afii10017;CYRILLIC CAPITAL LETTER A +0411;afii10018;CYRILLIC CAPITAL LETTER BE +0412;afii10019;CYRILLIC CAPITAL LETTER VE +0413;afii10020;CYRILLIC CAPITAL LETTER GHE +0414;afii10021;CYRILLIC CAPITAL LETTER DE +0415;afii10022;CYRILLIC CAPITAL LETTER IE +0401;afii10023;CYRILLIC CAPITAL LETTER IO +0416;afii10024;CYRILLIC CAPITAL LETTER ZHE +0417;afii10025;CYRILLIC CAPITAL LETTER ZE +0418;afii10026;CYRILLIC CAPITAL LETTER I +0419;afii10027;CYRILLIC CAPITAL LETTER SHORT I +041A;afii10028;CYRILLIC CAPITAL LETTER KA +041B;afii10029;CYRILLIC CAPITAL LETTER EL +041C;afii10030;CYRILLIC CAPITAL LETTER EM +041D;afii10031;CYRILLIC CAPITAL LETTER EN +041E;afii10032;CYRILLIC CAPITAL LETTER O +041F;afii10033;CYRILLIC CAPITAL LETTER PE +0420;afii10034;CYRILLIC CAPITAL LETTER ER +0421;afii10035;CYRILLIC CAPITAL LETTER ES +0422;afii10036;CYRILLIC CAPITAL LETTER TE +0423;afii10037;CYRILLIC CAPITAL LETTER U +0424;afii10038;CYRILLIC CAPITAL LETTER EF +0425;afii10039;CYRILLIC CAPITAL LETTER HA +0426;afii10040;CYRILLIC CAPITAL LETTER TSE +0427;afii10041;CYRILLIC CAPITAL LETTER CHE +0428;afii10042;CYRILLIC CAPITAL LETTER SHA +0429;afii10043;CYRILLIC CAPITAL LETTER SHCHA +042A;afii10044;CYRILLIC CAPITAL LETTER HARD SIGN +042B;afii10045;CYRILLIC CAPITAL LETTER YERU +042C;afii10046;CYRILLIC CAPITAL LETTER SOFT SIGN +042D;afii10047;CYRILLIC CAPITAL LETTER E +042E;afii10048;CYRILLIC CAPITAL LETTER YU +042F;afii10049;CYRILLIC CAPITAL LETTER YA +0490;afii10050;CYRILLIC CAPITAL LETTER GHE WITH UPTURN +0402;afii10051;CYRILLIC CAPITAL LETTER DJE +0403;afii10052;CYRILLIC CAPITAL LETTER GJE +0404;afii10053;CYRILLIC CAPITAL LETTER UKRAINIAN IE +0405;afii10054;CYRILLIC CAPITAL LETTER DZE +0406;afii10055;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I +0407;afii10056;CYRILLIC CAPITAL LETTER YI +0408;afii10057;CYRILLIC CAPITAL LETTER JE +0409;afii10058;CYRILLIC CAPITAL LETTER LJE +040A;afii10059;CYRILLIC CAPITAL LETTER NJE +040B;afii10060;CYRILLIC CAPITAL LETTER TSHE +040C;afii10061;CYRILLIC CAPITAL LETTER KJE +040E;afii10062;CYRILLIC CAPITAL LETTER SHORT U +F6C4;afii10063;CYRILLIC SMALL LETTER GHE VARIANT +F6C5;afii10064;CYRILLIC SMALL LETTER BE VARIANT +0430;afii10065;CYRILLIC SMALL LETTER A +0431;afii10066;CYRILLIC SMALL LETTER BE +0432;afii10067;CYRILLIC SMALL LETTER VE +0433;afii10068;CYRILLIC SMALL LETTER GHE +0434;afii10069;CYRILLIC SMALL LETTER DE +0435;afii10070;CYRILLIC SMALL LETTER IE +0451;afii10071;CYRILLIC SMALL LETTER IO +0436;afii10072;CYRILLIC SMALL LETTER ZHE +0437;afii10073;CYRILLIC SMALL LETTER ZE +0438;afii10074;CYRILLIC SMALL LETTER I +0439;afii10075;CYRILLIC SMALL LETTER SHORT I +043A;afii10076;CYRILLIC SMALL LETTER KA +043B;afii10077;CYRILLIC SMALL LETTER EL +043C;afii10078;CYRILLIC SMALL LETTER EM +043D;afii10079;CYRILLIC SMALL LETTER EN +043E;afii10080;CYRILLIC SMALL LETTER O +043F;afii10081;CYRILLIC SMALL LETTER PE +0440;afii10082;CYRILLIC SMALL LETTER ER +0441;afii10083;CYRILLIC SMALL LETTER ES +0442;afii10084;CYRILLIC SMALL LETTER TE +0443;afii10085;CYRILLIC SMALL LETTER U +0444;afii10086;CYRILLIC SMALL LETTER EF +0445;afii10087;CYRILLIC SMALL LETTER HA +0446;afii10088;CYRILLIC SMALL LETTER TSE +0447;afii10089;CYRILLIC SMALL LETTER CHE +0448;afii10090;CYRILLIC SMALL LETTER SHA +0449;afii10091;CYRILLIC SMALL LETTER SHCHA +044A;afii10092;CYRILLIC SMALL LETTER HARD SIGN +044B;afii10093;CYRILLIC SMALL LETTER YERU +044C;afii10094;CYRILLIC SMALL LETTER SOFT SIGN +044D;afii10095;CYRILLIC SMALL LETTER E +044E;afii10096;CYRILLIC SMALL LETTER YU +044F;afii10097;CYRILLIC SMALL LETTER YA +0491;afii10098;CYRILLIC SMALL LETTER GHE WITH UPTURN +0452;afii10099;CYRILLIC SMALL LETTER DJE +0453;afii10100;CYRILLIC SMALL LETTER GJE +0454;afii10101;CYRILLIC SMALL LETTER UKRAINIAN IE +0455;afii10102;CYRILLIC SMALL LETTER DZE +0456;afii10103;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I +0457;afii10104;CYRILLIC SMALL LETTER YI +0458;afii10105;CYRILLIC SMALL LETTER JE +0459;afii10106;CYRILLIC SMALL LETTER LJE +045A;afii10107;CYRILLIC SMALL LETTER NJE +045B;afii10108;CYRILLIC SMALL LETTER TSHE +045C;afii10109;CYRILLIC SMALL LETTER KJE +045E;afii10110;CYRILLIC SMALL LETTER SHORT U +040F;afii10145;CYRILLIC CAPITAL LETTER DZHE +0462;afii10146;CYRILLIC CAPITAL LETTER YAT +0472;afii10147;CYRILLIC CAPITAL LETTER FITA +0474;afii10148;CYRILLIC CAPITAL LETTER IZHITSA +F6C6;afii10192;CYRILLIC SMALL LETTER DE VARIANT +045F;afii10193;CYRILLIC SMALL LETTER DZHE +0463;afii10194;CYRILLIC SMALL LETTER YAT +0473;afii10195;CYRILLIC SMALL LETTER FITA +0475;afii10196;CYRILLIC SMALL LETTER IZHITSA +F6C7;afii10831;CYRILLIC SMALL LETTER PE VARIANT +F6C8;afii10832;CYRILLIC SMALL LETTER TE VARIANT +04D9;afii10846;CYRILLIC SMALL LETTER SCHWA +200E;afii299;LEFT-TO-RIGHT MARK +200F;afii300;RIGHT-TO-LEFT MARK +200D;afii301;ZERO WIDTH JOINER +066A;afii57381;ARABIC PERCENT SIGN +060C;afii57388;ARABIC COMMA +0660;afii57392;ARABIC-INDIC DIGIT ZERO +0661;afii57393;ARABIC-INDIC DIGIT ONE +0662;afii57394;ARABIC-INDIC DIGIT TWO +0663;afii57395;ARABIC-INDIC DIGIT THREE +0664;afii57396;ARABIC-INDIC DIGIT FOUR +0665;afii57397;ARABIC-INDIC DIGIT FIVE +0666;afii57398;ARABIC-INDIC DIGIT SIX +0667;afii57399;ARABIC-INDIC DIGIT SEVEN +0668;afii57400;ARABIC-INDIC DIGIT EIGHT +0669;afii57401;ARABIC-INDIC DIGIT NINE +061B;afii57403;ARABIC SEMICOLON +061F;afii57407;ARABIC QUESTION MARK +0621;afii57409;ARABIC LETTER HAMZA +0622;afii57410;ARABIC LETTER ALEF WITH MADDA ABOVE +0623;afii57411;ARABIC LETTER ALEF WITH HAMZA ABOVE +0624;afii57412;ARABIC LETTER WAW WITH HAMZA ABOVE +0625;afii57413;ARABIC LETTER ALEF WITH HAMZA BELOW +0626;afii57414;ARABIC LETTER YEH WITH HAMZA ABOVE +0627;afii57415;ARABIC LETTER ALEF +0628;afii57416;ARABIC LETTER BEH +0629;afii57417;ARABIC LETTER TEH MARBUTA +062A;afii57418;ARABIC LETTER TEH +062B;afii57419;ARABIC LETTER THEH +062C;afii57420;ARABIC LETTER JEEM +062D;afii57421;ARABIC LETTER HAH +062E;afii57422;ARABIC LETTER KHAH +062F;afii57423;ARABIC LETTER DAL +0630;afii57424;ARABIC LETTER THAL +0631;afii57425;ARABIC LETTER REH +0632;afii57426;ARABIC LETTER ZAIN +0633;afii57427;ARABIC LETTER SEEN +0634;afii57428;ARABIC LETTER SHEEN +0635;afii57429;ARABIC LETTER SAD +0636;afii57430;ARABIC LETTER DAD +0637;afii57431;ARABIC LETTER TAH +0638;afii57432;ARABIC LETTER ZAH +0639;afii57433;ARABIC LETTER AIN +063A;afii57434;ARABIC LETTER GHAIN +0640;afii57440;ARABIC TATWEEL +0641;afii57441;ARABIC LETTER FEH +0642;afii57442;ARABIC LETTER QAF +0643;afii57443;ARABIC LETTER KAF +0644;afii57444;ARABIC LETTER LAM +0645;afii57445;ARABIC LETTER MEEM +0646;afii57446;ARABIC LETTER NOON +0648;afii57448;ARABIC LETTER WAW +0649;afii57449;ARABIC LETTER ALEF MAKSURA +064A;afii57450;ARABIC LETTER YEH +064B;afii57451;ARABIC FATHATAN +064C;afii57452;ARABIC DAMMATAN +064D;afii57453;ARABIC KASRATAN +064E;afii57454;ARABIC FATHA +064F;afii57455;ARABIC DAMMA +0650;afii57456;ARABIC KASRA +0651;afii57457;ARABIC SHADDA +0652;afii57458;ARABIC SUKUN +0647;afii57470;ARABIC LETTER HEH +06A4;afii57505;ARABIC LETTER VEH +067E;afii57506;ARABIC LETTER PEH +0686;afii57507;ARABIC LETTER TCHEH +0698;afii57508;ARABIC LETTER JEH +06AF;afii57509;ARABIC LETTER GAF +0679;afii57511;ARABIC LETTER TTEH +0688;afii57512;ARABIC LETTER DDAL +0691;afii57513;ARABIC LETTER RREH +06BA;afii57514;ARABIC LETTER NOON GHUNNA +06D2;afii57519;ARABIC LETTER YEH BARREE +06D5;afii57534;ARABIC LETTER AE +20AA;afii57636;NEW SHEQEL SIGN +05BE;afii57645;HEBREW PUNCTUATION MAQAF +05C3;afii57658;HEBREW PUNCTUATION SOF PASUQ +05D0;afii57664;HEBREW LETTER ALEF +05D1;afii57665;HEBREW LETTER BET +05D2;afii57666;HEBREW LETTER GIMEL +05D3;afii57667;HEBREW LETTER DALET +05D4;afii57668;HEBREW LETTER HE +05D5;afii57669;HEBREW LETTER VAV +05D6;afii57670;HEBREW LETTER ZAYIN +05D7;afii57671;HEBREW LETTER HET +05D8;afii57672;HEBREW LETTER TET +05D9;afii57673;HEBREW LETTER YOD +05DA;afii57674;HEBREW LETTER FINAL KAF +05DB;afii57675;HEBREW LETTER KAF +05DC;afii57676;HEBREW LETTER LAMED +05DD;afii57677;HEBREW LETTER FINAL MEM +05DE;afii57678;HEBREW LETTER MEM +05DF;afii57679;HEBREW LETTER FINAL NUN +05E0;afii57680;HEBREW LETTER NUN +05E1;afii57681;HEBREW LETTER SAMEKH +05E2;afii57682;HEBREW LETTER AYIN +05E3;afii57683;HEBREW LETTER FINAL PE +05E4;afii57684;HEBREW LETTER PE +05E5;afii57685;HEBREW LETTER FINAL TSADI +05E6;afii57686;HEBREW LETTER TSADI +05E7;afii57687;HEBREW LETTER QOF +05E8;afii57688;HEBREW LETTER RESH +05E9;afii57689;HEBREW LETTER SHIN +05EA;afii57690;HEBREW LETTER TAV +FB2A;afii57694;HEBREW LETTER SHIN WITH SHIN DOT +FB2B;afii57695;HEBREW LETTER SHIN WITH SIN DOT +FB4B;afii57700;HEBREW LETTER VAV WITH HOLAM +FB1F;afii57705;HEBREW LIGATURE YIDDISH YOD YOD PATAH +05F0;afii57716;HEBREW LIGATURE YIDDISH DOUBLE VAV +05F1;afii57717;HEBREW LIGATURE YIDDISH VAV YOD +05F2;afii57718;HEBREW LIGATURE YIDDISH DOUBLE YOD +FB35;afii57723;HEBREW LETTER VAV WITH DAGESH +05B4;afii57793;HEBREW POINT HIRIQ +05B5;afii57794;HEBREW POINT TSERE +05B6;afii57795;HEBREW POINT SEGOL +05BB;afii57796;HEBREW POINT QUBUTS +05B8;afii57797;HEBREW POINT QAMATS +05B7;afii57798;HEBREW POINT PATAH +05B0;afii57799;HEBREW POINT SHEVA +05B2;afii57800;HEBREW POINT HATAF PATAH +05B1;afii57801;HEBREW POINT HATAF SEGOL +05B3;afii57802;HEBREW POINT HATAF QAMATS +05C2;afii57803;HEBREW POINT SIN DOT +05C1;afii57804;HEBREW POINT SHIN DOT +05B9;afii57806;HEBREW POINT HOLAM +05BC;afii57807;HEBREW POINT DAGESH OR MAPIQ +05BD;afii57839;HEBREW POINT METEG +05BF;afii57841;HEBREW POINT RAFE +05C0;afii57842;HEBREW PUNCTUATION PASEQ +02BC;afii57929;MODIFIER LETTER APOSTROPHE +2105;afii61248;CARE OF +2113;afii61289;SCRIPT SMALL L +2116;afii61352;NUMERO SIGN +202C;afii61573;POP DIRECTIONAL FORMATTING +202D;afii61574;LEFT-TO-RIGHT OVERRIDE +202E;afii61575;RIGHT-TO-LEFT OVERRIDE +200C;afii61664;ZERO WIDTH NON-JOINER +066D;afii63167;ARABIC FIVE POINTED STAR +02BD;afii64937;MODIFIER LETTER REVERSED COMMA +00E0;agrave;LATIN SMALL LETTER A WITH GRAVE +2135;aleph;ALEF SYMBOL +03B1;alpha;GREEK SMALL LETTER ALPHA +03AC;alphatonos;GREEK SMALL LETTER ALPHA WITH TONOS +0101;amacron;LATIN SMALL LETTER A WITH MACRON +0026;ampersand;AMPERSAND +F726;ampersandsmall;SMALL CAPITAL AMPERSAND +2220;angle;ANGLE +2329;angleleft;LEFT-POINTING ANGLE BRACKET +232A;angleright;RIGHT-POINTING ANGLE BRACKET +0387;anoteleia;GREEK ANO TELEIA +0105;aogonek;LATIN SMALL LETTER A WITH OGONEK +2248;approxequal;ALMOST EQUAL TO +00E5;aring;LATIN SMALL LETTER A WITH RING ABOVE +01FB;aringacute;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE +2194;arrowboth;LEFT RIGHT ARROW +21D4;arrowdblboth;LEFT RIGHT DOUBLE ARROW +21D3;arrowdbldown;DOWNWARDS DOUBLE ARROW +21D0;arrowdblleft;LEFTWARDS DOUBLE ARROW +21D2;arrowdblright;RIGHTWARDS DOUBLE ARROW +21D1;arrowdblup;UPWARDS DOUBLE ARROW +2193;arrowdown;DOWNWARDS ARROW +F8E7;arrowhorizex;HORIZONTAL ARROW EXTENDER +2190;arrowleft;LEFTWARDS ARROW +2192;arrowright;RIGHTWARDS ARROW +2191;arrowup;UPWARDS ARROW +2195;arrowupdn;UP DOWN ARROW +21A8;arrowupdnbse;UP DOWN ARROW WITH BASE +F8E6;arrowvertex;VERTICAL ARROW EXTENDER +005E;asciicircum;CIRCUMFLEX ACCENT +007E;asciitilde;TILDE +002A;asterisk;ASTERISK +2217;asteriskmath;ASTERISK OPERATOR +F6E9;asuperior;SUPERSCRIPT LATIN SMALL LETTER A +0040;at;COMMERCIAL AT +00E3;atilde;LATIN SMALL LETTER A WITH TILDE +0062;b;LATIN SMALL LETTER B +005C;backslash;REVERSE SOLIDUS +007C;bar;VERTICAL LINE +03B2;beta;GREEK SMALL LETTER BETA +2588;block;FULL BLOCK +F8F4;braceex;CURLY BRACKET EXTENDER +007B;braceleft;LEFT CURLY BRACKET +F8F3;braceleftbt;LEFT CURLY BRACKET BOTTOM +F8F2;braceleftmid;LEFT CURLY BRACKET MID +F8F1;bracelefttp;LEFT CURLY BRACKET TOP +007D;braceright;RIGHT CURLY BRACKET +F8FE;bracerightbt;RIGHT CURLY BRACKET BOTTOM +F8FD;bracerightmid;RIGHT CURLY BRACKET MID +F8FC;bracerighttp;RIGHT CURLY BRACKET TOP +005B;bracketleft;LEFT SQUARE BRACKET +F8F0;bracketleftbt;LEFT SQUARE BRACKET BOTTOM +F8EF;bracketleftex;LEFT SQUARE BRACKET EXTENDER +F8EE;bracketlefttp;LEFT SQUARE BRACKET TOP +005D;bracketright;RIGHT SQUARE BRACKET +F8FB;bracketrightbt;RIGHT SQUARE BRACKET BOTTOM +F8FA;bracketrightex;RIGHT SQUARE BRACKET EXTENDER +F8F9;bracketrighttp;RIGHT SQUARE BRACKET TOP +02D8;breve;BREVE +00A6;brokenbar;BROKEN BAR +F6EA;bsuperior;SUPERSCRIPT LATIN SMALL LETTER B +2022;bullet;BULLET +0063;c;LATIN SMALL LETTER C +0107;cacute;LATIN SMALL LETTER C WITH ACUTE +02C7;caron;CARON +21B5;carriagereturn;DOWNWARDS ARROW WITH CORNER LEFTWARDS +010D;ccaron;LATIN SMALL LETTER C WITH CARON +00E7;ccedilla;LATIN SMALL LETTER C WITH CEDILLA +0109;ccircumflex;LATIN SMALL LETTER C WITH CIRCUMFLEX +010B;cdotaccent;LATIN SMALL LETTER C WITH DOT ABOVE +00B8;cedilla;CEDILLA +00A2;cent;CENT SIGN +F6DF;centinferior;SUBSCRIPT CENT SIGN +F7A2;centoldstyle;OLDSTYLE CENT SIGN +F6E0;centsuperior;SUPERSCRIPT CENT SIGN +03C7;chi;GREEK SMALL LETTER CHI +25CB;circle;WHITE CIRCLE +2297;circlemultiply;CIRCLED TIMES +2295;circleplus;CIRCLED PLUS +02C6;circumflex;MODIFIER LETTER CIRCUMFLEX ACCENT +2663;club;BLACK CLUB SUIT +003A;colon;COLON +20A1;colonmonetary;COLON SIGN +002C;comma;COMMA +F6C3;commaaccent;COMMA BELOW +F6E1;commainferior;SUBSCRIPT COMMA +F6E2;commasuperior;SUPERSCRIPT COMMA +2245;congruent;APPROXIMATELY EQUAL TO +00A9;copyright;COPYRIGHT SIGN +F8E9;copyrightsans;COPYRIGHT SIGN SANS SERIF +F6D9;copyrightserif;COPYRIGHT SIGN SERIF +00A4;currency;CURRENCY SIGN +F6D1;cyrBreve;CAPITAL CYRILLIC BREVE +F6D2;cyrFlex;CAPITAL CYRILLIC CIRCUMFLEX +F6D4;cyrbreve;CYRILLIC BREVE +F6D5;cyrflex;CYRILLIC CIRCUMFLEX +0064;d;LATIN SMALL LETTER D +2020;dagger;DAGGER +2021;daggerdbl;DOUBLE DAGGER +F6D3;dblGrave;CAPITAL DOUBLE GRAVE ACCENT +F6D6;dblgrave;DOUBLE GRAVE ACCENT +010F;dcaron;LATIN SMALL LETTER D WITH CARON +0111;dcroat;LATIN SMALL LETTER D WITH STROKE +00B0;degree;DEGREE SIGN +03B4;delta;GREEK SMALL LETTER DELTA +2666;diamond;BLACK DIAMOND SUIT +00A8;dieresis;DIAERESIS +F6D7;dieresisacute;DIAERESIS ACUTE ACCENT +F6D8;dieresisgrave;DIAERESIS GRAVE ACCENT +0385;dieresistonos;GREEK DIALYTIKA TONOS +00F7;divide;DIVISION SIGN +2593;dkshade;DARK SHADE +2584;dnblock;LOWER HALF BLOCK +0024;dollar;DOLLAR SIGN +F6E3;dollarinferior;SUBSCRIPT DOLLAR SIGN +F724;dollaroldstyle;OLDSTYLE DOLLAR SIGN +F6E4;dollarsuperior;SUPERSCRIPT DOLLAR SIGN +20AB;dong;DONG SIGN +02D9;dotaccent;DOT ABOVE +0323;dotbelowcomb;COMBINING DOT BELOW +0131;dotlessi;LATIN SMALL LETTER DOTLESS I +F6BE;dotlessj;LATIN SMALL LETTER DOTLESS J +22C5;dotmath;DOT OPERATOR +F6EB;dsuperior;SUPERSCRIPT LATIN SMALL LETTER D +0065;e;LATIN SMALL LETTER E +00E9;eacute;LATIN SMALL LETTER E WITH ACUTE +0115;ebreve;LATIN SMALL LETTER E WITH BREVE +011B;ecaron;LATIN SMALL LETTER E WITH CARON +00EA;ecircumflex;LATIN SMALL LETTER E WITH CIRCUMFLEX +00EB;edieresis;LATIN SMALL LETTER E WITH DIAERESIS +0117;edotaccent;LATIN SMALL LETTER E WITH DOT ABOVE +00E8;egrave;LATIN SMALL LETTER E WITH GRAVE +0038;eight;DIGIT EIGHT +2088;eightinferior;SUBSCRIPT EIGHT +F738;eightoldstyle;OLDSTYLE DIGIT EIGHT +2078;eightsuperior;SUPERSCRIPT EIGHT +2208;element;ELEMENT OF +2026;ellipsis;HORIZONTAL ELLIPSIS +0113;emacron;LATIN SMALL LETTER E WITH MACRON +2014;emdash;EM DASH +2205;emptyset;EMPTY SET +2013;endash;EN DASH +014B;eng;LATIN SMALL LETTER ENG +0119;eogonek;LATIN SMALL LETTER E WITH OGONEK +03B5;epsilon;GREEK SMALL LETTER EPSILON +03AD;epsilontonos;GREEK SMALL LETTER EPSILON WITH TONOS +003D;equal;EQUALS SIGN +2261;equivalence;IDENTICAL TO +212E;estimated;ESTIMATED SYMBOL +F6EC;esuperior;SUPERSCRIPT LATIN SMALL LETTER E +03B7;eta;GREEK SMALL LETTER ETA +03AE;etatonos;GREEK SMALL LETTER ETA WITH TONOS +00F0;eth;LATIN SMALL LETTER ETH +0021;exclam;EXCLAMATION MARK +203C;exclamdbl;DOUBLE EXCLAMATION MARK +00A1;exclamdown;INVERTED EXCLAMATION MARK +F7A1;exclamdownsmall;SMALL CAPITAL INVERTED EXCLAMATION MARK +F721;exclamsmall;SMALL CAPITAL EXCLAMATION MARK +2203;existential;THERE EXISTS +0066;f;LATIN SMALL LETTER F +2640;female;FEMALE SIGN +FB00;ff;LATIN SMALL LIGATURE FF +FB03;ffi;LATIN SMALL LIGATURE FFI +FB04;ffl;LATIN SMALL LIGATURE FFL +FB01;fi;LATIN SMALL LIGATURE FI +2012;figuredash;FIGURE DASH +25A0;filledbox;BLACK SQUARE +25AC;filledrect;BLACK RECTANGLE +0035;five;DIGIT FIVE +215D;fiveeighths;VULGAR FRACTION FIVE EIGHTHS +2085;fiveinferior;SUBSCRIPT FIVE +F735;fiveoldstyle;OLDSTYLE DIGIT FIVE +2075;fivesuperior;SUPERSCRIPT FIVE +FB02;fl;LATIN SMALL LIGATURE FL +0192;florin;LATIN SMALL LETTER F WITH HOOK +0034;four;DIGIT FOUR +2084;fourinferior;SUBSCRIPT FOUR +F734;fouroldstyle;OLDSTYLE DIGIT FOUR +2074;foursuperior;SUPERSCRIPT FOUR +2044;fraction;FRACTION SLASH +2215;fraction;DIVISION SLASH;Duplicate +20A3;franc;FRENCH FRANC SIGN +0067;g;LATIN SMALL LETTER G +03B3;gamma;GREEK SMALL LETTER GAMMA +011F;gbreve;LATIN SMALL LETTER G WITH BREVE +01E7;gcaron;LATIN SMALL LETTER G WITH CARON +011D;gcircumflex;LATIN SMALL LETTER G WITH CIRCUMFLEX +0123;gcommaaccent;LATIN SMALL LETTER G WITH CEDILLA +0121;gdotaccent;LATIN SMALL LETTER G WITH DOT ABOVE +00DF;germandbls;LATIN SMALL LETTER SHARP S +2207;gradient;NABLA +0060;grave;GRAVE ACCENT +0300;gravecomb;COMBINING GRAVE ACCENT +003E;greater;GREATER-THAN SIGN +2265;greaterequal;GREATER-THAN OR EQUAL TO +00AB;guillemotleft;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK +00BB;guillemotright;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK +2039;guilsinglleft;SINGLE LEFT-POINTING ANGLE QUOTATION MARK +203A;guilsinglright;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK +0068;h;LATIN SMALL LETTER H +0127;hbar;LATIN SMALL LETTER H WITH STROKE +0125;hcircumflex;LATIN SMALL LETTER H WITH CIRCUMFLEX +2665;heart;BLACK HEART SUIT +0309;hookabovecomb;COMBINING HOOK ABOVE +2302;house;HOUSE +02DD;hungarumlaut;DOUBLE ACUTE ACCENT +002D;hyphen;HYPHEN-MINUS +00AD;hyphen;SOFT HYPHEN;Duplicate +F6E5;hypheninferior;SUBSCRIPT HYPHEN-MINUS +F6E6;hyphensuperior;SUPERSCRIPT HYPHEN-MINUS +0069;i;LATIN SMALL LETTER I +00ED;iacute;LATIN SMALL LETTER I WITH ACUTE +012D;ibreve;LATIN SMALL LETTER I WITH BREVE +00EE;icircumflex;LATIN SMALL LETTER I WITH CIRCUMFLEX +00EF;idieresis;LATIN SMALL LETTER I WITH DIAERESIS +00EC;igrave;LATIN SMALL LETTER I WITH GRAVE +0133;ij;LATIN SMALL LIGATURE IJ +012B;imacron;LATIN SMALL LETTER I WITH MACRON +221E;infinity;INFINITY +222B;integral;INTEGRAL +2321;integralbt;BOTTOM HALF INTEGRAL +F8F5;integralex;INTEGRAL EXTENDER +2320;integraltp;TOP HALF INTEGRAL +2229;intersection;INTERSECTION +25D8;invbullet;INVERSE BULLET +25D9;invcircle;INVERSE WHITE CIRCLE +263B;invsmileface;BLACK SMILING FACE +012F;iogonek;LATIN SMALL LETTER I WITH OGONEK +03B9;iota;GREEK SMALL LETTER IOTA +03CA;iotadieresis;GREEK SMALL LETTER IOTA WITH DIALYTIKA +0390;iotadieresistonos;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS +03AF;iotatonos;GREEK SMALL LETTER IOTA WITH TONOS +F6ED;isuperior;SUPERSCRIPT LATIN SMALL LETTER I +0129;itilde;LATIN SMALL LETTER I WITH TILDE +006A;j;LATIN SMALL LETTER J +0135;jcircumflex;LATIN SMALL LETTER J WITH CIRCUMFLEX +006B;k;LATIN SMALL LETTER K +03BA;kappa;GREEK SMALL LETTER KAPPA +0137;kcommaaccent;LATIN SMALL LETTER K WITH CEDILLA +0138;kgreenlandic;LATIN SMALL LETTER KRA +006C;l;LATIN SMALL LETTER L +013A;lacute;LATIN SMALL LETTER L WITH ACUTE +03BB;lambda;GREEK SMALL LETTER LAMDA +013E;lcaron;LATIN SMALL LETTER L WITH CARON +013C;lcommaaccent;LATIN SMALL LETTER L WITH CEDILLA +0140;ldot;LATIN SMALL LETTER L WITH MIDDLE DOT +003C;less;LESS-THAN SIGN +2264;lessequal;LESS-THAN OR EQUAL TO +258C;lfblock;LEFT HALF BLOCK +20A4;lira;LIRA SIGN +F6C0;ll;LATIN SMALL LETTER LL +2227;logicaland;LOGICAL AND +00AC;logicalnot;NOT SIGN +2228;logicalor;LOGICAL OR +017F;longs;LATIN SMALL LETTER LONG S +25CA;lozenge;LOZENGE +0142;lslash;LATIN SMALL LETTER L WITH STROKE +F6EE;lsuperior;SUPERSCRIPT LATIN SMALL LETTER L +2591;ltshade;LIGHT SHADE +006D;m;LATIN SMALL LETTER M +00AF;macron;MACRON +02C9;macron;MODIFIER LETTER MACRON;Duplicate +2642;male;MALE SIGN +2212;minus;MINUS SIGN +2032;minute;PRIME +F6EF;msuperior;SUPERSCRIPT LATIN SMALL LETTER M +00B5;mu;MICRO SIGN +03BC;mu;GREEK SMALL LETTER MU;Duplicate +00D7;multiply;MULTIPLICATION SIGN +266A;musicalnote;EIGHTH NOTE +266B;musicalnotedbl;BEAMED EIGHTH NOTES +006E;n;LATIN SMALL LETTER N +0144;nacute;LATIN SMALL LETTER N WITH ACUTE +0149;napostrophe;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE +0148;ncaron;LATIN SMALL LETTER N WITH CARON +0146;ncommaaccent;LATIN SMALL LETTER N WITH CEDILLA +0039;nine;DIGIT NINE +2089;nineinferior;SUBSCRIPT NINE +F739;nineoldstyle;OLDSTYLE DIGIT NINE +2079;ninesuperior;SUPERSCRIPT NINE +2209;notelement;NOT AN ELEMENT OF +2260;notequal;NOT EQUAL TO +2284;notsubset;NOT A SUBSET OF +207F;nsuperior;SUPERSCRIPT LATIN SMALL LETTER N +00F1;ntilde;LATIN SMALL LETTER N WITH TILDE +03BD;nu;GREEK SMALL LETTER NU +0023;numbersign;NUMBER SIGN +006F;o;LATIN SMALL LETTER O +00F3;oacute;LATIN SMALL LETTER O WITH ACUTE +014F;obreve;LATIN SMALL LETTER O WITH BREVE +00F4;ocircumflex;LATIN SMALL LETTER O WITH CIRCUMFLEX +00F6;odieresis;LATIN SMALL LETTER O WITH DIAERESIS +0153;oe;LATIN SMALL LIGATURE OE +02DB;ogonek;OGONEK +00F2;ograve;LATIN SMALL LETTER O WITH GRAVE +01A1;ohorn;LATIN SMALL LETTER O WITH HORN +0151;ohungarumlaut;LATIN SMALL LETTER O WITH DOUBLE ACUTE +014D;omacron;LATIN SMALL LETTER O WITH MACRON +03C9;omega;GREEK SMALL LETTER OMEGA +03D6;omega1;GREEK PI SYMBOL +03CE;omegatonos;GREEK SMALL LETTER OMEGA WITH TONOS +03BF;omicron;GREEK SMALL LETTER OMICRON +03CC;omicrontonos;GREEK SMALL LETTER OMICRON WITH TONOS +0031;one;DIGIT ONE +2024;onedotenleader;ONE DOT LEADER +215B;oneeighth;VULGAR FRACTION ONE EIGHTH +F6DC;onefitted;PROPORTIONAL DIGIT ONE +00BD;onehalf;VULGAR FRACTION ONE HALF +2081;oneinferior;SUBSCRIPT ONE +F731;oneoldstyle;OLDSTYLE DIGIT ONE +00BC;onequarter;VULGAR FRACTION ONE QUARTER +00B9;onesuperior;SUPERSCRIPT ONE +2153;onethird;VULGAR FRACTION ONE THIRD +25E6;openbullet;WHITE BULLET +00AA;ordfeminine;FEMININE ORDINAL INDICATOR +00BA;ordmasculine;MASCULINE ORDINAL INDICATOR +221F;orthogonal;RIGHT ANGLE +00F8;oslash;LATIN SMALL LETTER O WITH STROKE +01FF;oslashacute;LATIN SMALL LETTER O WITH STROKE AND ACUTE +F6F0;osuperior;SUPERSCRIPT LATIN SMALL LETTER O +00F5;otilde;LATIN SMALL LETTER O WITH TILDE +0070;p;LATIN SMALL LETTER P +00B6;paragraph;PILCROW SIGN +0028;parenleft;LEFT PARENTHESIS +F8ED;parenleftbt;LEFT PAREN BOTTOM +F8EC;parenleftex;LEFT PAREN EXTENDER +208D;parenleftinferior;SUBSCRIPT LEFT PARENTHESIS +207D;parenleftsuperior;SUPERSCRIPT LEFT PARENTHESIS +F8EB;parenlefttp;LEFT PAREN TOP +0029;parenright;RIGHT PARENTHESIS +F8F8;parenrightbt;RIGHT PAREN BOTTOM +F8F7;parenrightex;RIGHT PAREN EXTENDER +208E;parenrightinferior;SUBSCRIPT RIGHT PARENTHESIS +207E;parenrightsuperior;SUPERSCRIPT RIGHT PARENTHESIS +F8F6;parenrighttp;RIGHT PAREN TOP +2202;partialdiff;PARTIAL DIFFERENTIAL +0025;percent;PERCENT SIGN +002E;period;FULL STOP +00B7;periodcentered;MIDDLE DOT +2219;periodcentered;BULLET OPERATOR;Duplicate +F6E7;periodinferior;SUBSCRIPT FULL STOP +F6E8;periodsuperior;SUPERSCRIPT FULL STOP +22A5;perpendicular;UP TACK +2030;perthousand;PER MILLE SIGN +20A7;peseta;PESETA SIGN +03C6;phi;GREEK SMALL LETTER PHI +03D5;phi1;GREEK PHI SYMBOL +03C0;pi;GREEK SMALL LETTER PI +002B;plus;PLUS SIGN +00B1;plusminus;PLUS-MINUS SIGN +211E;prescription;PRESCRIPTION TAKE +220F;product;N-ARY PRODUCT +2282;propersubset;SUBSET OF +2283;propersuperset;SUPERSET OF +221D;proportional;PROPORTIONAL TO +03C8;psi;GREEK SMALL LETTER PSI +0071;q;LATIN SMALL LETTER Q +003F;question;QUESTION MARK +00BF;questiondown;INVERTED QUESTION MARK +F7BF;questiondownsmall;SMALL CAPITAL INVERTED QUESTION MARK +F73F;questionsmall;SMALL CAPITAL QUESTION MARK +0022;quotedbl;QUOTATION MARK +201E;quotedblbase;DOUBLE LOW-9 QUOTATION MARK +201C;quotedblleft;LEFT DOUBLE QUOTATION MARK +201D;quotedblright;RIGHT DOUBLE QUOTATION MARK +2018;quoteleft;LEFT SINGLE QUOTATION MARK +201B;quotereversed;SINGLE HIGH-REVERSED-9 QUOTATION MARK +2019;quoteright;RIGHT SINGLE QUOTATION MARK +201A;quotesinglbase;SINGLE LOW-9 QUOTATION MARK +0027;quotesingle;APOSTROPHE +0072;r;LATIN SMALL LETTER R +0155;racute;LATIN SMALL LETTER R WITH ACUTE +221A;radical;SQUARE ROOT +F8E5;radicalex;RADICAL EXTENDER +0159;rcaron;LATIN SMALL LETTER R WITH CARON +0157;rcommaaccent;LATIN SMALL LETTER R WITH CEDILLA +2286;reflexsubset;SUBSET OF OR EQUAL TO +2287;reflexsuperset;SUPERSET OF OR EQUAL TO +00AE;registered;REGISTERED SIGN +F8E8;registersans;REGISTERED SIGN SANS SERIF +F6DA;registerserif;REGISTERED SIGN SERIF +2310;revlogicalnot;REVERSED NOT SIGN +03C1;rho;GREEK SMALL LETTER RHO +02DA;ring;RING ABOVE +F6F1;rsuperior;SUPERSCRIPT LATIN SMALL LETTER R +2590;rtblock;RIGHT HALF BLOCK +F6DD;rupiah;RUPIAH SIGN +0073;s;LATIN SMALL LETTER S +015B;sacute;LATIN SMALL LETTER S WITH ACUTE +0161;scaron;LATIN SMALL LETTER S WITH CARON +015F;scedilla;LATIN SMALL LETTER S WITH CEDILLA +F6C2;scedilla;LATIN SMALL LETTER S WITH CEDILLA;Duplicate +015D;scircumflex;LATIN SMALL LETTER S WITH CIRCUMFLEX +0219;scommaaccent;LATIN SMALL LETTER S WITH COMMA BELOW +2033;second;DOUBLE PRIME +00A7;section;SECTION SIGN +003B;semicolon;SEMICOLON +0037;seven;DIGIT SEVEN +215E;seveneighths;VULGAR FRACTION SEVEN EIGHTHS +2087;seveninferior;SUBSCRIPT SEVEN +F737;sevenoldstyle;OLDSTYLE DIGIT SEVEN +2077;sevensuperior;SUPERSCRIPT SEVEN +2592;shade;MEDIUM SHADE +03C3;sigma;GREEK SMALL LETTER SIGMA +03C2;sigma1;GREEK SMALL LETTER FINAL SIGMA +223C;similar;TILDE OPERATOR +0036;six;DIGIT SIX +2086;sixinferior;SUBSCRIPT SIX +F736;sixoldstyle;OLDSTYLE DIGIT SIX +2076;sixsuperior;SUPERSCRIPT SIX +002F;slash;SOLIDUS +263A;smileface;WHITE SMILING FACE +0020;space;SPACE +00A0;space;NO-BREAK SPACE;Duplicate +2660;spade;BLACK SPADE SUIT +F6F2;ssuperior;SUPERSCRIPT LATIN SMALL LETTER S +00A3;sterling;POUND SIGN +220B;suchthat;CONTAINS AS MEMBER +2211;summation;N-ARY SUMMATION +263C;sun;WHITE SUN WITH RAYS +0074;t;LATIN SMALL LETTER T +03C4;tau;GREEK SMALL LETTER TAU +0167;tbar;LATIN SMALL LETTER T WITH STROKE +0165;tcaron;LATIN SMALL LETTER T WITH CARON +0163;tcommaaccent;LATIN SMALL LETTER T WITH CEDILLA +021B;tcommaaccent;LATIN SMALL LETTER T WITH COMMA BELOW;Duplicate +2234;therefore;THEREFORE +03B8;theta;GREEK SMALL LETTER THETA +03D1;theta1;GREEK THETA SYMBOL +00FE;thorn;LATIN SMALL LETTER THORN +0033;three;DIGIT THREE +215C;threeeighths;VULGAR FRACTION THREE EIGHTHS +2083;threeinferior;SUBSCRIPT THREE +F733;threeoldstyle;OLDSTYLE DIGIT THREE +00BE;threequarters;VULGAR FRACTION THREE QUARTERS +F6DE;threequartersemdash;THREE QUARTERS EM DASH +00B3;threesuperior;SUPERSCRIPT THREE +02DC;tilde;SMALL TILDE +0303;tildecomb;COMBINING TILDE +0384;tonos;GREEK TONOS +2122;trademark;TRADE MARK SIGN +F8EA;trademarksans;TRADE MARK SIGN SANS SERIF +F6DB;trademarkserif;TRADE MARK SIGN SERIF +25BC;triagdn;BLACK DOWN-POINTING TRIANGLE +25C4;triaglf;BLACK LEFT-POINTING POINTER +25BA;triagrt;BLACK RIGHT-POINTING POINTER +25B2;triagup;BLACK UP-POINTING TRIANGLE +F6F3;tsuperior;SUPERSCRIPT LATIN SMALL LETTER T +0032;two;DIGIT TWO +2025;twodotenleader;TWO DOT LEADER +2082;twoinferior;SUBSCRIPT TWO +F732;twooldstyle;OLDSTYLE DIGIT TWO +00B2;twosuperior;SUPERSCRIPT TWO +2154;twothirds;VULGAR FRACTION TWO THIRDS +0075;u;LATIN SMALL LETTER U +00FA;uacute;LATIN SMALL LETTER U WITH ACUTE +016D;ubreve;LATIN SMALL LETTER U WITH BREVE +00FB;ucircumflex;LATIN SMALL LETTER U WITH CIRCUMFLEX +00FC;udieresis;LATIN SMALL LETTER U WITH DIAERESIS +00F9;ugrave;LATIN SMALL LETTER U WITH GRAVE +01B0;uhorn;LATIN SMALL LETTER U WITH HORN +0171;uhungarumlaut;LATIN SMALL LETTER U WITH DOUBLE ACUTE +016B;umacron;LATIN SMALL LETTER U WITH MACRON +005F;underscore;LOW LINE +2017;underscoredbl;DOUBLE LOW LINE +222A;union;UNION +2200;universal;FOR ALL +0173;uogonek;LATIN SMALL LETTER U WITH OGONEK +2580;upblock;UPPER HALF BLOCK +03C5;upsilon;GREEK SMALL LETTER UPSILON +03CB;upsilondieresis;GREEK SMALL LETTER UPSILON WITH DIALYTIKA +03B0;upsilondieresistonos;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS +03CD;upsilontonos;GREEK SMALL LETTER UPSILON WITH TONOS +016F;uring;LATIN SMALL LETTER U WITH RING ABOVE +0169;utilde;LATIN SMALL LETTER U WITH TILDE +0076;v;LATIN SMALL LETTER V +0077;w;LATIN SMALL LETTER W +1E83;wacute;LATIN SMALL LETTER W WITH ACUTE +0175;wcircumflex;LATIN SMALL LETTER W WITH CIRCUMFLEX +1E85;wdieresis;LATIN SMALL LETTER W WITH DIAERESIS +2118;weierstrass;SCRIPT CAPITAL P +1E81;wgrave;LATIN SMALL LETTER W WITH GRAVE +0078;x;LATIN SMALL LETTER X +03BE;xi;GREEK SMALL LETTER XI +0079;y;LATIN SMALL LETTER Y +00FD;yacute;LATIN SMALL LETTER Y WITH ACUTE +0177;ycircumflex;LATIN SMALL LETTER Y WITH CIRCUMFLEX +00FF;ydieresis;LATIN SMALL LETTER Y WITH DIAERESIS +00A5;yen;YEN SIGN +1EF3;ygrave;LATIN SMALL LETTER Y WITH GRAVE +007A;z;LATIN SMALL LETTER Z +017A;zacute;LATIN SMALL LETTER Z WITH ACUTE +017E;zcaron;LATIN SMALL LETTER Z WITH CARON +017C;zdotaccent;LATIN SMALL LETTER Z WITH DOT ABOVE +0030;zero;DIGIT ZERO +2080;zeroinferior;SUBSCRIPT ZERO +F730;zerooldstyle;OLDSTYLE DIGIT ZERO +2070;zerosuperior;SUPERSCRIPT ZERO +03B6;zeta;GREEK SMALL LETTER ZETA +""" + + +t1_bias = 0 +glyph_list = [] + + +def the_adobe_glyph_list(): + """return the list of glyph names in the adobe list""" + + lines = string.split( adobe_glyph_list, '\n' ) + glyphs = [] + + for line in lines: + if line: + fields = string.split( line, ';' ) +# print fields[0] + ' - ' + fields[1] + glyphs.append( fields[1] ) + + return glyphs + + +def the_adobe_glyphs(): + """return the list of unicode values""" + + lines = string.split( adobe_glyph_list, '\n' ) + glyphs = [] + values = [] + + for line in lines: + if line: + fields = string.split( line, ';' ) +# print fields[0] + ' - ' + fields[1] + glyphs.append( fields[1] ) + values.append( fields[0] ) + + return glyphs, values + + +def count_extra_glyphs( alist, filter ): + """count the number of extra glyphs""" + + count = 0 + extras = [] + + for name in alist: + try: + filtered_index = filter.index( name ) + except: + extras.append( name ) + + return extras + + +def dump_mac_indices( file ): + write = file.write + + write( " static const unsigned short mac_standard_names[" + \ + repr( len( mac_standard_names ) + 1 ) + "] =\n" ) + write( " {\n" ) + + count = 0 + for name in mac_standard_names: + try: + t1_index = t1_standard_strings.index( name ) + write( " " + repr( t1_bias + t1_index ) + ",\n" ) + except: + write( " " + repr( count ) + ",\n" ) + count = count + 1 + + write( " 0\n" ) + write( " };\n" ) + write( "\n" ) + write( "\n" ) + + +def dump_glyph_list( file, glyph_list, adobe_extra ): + write = file.write + + name_list = [] + + write( " static const char* standard_glyph_names[] =\n" ) + write( " {\n" ) + + for name in glyph_list: + write( ' "' + name + '",\n' ) + name_list.append( name ) + + write( "\n" ) + write( "#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST\n" ) + write( "\n" ) + + for name in adobe_extra: + write( ' "' + name + '",\n' ) + name_list.append( name ) + + write( "\n" ) + write( "#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */\n" ) + write( "\n" ) + write( " 0\n" ) + write( " };\n" ) + write( "\n" ) + write( "\n" ) + + return name_list + + +def dump_unicode_values( file, base_list, adobe_list ): + """build the glyph names to unicode values table""" + + write = file.write + + adobe_glyphs, uni_values = the_adobe_glyphs() + + write( "\n" ) + write( " static const unsigned short names_to_unicode[" + \ + repr( len( base_list ) + len( adobe_list ) + 1 ) + "] =\n" ) + write( " {\n" ) + + for name in base_list: + try: + index = adobe_glyphs.index( name ) + write( " 0x" + uni_values[index] + ",\n" ) + except: + write( " 0,\n" ) + + write( "\n" ) + write( "#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST\n" ) + write( "\n" ) + + for name in adobe_list: + try: + index = adobe_glyphs.index( name ) + write( " 0x" + uni_values[index] + ",\n" ) + except: + write( " 0,\n" ) + + write( "\n" ) + write( "#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */\n" ) + write( " 0\n" ) + write( " };\n" ) + write( "\n" ) + write( "\n" ) + write( "\n" ) + + +def dump_encoding( file, encoding_name, encoding_list ): + """dumps a given encoding""" + + write = file.write + + write( " static const unsigned short " + encoding_name + "[" + \ + repr( len( encoding_list ) + 1 ) + "] =\n" ) + write( " {\n" ) + + for value in encoding_list: + write( " " + repr( value ) + ",\n" ) + write( " 0\n" ) + write( " };\n" ) + write( "\n" ) + write( "\n" ) + + +def main(): + """main program body""" + + if len( sys.argv ) != 2: + print __doc__ % sys.argv[0] + sys.exit( 1 ) + + file = open( sys.argv[1], "w\n" ) + write = file.write + + count_sid = len( t1_standard_strings ) + + # build mac index table & supplemental glyph names + mac_list = count_extra_glyphs( mac_standard_names, t1_standard_strings ) + count_mac = len( mac_list ) + t1_bias = count_mac + base_list = mac_list + t1_standard_strings + + # build adobe unicode index table & supplemental glyph names + adobe_list = the_adobe_glyph_list() + adobe_list = count_extra_glyphs( adobe_list, base_list ) + count_adobe = len( adobe_list ) + + write( "/***************************************************************************/\n" ) + write( "/* */\n" ) + + write( "/* %-71s*/\n" % sys.argv[1] ) + + write( "/* */\n" ) + write( "/* PostScript glyph names (specification only). */\n" ) + write( "/* */\n" ) + write( "/* Copyright 2000 by */\n" ) + write( "/* David Turner, Robert Wilhelm, and Werner Lemberg. */\n" ) + write( "/* */\n" ) + write( "/* This file is part of the FreeType project, and may only be used, */\n" ) + write( "/* modified, and distributed under the terms of the FreeType project */\n" ) + write( "/* license, LICENSE.TXT. By continuing to use, modify, or distribute */\n" ) + write( "/* this file you indicate that you have read the license and */\n" ) + write( "/* understand and accept it fully. */\n" ) + write( "/* */\n" ) + write( "/***************************************************************************/\n" ) + write( "\n" ) + write( "\n" ) + write( " /* this file has been generated automatically -- do not edit! */\n" ) + write( "\n" ) + write( "\n" ) + + # dump glyph list + name_list = dump_glyph_list( file, base_list, adobe_list ) + + # dump t1_standard_list + write( " static const char** t1_standard_glyphs = " \ + + "standard_glyph_names + " + repr( t1_bias ) + ";\n" ) + write( "\n" ) + write( "\n" ) + + write( "#define NUM_STD_GLYPHS " + repr( len( t1_standard_strings ) ) + "\n" ) + write( "\n" ) + write( "#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST\n" ) + write( "#define NUM_ADOBE_GLYPHS " + \ + repr( len( base_list ) + len( adobe_list ) - t1_bias ) + "\n" ) + write( "#else\n" ) + write( "#define NUM_ADOBE_GLYPHS " + \ + repr( len( base_list ) - t1_bias ) + "\n" ) + write( "#endif\n" ) + write( "\n" ) + write( "\n" ) + + # dump mac indices table + dump_mac_indices( file ) + + # discard mac names from base list + base_list = base_list[t1_bias:] + + # dump unicode values table + dump_unicode_values( file, base_list, adobe_list ) + + dump_encoding( file, "t1_standard_encoding", t1_standard_encoding ) + dump_encoding( file, "t1_expert_encoding", t1_expert_encoding ) + + write( "/* END */\n" ) + + +# Now run the main routine +# +main() + + +# END diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/Image1.png b/reactos/subsys/win32k/freetype/docs/glyphs/Image1.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/Image1.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/Image2.png b/reactos/subsys/win32k/freetype/docs/glyphs/Image2.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/Image2.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/Image3.png b/reactos/subsys/win32k/freetype/docs/glyphs/Image3.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/Image3.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/Image4.png b/reactos/subsys/win32k/freetype/docs/glyphs/Image4.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/Image4.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/bbox1.png b/reactos/subsys/win32k/freetype/docs/glyphs/bbox1.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/bbox1.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/bbox2.png b/reactos/subsys/win32k/freetype/docs/glyphs/bbox2.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/bbox2.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/body_comparison.png b/reactos/subsys/win32k/freetype/docs/glyphs/body_comparison.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/body_comparison.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/bravo_kerned.png b/reactos/subsys/win32k/freetype/docs/glyphs/bravo_kerned.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/bravo_kerned.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/bravo_unkerned.png b/reactos/subsys/win32k/freetype/docs/glyphs/bravo_unkerned.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/bravo_unkerned.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/clipping.png b/reactos/subsys/win32k/freetype/docs/glyphs/clipping.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/clipping.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/down_flow.png b/reactos/subsys/win32k/freetype/docs/glyphs/down_flow.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/down_flow.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/grid_1.png b/reactos/subsys/win32k/freetype/docs/glyphs/grid_1.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/grid_1.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/index.html b/reactos/subsys/win32k/freetype/docs/glyphs/index.html new file mode 100644 index 00000000000..85dde95d2b3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/index.html @@ -0,0 +1,1626 @@ + + + + + + + FreeType Glyph Conventions + + + + + +
+

+FreeType Glyph Conventions

+ +
+

+version 2.0

+ +
+

+Copyright 1998-1999David Turner (david@freetype.org)
+Copyright 1999 The FreeType Development Team (devel@freetype.org)

+ +


+


+

+Introduction

+ +
This document discusses in great details the definition of +various concepts related to digital typography, as well as a few specific +to the FreeType library. It also explains the ways typographic information, +like glyph metrics, kerning distances, etc.. is to be managed and used. +It relates to the layout and display of text strings, either in a conventional +(i.e. Roman) layout, or with right-to-left or vertical ones. Some aspects +like rotation and transformation are explained too. +

Comments and corrections are highly welcomed, and can be sent to the +FreeType +developers list.

+ +
+

+I. Basic typographic concepts

+ +
+

+1. Font files, format and information

+ +
A font is a collection of various character images that can +be used to display or print text. The images in a single font share some +common properties, including look, style, serifs, etc.. Typographically +speaking, one has to distinguish between a font family and its multiple +font +faces, which usually differ in style though come from the same template. +For example, "Palatino Regular" and "Palatino Italic" are +two distinct faces from the same famous family, called "Palatino" +itself. +

The single term font is nearly always used in ambiguous ways to refer +to either a given family or given face, depending on the context. For example, +most users of word-processors use "font" to describe a font family (e.g. +Courier, Palatino, etc..); however most of these families are implemented +through several data files depending on the file format : for TrueType, +this is usually one per face (i.e. ARIAL.TFF for "Arial Regular", ARIALI.TTF +for "Arial Italic", etc..). The file is also called a "font" but really +contains a font face. +

A digital font is thus a data file that may contain one or +more font faces. For each of these, it contains character images, character +metrics, as well as other kind of information important to the layout of +text and the processing of specific character encodings. In some awkward +formats, like Adobe Type1, a single font face is described through several +files (i.e. one contains the character images, another one the character +metrics). We will ignore this implementation issue in most of this document +and consider digital fonts as single files, though FreeType 2.0 is able +to support multiple-files fonts correctly. +

As a convenience, a font file containing more than one face is called +a font collection. This case is rather rare but can be seen in many asian +fonts, which contain images for two or more scripts for a given language.

+ +

+2. Character images and mappings :

+ +
The character images are called glyphs. A single character +can have several distinct images, i.e. several glyphs, depending on script, +usage or context. Several characters can also take a single glyph (good +examples are roman ligatures like "oe" and "fi" which can be represented +by a single glyph like "œ" and "?"). The relationships between characters +and glyphs can be a very complex one but won't be detailed in this document. +Moreover, some formats use more or less awkward schemes to store and access +the glyphs. For the sake of clarity, we'll only retain the following notions +when working with FreeType : +
  +
    +
  • +A font file contains a set of glyphs, each one can be stored as a bitmap, +a vector representation or any other scheme (e.g. most scalable formats +use a combination of math representation and control data/programs). These +glyphs can be stored in any order in the font file, and is typically accessed +through a simple glyph index.
  • +
+
+
+ +
    +
      +
        +
      • +The font file contains one (or more) table, called a character map (or +charmap in short), which is used to convert character codes for a given +encoding (e.g. ASCII, Unicode, DBCS, Big5, etc..) into glyph indexes relative +to the font file. A single font face may contain several charmaps. For +example, most TrueType fonts contain an Apple-specific charmap as well +as a Unicode charmap, which makes them usable on both Mac and Windows platforms.
      • +
      +
    + +

    +3. Character and font metrics :

    + +
      Each glyph image is associated to various metrics which are used to +describe the way it must be placed and managed when rendering text. Though +they are described in more details in section III, they relate to glyph +placement, cursor advances as well as text layouts. They are extremely +important to compute the flow of text when rendering string of text. +

      Each scalable format also contains some global metrics, expressed in +notional units, used to describe some properties of all glyphs in a same +face. For example : the maximum glyph bounding box, the ascender, descender +and text height for the font. +

      Though these metrics also exist for non-scalable formats, they only +apply for a set of given character dimensions and resolutions, and they're +usually expressed in pixels then.

    +
+ +


+


+

+II. Glyph Outlines

+ +
This section describes the vectorial representation of glyph +images, called outlines. +
  +

+1. Pixels, Points and Device Resolutions :

+ +
Though it is a very common assumption when dealing with computer +graphics programs, the physical dimensions of a given pixel (be it for +screens or printers) are not squared. Often, the output device, be it a +screen or printer exhibits varying resolutions in the horizontal and vertical +directions, and this must be taken care of when rendering text. +

It is thus common to define a device's characteristics through two numbers +expressed in dpi (dots per inch). For example, a printer with a +resolution of 300x600 dpi has 300 pixels per inch in the horizontal direction, +and 600 in the vertical one. The resolution of a typical computer monitor +varies with its size (a 15" and 17" monitors don't have the same pixel +sizes at 640x480), and of course the graphics mode resolution. +

As a consequence, the size of text is usually given in points, +rather than device-specific pixels. Points are a simple physical +unit, where 1 point = 1/72th of an inch, in digital typography. As an example, +most roman books are printed with a body text which size is chosen between +10 and 14 points. +

It is thus possible to compute the size of text in pixels from the size +in points through the following computation : +

+

pixel_size = point_size * resolution / 72

+ +

Where resolution is expressed in dpi. Note that because the horizontal +and vertical resolutions may differ, a single point size usually defines +different text width and height in pixels. +
  +

IMPORTANT NOTE: +
Unlike what is often thought, the "size of text in pixels" is not +directly related to the real dimensions of characters when they're displayed +or printed. The relationship between these two concepts is a bit more complex +and relate to some design choice made by the font designer. This is described +in more details the next sub-section (see the explanations on the EM square).

+ +

+2. Vectorial representation :

+ +
The source format of outlines is a collection of closed paths +called contours. Each contour delimits an outer or inner region +of the glyph, and can be made of either line segments or bezier +arcs. +

The arcs are defined through control points, and can be either +second-order (these are "conic beziers") or third-order ("cubic" beziers) +polynomials, depending on the font format. Hence, each point of the outline +has an associated flag indicating its type (normal or control point). +And scaling the points will scale the whole outline. +

Each glyph's original outline points are located on a grid of indivisible +units. The points are usually stored in a font file as 16-bit integer grid +coordinates, with the grid origin's being at (0,0); they thus range from +-16384 to 16383. (even though point coordinates can be floats in other +formats such as Type 1, we'll restrict our analysis to integer ones, driven +by the need for simplicity..). +

IMPORTANT NOTE: +
The grid is always oriented like the traditional mathematical 2D +plane, i.e. the X axis from the left to the right, and the Y axis from +bottom to top. +

In creating the glyph outlines, a type designer uses an imaginary square +called the "EM square". Typically, the EM square can be thought of as a +tablet on which the character are drawn. The square's size, i.e., the number +of grid units on its sides, is very important for two reasons: +
  +

+
  • +it is the reference used to scale the outlines to a given text dimension. +For example, a size of 12pt at 300x300 dpi corresponds to 12*300/72 = 50 +pixels. This is the size the EM square would appear on the output device +if it was rendered directly. In other words, scaling from grid units to +pixels uses the formula:
  • +
    + +
    pixel_size = point_size * resolution / 72 +
    pixel_coordinate = grid_coordinate * pixel_size / EM_size
    + +
    +
  • +the greater the EM size is, the larger resolution the designer can use +when digitizing outlines. For example, in the extreme example of an EM +size of 4 units, there are only 25 point positions available within the +EM square which is clearly not enough. Typical TrueType fonts use an EM +size of 2048 units (note: with Type 1 PostScript fonts, the EM size is +fixed to 1000 grid units. However, point coordinates can be expressed in +floating values).
  • +
    +Note that glyphs can freely extend beyond the EM square if the font designer +wants so. The EM is used as a convenience, and is a valuable convenience +from traditional typography. +
    +

    Note : Grid units are very often called "font units" or "EM units".

    + +

    NOTE: +
    As said before, the pixel_size computed in  the above formula +does not relate directly to the size of characters on the screen. It simply +is the size of the EM square if it was to be displayed directly. Each font +designer is free to place its glyphs as it pleases him within the square. +This explains why the letters of the following text have not the same height, +even though they're displayed at the same point size with distinct fonts +: +

    +

    + +

    As one can see, the glyphs of the Courier family are smaller than those +of Times New Roman, which themselves are slightly smaller than those of +Arial, even though everything is displayed or printed  at a size of +16 points. This only reflect design choices. +
     

    + +

    +3. Hinting and Bitmap rendering

    + +
    The outline as stored in a font file is called the "master" +outline, as its points coordinates are expressed in font units. Before +it can be converted into a bitmap, it must be scaled to a given size/resolution. +This is done through a very simple transform, but always creates undesirable +artifacts, e.g. stems of different widths or heights in letters like "E" +or "H". +

    As a consequence, proper glyph rendering needs the scaled points to +be aligned along the target device pixel grid, through an operation called +"grid-fitting", and often "hinting". One of its main purpose is to ensure +that important widths and heights are respected throughout the whole font +(for example, it is very often desirable that the "I" and the "T" have +their central vertical line of the same pixel width), as well as manage +features like stems and overshoots, which can cause problems at small pixel +sizes. +

    There are several ways to perform grid-fitting properly, for example +most scalable formats associate some control data or programs with each +glyph outline. Here is an overview : +
      +

    +
    explicit grid-fitting : +
    The TrueType format defines a stack-based virtual machine, +for which programs can be written with the help of more than 200 opcodes +(most of these relating to geometrical operations). Each glyph is thus +made of both an outline and a control program, its purpose being to perform +the actual grid-fitting in the way defined by the font designer.
    + +


    implicit grid-fitting (also called hinting) : +

    The Type 1 format takes a much simpler approach : each glyph +is made of an outline as well as several pieces called "hints" which are +used to describe some important features of the glyph, like the presence +of stems, some width regularities, and the like. There aren't a lot of +hint types, and it's up to the final renderer to interpret the hints in +order to produce a fitted outline.
    + +


    automatic grid-fitting : +

    Some formats simply include no control information with each +glyph outline, apart metrics like the advance width and height. It's then +up to the renderer to "guess" the more interesting features of the outline +in order to perform some decent grid-fitting.
    +
    +
    + +
    +


    The following table summarises the pros and cons of each scheme +:

    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    Grid-fitting scheme
    +
    +
    +
    +
    Pros
    +
    +
    +
    +
    Cons
    +
    +
    +
    +
    Explicit
    +
    +
    +
    +
    Quality +
    excellence at small sizes is possible. This is +very important for screen display. +

    Consistency +
    all renderers produce the same glyph bitmaps.

    +
    +
    +
    +
    Speed +
    intepreting bytecode can be slow if the glyph +programs are complex. +

    Size +
    glyph programs can be long +

    Technicity +
    it is extremely difficult to write good hinting +programs. Very few tools available.

    +
    +
    +
    +
    Implicit
    +
    +
    +
    +
    Size +
    hints are usually much smaller than explicit +glyph programs. +

    Speed +
    grid-fitting is usually a fast process

    +
    +
    +
    +
    Quality +
    often questionable at small sizes. Better with +anti-aliasing though. +

    Inconsistency +
    results can vary between different renderers, +or even distinct versions of the same engine.

    +
    +
    +
    +
    Automatic
    +
    +
    +
    +
    Size +
    no need for control information, resulting in +smaller font files. +

    Speed +
    depends on the grid-fitting algo.Usually faster +than explicit grid-fitting.

    +
    +
    +
    +
    Quality +
    often questionable at small sizes. Better with +anti-aliasing though +

    Speed +
    depends on the grid-fitting algo. +

    Inconsistency +
    results can vary between different renderers, +or even distinct versions of the same engine.

    +
    +
    +
    + +
    +

    +III. Glyph metrics

    + +
    +

    +1. Baseline, Pens and Layouts

    +The baseline is an imaginary line that is used to "guide" glyphs when rendering +text. It can be horizontal (e.g. Roman, Cyrillic, Arabic, etc.) or vertical +(e.g. Chinese, Japanese, Korean, etc). Moreover, to render text, a virtual +point, located on the baseline, called the "pen position" or "origin", +is used to locate glyphs. +

    Each layout uses a different convention for glyph placement: +
      +

    +
  • +with horizontal layout, glyphs simply "rest" on the baseline. Text is rendered +by incrementing the pen position, either to the right or to the left.
  • +
    +
    + +
      +
        the distance between two successive pen positions is glyph-specific +and is called the "advance width". Note that its value is _always_ positive, +even for right-to-left oriented alphabets, like Arabic. This introduces +some differences in the way text is rendered. +

        IMPORTANT NOTE:  The pen position is always placed on the baseline.

      + +
      + +
        +
      • +with a vertical layout, glyphs are centered around the baseline:
      • +
      + +
      + +


      +

      +2. Typographic metrics and bounding boxes

      + +
        A various number of face metrics are defined for all glyphs in a given +font. +

        the ascent +

          this is the distance from the baseline to the highest/upper grid coordinate +used to place an outline point. It is a positive value, due to the grid's +orientation with the Y axis upwards.
        + +


        the descent +

          the distance from the baseline to the lowest grid coordinate used to +place an outline point. This is a negative value, due to the grid's orientation.
        + +


        the linegap +

          the distance that must be placed between two lines of text. The baseline-to-baseline +distance should be computed as: +
          +

          ascent - descent + linegap

          +if you use the typographic values.
        +Other, simpler metrics are: +

        the glyph's bounding box, also called "bbox" +

          this is an imaginary box that encloses all glyphs from the font, as +tightly as possible. It is represented by four fields, namely xMin, +yMin, +xMax, +and yMax, that can be computed for any outline. Their values can +be in font units (if measured in the original outline) or in fractional/integer +pixel units (when measured on scaled outlines). +

          Note that if it wasn't for grid-fitting, you wouldn't need to know a +box's complete values, but only its dimensions to know how big is a glyph +outline/bitmap. However, correct rendering of hinted glyphs needs the preservation +of important grid alignment on each glyph translation/placement on the +baseline.

        +the internal leading +
          this concept comes directly from the world of traditional typography. +It represents the amount of space within the "leading" which is reserved +for glyph features that lay outside of the EM square (like accentuation). +It usually can be computed as: +
          +

          internal leading = ascent - descent - EM_size

          +
        +the external leading +
          this is another name for the line gap.
        +
      + +

      +3. Bearings and Advances

      + +
        Each glyph has also distances called "bearings" and "advances". Their +definition is constant, but their values depend on the layout, as the same +glyph can be used to render text either horizontally or vertically: +

        the left side bearing: a.k.a. bearingX +

          this is the horizontal distance from the current pen position to the +glyph's left bbox edge. It is positive for horizontal layouts, and most +generally negative for vertical one.
        + +


        the top side bearing: a.k.a. bearingY +

          this is the vertical distance from the baseline to the top of the glyph's +bbox. It is usually positive for horizontal layouts, and negative for vertical +ones
        + +


        the advance width: a.k.a. advanceX +

          is the horizontal distance the pen position must be incremented (for +left-to-right writing) or decremented (for right-to-left writing) by after +each glyph is rendered when processing text. It is always positive for +horizontal layouts, and null for vertical ones.
        + +


        the advance height: a.k.a. advanceY +

          is the vertical distance the pen position must be decremented by after +each glyph is rendered. It is always null for horizontal layouts, and positive +for vertical layouts.
        + +


        the glyph width +

          this is simply the glyph's horizontal extent. More simply it is (bbox.xMax-bbox.xMin) +for unscaled font coordinates. For scaled glyphs, its computation requests +specific care, described in the grid-fitting chapter below.
        + +


        the glyph height +

          this is simply the glyph's vertical extent. More simply, it is (bbox.yMax-bbox.yMin) +for unscaled font coordinates. For scaled glyphs, its computation requests +specific care, described in the grid-fitting chapter below.
        + +


        the right side bearing +

          is only used for horizontal layouts to describe the distance from the +bbox's right edge to the advance width. It is in most cases a non-negative +number.
        + +
        advance_width - left_side_bearing - (xMax-xMin)
        + +

        Here is a picture giving all the details for horizontal metrics : +

        +

        + +

        And here is another one for the vertical metrics : +

        +

        +
      + +

      +4. The effects of grid-fitting

      + +
        Because hinting aligns the glyph's control points to the pixel grid, +this process slightly modifies the dimensions of character images in ways +that differ from simple scaling. +

        For example, the image of the lowercase "m" letter sometimes fits a +square in the master grid. However, to make it readable at small pixel +sizes, hinting tends to enlarge its scaled outline in order to keep its +three legs distinctly visible, resulting in a larger character bitmap. +

        The glyph metrics are also influenced by the grid-fitting process. Mainly +because : +
          +

          +
        • +The image's width and height are altered. Even if this is only by one pixel, +it can make a big difference at small pixel sizes
        • + +
        • +The image's bounding box is modified, thus modifying the bearings
        • + +
        • +The advances must be updated. For example, the advance width must be incremented +when the hinted bitmap is larger than the scaled one, to reflect the augmented +glyph width.
        • +
        + +


        Note also that : +
          +

          +
        • +Because of hinting, simply scaling the font ascent or descent might not +give correct results. A simple solution consists in keeping the ceiling +of the scaled ascent, and floor of the scaled descent.
        • +
        + +
          +
        • +There is no easy way to get the hinted glyph and advance widths of a range +of glyphs, as hinting works differently on each outline. The only solution +is to hint each glyph separately and record the returned values. Some formats, +like TrueType, even include a table of pre-computed values for a small +set of common character pixel sizes.
        • +
        + +
          +
        • +Hinting depends on the final character width and height in pixels, which +means that it is highly resolution-dependent. This property makes correct +WYSIWYG layouts difficult to implement.
        • +
        + +


        IMPORTANT NOTE: +
        Performing 2D transforms on glyph outlines is very easy with FreeType. +However, when using translation on a hinted outlines, one should aways +take care of  exclusively using integer pixel distances (which +means that the parameters to the FT_Translate_Outline API should all be +multiples of 64, as the point coordinates are in 26.6 fixed float format). +

        Otherwise, the translation will simply ruin the hinter's work, +resulting in a very low quality bitmaps. +
          +
         

      + +

      + 5. Text widths and bounding box :

      + +
        As seen before, the "origin" of a given glyph corresponds to the position +of the pen on the baseline. It is not necessarily located on one of the +glyph's bounding box corners, unlike many typical bitmapped font formats. +In some cases, the origin can be out of the bounding box, in others, it +can be within it, depending on the shape of the given glyph. +

        Likewise, the glyph's "advance width" is the increment to apply to the +pen position during layout, and is not related to the glyph's "width", +which really is the glyph's bounding width. +
          +

        The same conventions apply to strings of text. This means that : +
          +

          +
            +
          • +The bounding box of a given string of text doesn't necessarily contain +the text cursor, nor is the latter located on one of its corners.
          • +
          + +
            +
          • +The string's advance width isn't related to its bounding box's dimensions. +Especially if it contains beginning and terminal spaces or tabs.
          • +
          + +
            +
          • +Finally, additional processing like kerning creates strings of text whose +dimensions are not directly related to the simple juxtaposition of individual +glyph metrics. For example, the advance width of "VA" isn't the sum of +the advances of "V" and "A" taken separately.
          • +
          +
        +
      +
    + +
    +

    + IV. Kerning

    + +
    The term 'kerning' refers to specific information used to adjust +the relative positions of coincident glyphs in a string of text. This section +describes several types of kerning information, as well as the way to process +them when performing text layout. +
      +

    +1. Kerning pairs

    + +
    Kerning consists in modifying the spacing between two successive +glyphs according to their outlines. For example, a "T" and a "y" can be +easily moved closer, as the top of the "y" fits nicely under the "T"'s +upper right bar. +

    When laying out text with only their standard widths, some consecutive +glyphs sometimes seem a bit too close or too distant. For example, the +space between the 'A' and the 'V' in the following word seems a little +wider than needed. +

    +

    + +

    Compare this to the same word, when the distance between these two letters +has been slightly reduced : +

    +

    + +

    As you can see, this adjustment can make a great difference. Some font +faces thus include a table containing kerning distances for a set of given +glyph pairs, used during text layout. Note that : +
      +

    +
      +
    • +The pairs are ordered, i.e. the space for pair (A,V) isn't necessarily +the space for pair (V,A). They also index glyphs, and not characters.
    • +
    + +
      +
    • +Kerning distances can be expressed in horizontal or vertical directions, +depending on layout and/or script. For example, some horizontal layouts +like arabic can make use of vertical kerning adjustments between successive +glyphs. A vertical script can have vertical kerning distances.
    • +
    + +
      +
    • +Kerning distances are expressed in grid units. They are usually oriented +in the X axis, which means that a negative value indicates that two glyphs +must be set closer in a horizontal layout.
    • +
    +
    +
    + +

    +2. Applying kerning

    + +
    Applying kerning when rendering text is a rather easy process. +It merely consists in adding the scaled kern distance to the pen position +before writing each next glyph. However, the typographically correct renderer +must take a few more details in consideration. +

    The "sliding dot" problem is a good example : many font faces include +a kerning distance between capital letters like "T" or "F" and a following +dot ("."), in order to slide the latter glyph just right to their main +leg. I.e. +

    +

    + +

    However, this sometimes requires additional adjustments between the +dot and the letter following it, depending on the shapes of the enclosing +letters. When applying "standard" kerning adjustments, the previous sentence +would become : +

    +

    + +

    Which clearly is too contracted. The solution here, as exhibited in +the first example is to only slide the dots when possible. Of course, this +requires a certain knowledge of the text's meaning. The above adjustments +would not necessarily be welcomed if we were rendering the final dot of +a given paragraph. +

    This is only one example, and there are many others showing that a real +typographer is needed to layout text properly. If not available, some kind +of user interaction or tagging of the text could be used to specify some +adjustments, but in all cases, this requires some support in applications +and text libraries. +

    For more mundane and common uses, however, we can have a very simple +algorithm, which  avoids the sliding dot problem, and others, though +not producing optimal results. It can be seen as : +
      +

    +
      +
    1. +place the first glyph on the baseline
    2. + +
    3. +save the location of the pen position/origin in pen1
    4. + +
    5. +adjust the pen position with the kerning distance between the first and +second glyph
    6. + +
    7. +place the second glyph and compute the next pen position/origin in pen2.
    8. + +
    9. +use pen1 as the next pen position if it is beyond pen2, use pen2 otherwise.
    10. +
    +
    +
    +
    + +

    + +

    + +

    +V. Text processing

    + +
    This section demonstrates how to use the concepts previously +defined to render text, whatever the layout you use. +
      +

    +1. Writing simple text strings :

    + +
    In this first example, we'll generate a simple string of Roman +text, i.e. with a horizontal left-to-right layout. Using exclusively pixel +metrics, the process looks like : +
    1) convert the character string into a series of glyph +indexes. +
    2) place the pen to the cursor position. +
    3) get or load the glyph image. +
    4) translate the glyph so that its 'origin' matches the pen position +
    5) render the glyph to the target device +
    6) increment the pen position by the glyph's advance width in pixels +
    7) start over at step 3 for each of the remaining glyphs +
    8) when all glyphs are done, set the text cursor to the new pen +position
    +Note that kerning isn't part of this algorithm.
    + +

    +2. Sub-pixel positioning :

    + +
    It is somewhat useful to use sub-pixel positioning when rendering +text. This is crucial, for example, to provide semi-WYSIWYG text layouts. +Text rendering is very similar to the algorithm described in sub-section +1, with the following few differences : +
      +
    • +The pen position is expressed in fractional pixels.
    • + +
    • +Because translating a hinted outline by a non-integer distance will ruin +its grid-fitting, the position of the glyph origin must be rounded before +rendering the character image.
    • + +
    • +The advance width is expressed in fractional pixels, and isn't necessarily +an integer.
    • +
    + +


    Which finally looks like : +

    1. convert the character string into a series of glyph +indexes. +
    2. place the pen to the cursor position. This can be a non-integer +point. +
    3. get or load the glyph image. +
    4. translate the glyph so that its 'origin' matches the rounded +pen position. +
    5. render the glyph to the target device +
    6. increment the pen position by the glyph's advance width in fractional +pixels. +
    7. start over at step 3 for each of the remaining glyphs +
    8. when all glyphs are done, set the text cursor to the new pen +position
    +Note that with fractional pixel positioning, the space between two given +letters isn't fixed, but determined by the accumulation of previous rounding +errors in glyph positioning.
    + +

    +3.  Simple kerning :

    + +
    Adding kerning to the basic text rendering algorithm is easy +: when a kerning pair is found, simply add the scaled kerning distance +to the pen position before step 4. Of course, the distance should be rounded +in the case of algorithm 1, though it doesn't need to for algorithm 2. +This gives us : +

    Algorithm 1 with kerning: +

    3) get or load the glyph image. +
    4) Add the rounded scaled kerning distance, if any, to the pen +position +
    5) translate the glyph so that its 'origin' matches the pen position +
    6) render the glyph to the target device +
    7) increment the pen position by the glyph's advance width in pixels +
    8) start over at step 3 for each of the remaining glyphs
    + +


    Algorithm 2 with kerning: +

    3) get or load the glyph image. +
    4) Add the scaled unrounded kerning distance, if any, to the pen +position. +
    5) translate the glyph so that its 'origin' matches the rounded +pen position. +
    6) render the glyph to the target device +
    7) increment the pen position by the glyph's advance width in fractional +pixels. +
    8) start over at step 3 for each of the remaining glyphs
    +Of course, the algorithm described in section IV can also be applied to +prevent the sliding dot problem if one wants to..
    + +

    +4. Right-To-Left Layout :

    + +
    The process of laying out arabic or hebrew text is extremely +similar. The only difference is that the pen position must be decremented +before the glyph rendering (remember : the advance width is always positive, +even for arabic glyphs). Thus, algorithm 1 becomes : +

    Right-to-left Algorithm 1: +

    3) get or load the glyph image. +
    4) Decrement the pen position by the glyph's advance width in pixels +
    5) translate the glyph so that its 'origin' matches the pen position +
    6) render the glyph to the target device +
    7) start over at step 3 for each of the remaining glyphs
    + +


    The changes to Algorithm 2, as well as the inclusion of kerning +are left as an exercise to the reader. +
      +
     

    + +

    +5. Vertical layouts :

    + +
    Laying out vertical text uses exactly the same processes, with +the following significant differences : +
      +
    +
  • +The baseline is vertical, and the vertical metrics must be used instead +of the horizontal one.
  • + +
  • +The left bearing is usually negative, but this doesn't change the fact +that the glyph origin must be located on the baseline.
  • + +
  • +The advance height is always positive, so the pen position must be decremented +if one wants to write top to bottom (assuming the Y axis is oriented upwards).
  • +
    +Through the following algorithm : +
    1) convert the character string into a series of glyph +indexes. +
    2) place the pen to the cursor position. +
    3) get or load the glyph image. +
    4) translate the glyph so that its 'origin' matches the pen position +
    5) render the glyph to the target device +
    6) decrement the vertical pen position by the glyph's advance height +in pixels +
    7) start over at step 3 for each of the remaining glyphs +
    8) when all glyphs are done, set the text cursor to the new pen +position
    +
    + +

    +6. WYSIWYG text layouts :

    + +
    As you probably know, the acronym WYSIWYG stands for 'What +You See Is What You Get'. Basically, this means that the output of +a document on the screen should match "perfectly" its printed version. +A true wysiwyg system requires two things : +

    device-independent text layout +

    Which means that the document's formatting is the same on the +screen than on any printed output, including line breaks, justification, +ligatures, fonts, position of inline images, etc..
    + +


    matching display and print character sizes +

    Which means that the displayed size of a given character should +match its dimensions when printed. For example, a text string which is +exactly 1 inch tall when printed should also appear 1 inch tall on the +screen (when using a scale of 100%).
    + +


    It is clear that matching sizes cannot be possible if the computer +has no knowledge of the physical resolutions of the display device(s) it +is using. And of course, this is the most common case ! That's not too +unfortunate, however  because most users really don't care about this +feature. Legibility is much more important. +

    When the Mac appeared, Apple decided to choose a resolution of 72 dpi +to describe the Macintosh screen to the font sub-system (whatever the monitor +used). This choice was most probably driven by the fact that, at this resolution, +1 point = 1 pixel. However; it neglected one crucial fact : as most users +tend to choose a document character size between 10 and 14 points, the +resultant displayed text was rather small and not too legible without scaling. +Microsoft engineers took notice of this problem and chose a resolution +of 96 dpi on Windows, which resulted in slightly larger, and more legible, +displayed characters (for the same printed text size). +

    These distinct resolutions explain some differences when displaying +text at the same character size on a Mac and a Windows machine. Moreover, +it is not unusual to find some TrueType fonts with enhanced hinting (tech +note: through delta-hinting) for the sizes of 10, 12, 14 and 16 points +at 96 dpi. +
      +

    As for device-independent text, it is a notion that is, unfortunately, +often abused. For example, many word processors, including MS Word, do +not really use device-independent glyph positioning algorithms when laying +out text. Rather, they use the target printer's resolution to compute hinted +glyph metrics for the layout. Though it guarantees that the printed version +is always the "nicest" it can be, especially for very low resolution printers +(like dot-matrix), it has a very sad effect : changing the printer can +have dramatic effects on the whole document layout, especially if +it makes strong use of justification, uses few page breaks, etc.. +

    Because the glyph metrics vary slightly when the resolution changes +(due to hinting), line breaks can change enormously, when these differences +accumulate over long runs of text. Try for example printing a very long +document (with no page breaks) on a 300 dpi ink-jet printer, then the same +one on a 3000 dpi laser printer : you'll be extremely lucky if your final +page count didn't change between the prints ! Of course, we can still call +this WYSIWYG, as long as the printer resolution is fixed !! +

    Some applications, like Adobe Acrobat, which targeted device-independent +placement from the start, do not suffer from this problem. There are two +ways to achieve this : either use the scaled and unhinted glyph metrics +when laying out text both in the rendering and printing processes, or simply +use wathever metrics you want and store them with the text in order to +get sure they're printed the same on all devices (the latter being probably +the best solution, as it also enables font substitution without breaking +text layouts). +

    Just like matching sizes, device-independent placement isn't necessarily +a feature that most users want. However, it is pretty clear that for any +kind of professional document processing work, it is a requirement.

    +
    + +

    + +

    + +

    +VI. FreeType outlines :

    + +
    The purpose of this section is to present the way FreeType +manages vectorial outlines, as well as the most common operations that +can be applied on them. +
      +

    +1. FreeType outline description and structure :

    + +
    +

    +a. Outline curve decomposition :

    + +
    An outline is described as a series of closed contours in the +2D plane. Each contour is made of a series of line segments and bezier +arcs. Depending on the file format, these can be second-order or third-order +polynomials. The former are also called quadratic or conic arcs, and they +come from the TrueType format. The latter are called cubic arcs and mostly +come from the Type1 format. +

    Each arc is described through a series of start, end and control points. +Each point of the outline has a specific tag which indicates wether it +is used to describe a line segment or an arc. The tags can take the following +values : +
      +
     

    + +
    + + + + + + + + + + + + + + + + + +
    +
    FT_Curve_Tag_On 
    +
    +
    Used when the point is "on" the curve. This corresponds to +start and end points of segments and arcs. The other tags specify what +is called an "off" point, i.e. one which isn't located on the contour itself, +but serves as a control point for a bezier arc.
    +
    +
    FT_Curve_Tag_Conic
    +
    +
    Used for an "off" point used to control a conic bezier arc.
    +
    +
    FT_Curve_Tag_Cubic
    +
    +
    Used for an "off" point used to control a cubic bezier arc.
    +
    + +
      +

    The following rules are applied to decompose the contour's points into +segments and arcs : +

    +
  • +two successive "on" points indicate a line segment joining them.
  • +
    +
    + +
      +
        +
      • +one conic "off" point amidst two "on" points indicates a conic bezier arc, +the "off" point being the control point, and the "on" ones the start and +end points.
      • +
      +
    + +
      +
        +
      • +Two successive cubic "off" points amidst two "on" points indicate a cubic +bezier arc. There must be exactly two cubic control points and two on points +for each cubic arc (using a single cubic "off" point between two "on" points +is forbidden, for example).
      • +
      +
    + +
      +
        +
      • +finally, two successive conic "off" points forces the rasterizer to create +(during the scan-line conversion process exclusively) a virtual "on" point +amidst them, at their exact middle. This greatly facilitates the definition +of successive conic bezier arcs. Moreover, it's the way outlines are described +in the TrueType specification.
      • +
      + +


      Note that it is possible to mix conic and cubic arcs in a single +contour, even though no current font driver produces such outlines. +
       

    + +
    + + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +b. Outline descriptor :

    + +
    A FreeType outline is described through a simple structure, +called FT_Outline, which fields are : +
      +
      +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    n_pointsthe number of points in the outline
    n_contoursthe number of contours in the outline
    pointsarray of point coordinates
    contoursarray of contour end indices
    flagsarray of point flags
    + +

    Here, points is a pointer to an array of FT_Vector +records, used to store the vectorial coordinates of each outline point. +These are expressed in 1/64th of a pixel, which is also known as the 26.6 +fixed float format. +

    contours is an array of point indices used to delimit +contours in the outline. For example, the first contour always starts at +point 0, and ends a point contours[0]. The second contour +starts at point "contours[0]+1" and ends at contours[1], +etc.. +

    Note that each contour is closed, and that n_points +should be equal to "contours[n_contours-1]+1" for a valid +outline. +

    Finally, flags is an array of bytes, used to store each +outline point's tag. +
      +
     

    +
    + +

    +2. Bounding and control box computations :

    + +
    A bounding box (also called "bbox") is simply +the smallest possible rectangle that encloses the shape of a given outline. +Because of the way arcs are defined, bezier control points are not necessarily +contained within an outline's bounding box. +

    This situation happens when one bezier arc is, for example, the upper +edge of an outline and an off point happens to be above the bbox. However, +it is very rare in the case of character outlines because most font designers +and creation tools always place on points at the extrema of each curved +edges, as it makes hinting much easier. +

    We thus define the control box (a.k.a. the "cbox") as +the smallest possible rectangle that encloses all points of a given outline +(including its off points). Clearly, it always includes the bbox, and equates +it in most cases. +

    Unlike the bbox, the cbox is also much faster to compute. +
      +

    + + + + + +
    + +

    Control and bounding boxes can be computed automatically through the +functions FT_Get_Outline_CBox and FT_Get_Outline_BBox. +The former function is always very fast, while the latter may be +slow in the case of "outside" control points (as it needs to find the extreme +of conic and cubic arcs for "perfect" computations). If this isn't the +case, it's as fast as computing the control box. +

    Note also that even though most glyph outlines have equal cbox and bbox +to ease hinting, this is not necessary the case anymore when a +
    transform like rotation is applied to them. +
     

    + +

    + 3. Coordinates, scaling and grid-fitting :

    + +
    An outline point's vectorial coordinates are expressed in the +26.6 format, i.e. in 1/64th of a pixel, hence coordinates (1.0, -2.5) is +stored as the integer pair ( x:64, y: -192 ). +

    After a master glyph outline is scaled from the EM grid to the current +character dimensions, the hinter or grid-fitter is in charge of aligning +important outline points (mainly edge delimiters) to the pixel grid. Even +though this process is much too complex to be described in a few lines, +its purpose is mainly to round point positions, while trying to preserve +important properties like widths, stems, etc.. +

    The following operations can be used to round vectorial distances in +the 26.6 format to the grid : +

    +

    round(x)   ==  (x+32) & -64 +
    floor(x)   ==       x & +-64 +
    ceiling(x) ==  (x+63) & -64

    + +

    Once a glyph outline is grid-fitted or transformed, it often is interesting +to compute the glyph image's pixel dimensions before rendering it. To do +so, one has to consider the following : +

    The scan-line converter draws all the pixels whose centers fall +inside the glyph shape. It can also detect "drop-outs", i.e. +discontinuities coming from extremely thin shape fragments, in order to +draw the "missing" pixels. These new pixels are always located at a distance +less than half of a pixel but one cannot predict easily where they'll appear +before rendering. +

    This leads to the following computations : +
      +

      +
    • +compute the bbox
    • +
    + +
      +
    • +grid-fit the bounding box with the following :
    • +
    + +
      +
        xmin = floor( bbox.xMin ) +
        xmax = ceiling( bbox.xMax ) +
        ymin = floor( bbox.yMin ) +
        ymax = ceiling( bbox.yMax )
      + +
    • +return pixel dimensions, i.e. width = (xmax - xmin)/64 and height += (ymax - ymin)/64
    • +
    + +


    By grid-fitting the bounding box, one guarantees that all the pixel +centers that are to be drawn, including those coming from drop-out +control, will be within the adjusted box. Then the +box's dimensions in pixels can be computed. +

    Note also that, when translating a grid-fitted outline, +one should always use integer distances to +move an outline in the 2D plane. Otherwise, glyph edges won't be aligned +on the pixel grid anymore, and the hinter's work will be lost, producing +very +low quality bitmaps and pixmaps..

    +
    + +
    +

    +VII. FreeType bitmaps :

    + +
    The purpose of this section is to present the way FreeType +manages bitmaps and pixmaps, and how they relate to the concepts previously +defined. The relationships between vectorial and pixel coordinates is explained. +
      +

    +1. FreeType bitmap and pixmap descriptor :

    + +
    A bitmap or pixmap is described through a single structure, +called FT_Raster_Map. It is a simple descriptor whose fields are +: +
      +
      +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FT_Raster_Map
    rowsthe number of rows, i.e. lines, in the bitmap
    widththe number of horizontal pixels in the bitmap
    colsthe number of "columns", i.e. bytes per line, in the bitmap
    flowthe bitmap's flow, i.e. orientation of rows (see below)
    pix_bitsthe number of bits per pixels. valid values are 1, 4, 8 and 16
    buffera typeless pointer to the bitmap pixel bufer
    + +

    The bitmap's flow determines wether the rows in the +pixel buffer are stored in ascending or descending order. Possible values +are FT_Flow_Up (value 1) and FT_Flow_Down +(value -1). +

    Remember that FreeType uses the Y upwards convention in the 2D +plane. Which means that a coordinate of (0,0) always refer to the lower-left +corner of a bitmap. +

    In the case of an 'up' flow, the rows are stored in increasing +vertical position, which means that the first bytes of the pixel buffer +are part of the lower bitmap row. On the opposite, a 'down' +flow means that the first buffer bytes are part of the upper bitmap +row, i.e. the last one in ascending order. +

    As a hint, consider that when rendering an outline into a Windows or +X11 bitmap buffer, one should always use a down flow in the bitmap descriptor. +
      +

    + + + + + + + + + + + +
    +
    + +

    +2. Vectorial versus pixel coordinates :

    + +
    This sub-section explains the differences between vectorial +and pixel coordinates. To make things clear, brackets will be used to describe +pixel coordinates, e.g. [3,5], while parentheses will be used for vectorial +ones, e.g. (-2,3.5). +

    In the pixel case, as we use the Y upwards convention, the coordinate +[0,0] always refers to the lower left pixel of a bitmap, while coordinate +[width-1, rows-1] to its upper right pixel. +

    In the vectorial case, point coordinates are expressed in floating units, +like (1.25, -2.3). Such a position doesn't refer to a given pixel, but +simply to an immaterial point in the 2D plane +

    The pixels themselves are indeed square boxes of the 2D plane, +which centers lie in half pixel coordinates. For example, the lower +left pixel of a bitmap is delimited by the square (0,0)-(1,1), +its center being at location (0.5,0.5). +

    This introduces some differences when computing distances. For example, +the "length" in pixels of the line [0,0]-[10,0] is 11. However, +the vectorial distance between (0,0)-(10,0) covers exactly 10 pixel centers, +hence its length if 10. +

    +
    + +

    +3. Converting outlines into bitmaps and pixmaps :

    + +
    Generating a bitmap or pixmap image from a vectorial image +is easy with FreeType. However, one must understand a few points regarding +the positioning of the outline in the 2D plane before calling the function +FT_Get_Outline_Bitmap. +These are : +
      +
      +
    • +The glyph loader and hinter always places the outline in the 2D plane so +that (0,0) matches its character origin. This means that the glyph’s outline, +and corresponding bounding box, can be placed anywhere in the 2D plane +(see the graphics in section III).
    • +
    + +
      +
    • +The target bitmap’s area is mapped to the 2D plane, with its lower left +corner at (0,0). This means that a bitmap or pixmap of dimensions [w,h] +will be mapped to a 2D rectangle window delimited by (0,0)-(w,h).
    • +
    + +
      +
    • +When calling FT_Get_Outline_Bitmap, everything that falls +within the bitmap window is rendered, the rest is ignored.
    • +
    + +


    A common mistake made by many developers when they begin using FreeType +is believing that a loaded outline can be directly rendered in a bitmap +of adequate dimensions. The following images illustrate why this is a problem +: +

      +
        +
      • +the first image shows a loaded outline in the 2D plane.
      • + +
      • +the second one shows the target window for a bitmap of arbitrary dimensions +[w,h]
      • + +
      • +the third one shows the juxtaposition of the outline and window in the +2D plane
      • + +
      • +the last image shows what will really be rendered in the bitmap.
      • +
      +
    + +
    + +


    +
    +
    +
    +
    +

    Indeed, in nearly all cases, the loaded or transformed outline must +be translated before it is rendered into a target bitmap, in order to adjust +its position relative to the target window. +

    For example, the correct way of creating a standalone glyph bitmap +is thus to : +
      +

      +
    • +Compute the size of the glyph bitmap. It can be computed directly from +the glyph metrics, or by computing its bounding box (this is useful when +a transform has been applied to the outline after the load, as the glyph +metrics are not valid anymore).
    • +
    + +
      +
    • +Create the bitmap with the computed dimensions. Don’t forget to fill the +pixel buffer with the background color.
    • +
    + +
      +
    • +Translate the outline so that its lower left corner matches (0,0). Don’t +forget that in order to preserve hinting, one should use integer, i.e. +rounded distances (of course, this isn’t required if preserving hinting +information doesn’t matter, like with rotated text). Usually, this means +translating with a vector ( -ROUND(xMin), -ROUND(yMin) ).
    • +
    + +
      +
    • +Call the function FT_Get_Outline_Bitmap.
    • +
    + +


    In the case where one wants to write glyph images directly into +a large bitmap, the outlines must be translated so that their vectorial +position correspond to the current text cursor/character origin.

    +
    + +

    + +

    + +

    +VII. FreeType anti-aliasing :

    +IMPORTANT NOTE : +
    This section is still in progress, as the way FreeType 2 handles anti-aliased +rendering hasn't been definitely set yet. The main reason being that a +flexible way of doing things is needed in order to allow further improvements +in the raster (i.e. number of gray levels > 100, etc..). +
    +

    +1. What is anti-aliasing :

    + +
    Anti-aliasing works by using various levels of grays to reduce +the "staircase" artefacts visible on the diagonals and curves of glyph +bitmaps. It is a way to artificially enhance the display resolution of +the target device. It can smooth out considerably displayed or printed +text.
    + +

    +2. How does it work with FreeType :

    + +
    FreeType's scan-line converter is able to produce anti-aliased +output directly. It is however limited to 8-bit pixmaps and 5 levels of +grays (or 17 levels, depending on a build configuration option). Here's +how one should use it : +

    +a. Set the gray-level palette :

    + +
    The scan-line converter uses 5 levels for anti-aliased output. +Level 0 corresponds to the text background color (e.g. white), and level +5 to the text foreground color. Intermediate levels are used for intermediate +shades of grays. +

    You must set the raster's palette when you want to use different colors, +use the function FT_Raster_Set_Palette as in : +

    { +
      static const char  gray_palette[5] = { 0, 7, 15, 31, +63 }; +
      … +
      error = FT_Set_Raster_Palette( library, 5, palette ); +
    } +
      +

      +
    • +The first parameter is a handle to a FreeType library object. See the user +guide for more details (the library contains a scan-line converter object).
    • +
    + +
      +
    • +The second parameter is the number of entries in the gray-level palette. +Valid values are 5 and 17 for now, but this may change in later implementations.
    • +
    + +
      +
    • +The last parameter is a pointer to a char table containing the pixel value +for each of the gray-levels. In this example, we use a background color +of 0, a foreground color of 63, and intermediate values in-between.
    • +
    + +


    The palette is copied in the raster object, as well as processed +to build several lookup-tables necessary for the internal anti-aliasing +algorithm. +
     

    + +

    +b. Render the pixmap :

    + +
    The scan-line converter doesn't create bitmaps or pixmaps, +it simply renders into those that are passed as parameters to the function +FT_Get_Outline_Bitmap. +To render an anti-aliased pixmap, simply set the target bitmap’s depth +to 8. Note however that this target 8-bit pixmap must always have a 'cols' +field padded to 32-bits, which means that the number of bytes per lines +of the pixmap must be a multiple of 4 ! +

    Once the palette has been set, and the pixmap buffer has been created +to receive the glyph image, simply call FT_Get_Outline_Bitmap. +Take care of clearing the target pixmap with the background color before +calling this function. For the sake of simplicity and efficiency, the raster +is not able to compose anti-aliased glyph images on a pre-existing images. +

    Here's some code demonstrating how to load and render a single glyph +pixmap : +

    { +
      FT_Outline     outline; +
      FT_Raster_Map  pixmap; +
      FT_BBox        cbox; +
      … +

      // load the outline +
      … +

      // compute glyph dimensions (grid-fit cbox, etc..) +
      FT_Get_Outline_CBox( &outline, &cbox ); +

      cbox.xMin = cbox.xMin & -64;       +// floor(xMin) +
      cbox.yMin = cbox.yMin & -64;       +// floor(yMin) +
      cbox.xMax = (cbox.xMax+32) & -64;  // ceiling(xMax) +
      cbox.yMax = (cbox.yMax+32) & -64;  // ceiling(yMax) +

      pixmap.width = (cbox.xMax - cbox.xMin)/64; +
      pixmap.rows  = (cbox.yMax - cbox.yMin)/64; +

      // fill the pixmap descriptor and create the pixmap buffer +
      // don't forget to pad the 'cols' field to 32 bits +
      pixmap.pix_bits = 8; +
      pixmap.flow     = FT_Flow_Down; +
      pixmap.cols     = (pixmap.width+3) & +-4;  // pad 'cols' to 32 bits +
      pixmap.buffer   = malloc( pixmap.cols * pixmap.rows +); +

      // fill the pixmap buffer with the background color +
      // +
      memset( pixmap.buffer, 0, pixmap.cols*pixmap.rows ); +

      // translate the outline to match (0,0) with the glyph's +
      // lower left corner (ignore the bearings) +
      // the cbox is grid-fitted, we won't ruin the hinting. +
      // +
      FT_Translate_Outline( &outline, -cbox.xMin, -cbox.yMin +); +

      // render the anti-aliased glyph pixmap +
      error = FT_Get_Outline_Bitmap( library, &outline, &pixmap +); +

      // save the bearings for later use.. +
      corner_x = cbox.xMin / 64; +
      corner_y = cbox.yMin / 64; +
    } +

    The resulting pixmap is always anti-aliased.

    +
    + +

    +3. Possible enhancements :

    + +
    FreeType's raster (i.e. its scan-line converter) is currently +limited to producing either 1-bit bitmaps or anti-aliased 8-bit pixmaps. +It is not possible, for example, to draw directly a bitmapped glyph image +into a 4, 8 or 16-bit pixmap through a call to FT_Get_Outline_Bitmap. +

    Moreover, the anti-aliasing filter is limited to use 5 or 17 levels +of grays (through 2x2 and 4x4 sub-sampling). There are cases where this +could seem insufficient for optimal results and where a higher number of +levels like 64 or 128 would be a good thing. +

    These enhancements are all possible but not planned for an immediate +future of the FreeType engine.

    +
    + + + diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/points_conic.png b/reactos/subsys/win32k/freetype/docs/glyphs/points_conic.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/points_conic.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/points_conic2.png b/reactos/subsys/win32k/freetype/docs/glyphs/points_conic2.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/points_conic2.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/points_cubic.png b/reactos/subsys/win32k/freetype/docs/glyphs/points_cubic.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/points_cubic.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/points_segment.png b/reactos/subsys/win32k/freetype/docs/glyphs/points_segment.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/points_segment.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/twlewis1.png b/reactos/subsys/win32k/freetype/docs/glyphs/twlewis1.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/twlewis1.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/twlewis2.png b/reactos/subsys/win32k/freetype/docs/glyphs/twlewis2.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/twlewis2.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/glyphs/up_flow.png b/reactos/subsys/win32k/freetype/docs/glyphs/up_flow.png new file mode 100644 index 00000000000..f1ad7558e49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/glyphs/up_flow.png @@ -0,0 +1 @@ +‰PNG diff --git a/reactos/subsys/win32k/freetype/docs/tutorial/index.html b/reactos/subsys/win32k/freetype/docs/tutorial/index.html new file mode 100644 index 00000000000..fb8a5b3ae4f --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/tutorial/index.html @@ -0,0 +1,871 @@ + + + + + + FreeType 2 Tutorial + + + + +

    + FreeType 2.0 Tutorial +

    + +

    + © 2000 David Turner + (david@freetype.org)
    + © 2000 The FreeType Development Team + (www.freetype.org) +

    + +
    + + +
    + +
    + +

    + Introduction +

    + +

    This short tutorial will teach you how to use the FreeType 2 + library in your own applications.

    + +
    + +

    + 1. Header files +

    + +

    To include the main FreeType header file, simply say

    + + +
    +    #include <freetype/freetype.h>
    +
    + +

    in your application code. Note that other files are available in the + FreeType include directory, most of them being included by + "freetype.h". They will be described later in this + tutorial.

    + +
    + +

    + 2. Initialize the library +

    + +

    Simply create a variable of type FT_Library named, for + example, library, and call the function + FT_Init_FreeType() as in

    + + +
    +    #include <freetype/freetype.h>
    +
    +    FT_Library  library;
    +
    +    ...
    +
    +    {
    +      ...
    +      error = FT_Init_FreeType( &library );
    +      if ( error )
    +      {
    +        ... an error occurred during library initialization ...
    +      }
    +    }
    +
    + +

    This function is in charge of the following:

    + +
      +
    • +

      Creating a new instance of the FreeType 2 library, and set + the handle library to it.

      +
    • +
    • +

      Load each modules that FreeType knows about in the library. + This means that by default, your new library object is able + to handle TrueType, Type 1, CID-keyed & OpenType/CFF fonts + gracefully.

      +
    • +
    + +

    As you can see, the function returns an error code, like most others + in the FreeType API. An error code of 0 always means that + the operation was successful; otherwise, the value describes the error, + and library is set to NULL.

    + +
    + +

    + 3. Load a font face +

    + +

    + a. From a font file +

    + +

    Create a new face object by calling FT_New_Face. + A face describes a given typeface and style. For example, + "Times New Roman Regular" and "Times New Roman Italic" correspond to + two different faces.

    + + +
    +    FT_Library   library;   /* handle to library     */
    +    FT_Face      face;      /* handle to face object */
    +
    +    error = FT_Init_FreeType( &library );
    +    if ( error ) { ... }
    +
    +    error = FT_New_Face( library,
    +                         "/usr/share/fonts/truetype/arial.ttf",
    +                         0,
    +                         &face );
    +    if ( error == FT_Err_Unknown_File_Format )
    +    {
    +      ... the font file could be opened and read, but it appears
    +      ... that its font format is unsupported
    +    }
    +    else if ( error )
    +    {
    +      ... another error code means that the font file could not
    +      ... be opened or read, or simply that it is broken...
    +    }
    +
    + +

    As you can certainly imagine, FT_New_Face opens a font + file, then tries to extract one face from it. Its parameters are

    + + + + + + + + + + + + + + + + + + +
    + library + +

    handle to the FreeType library instance where the face object + is created

    +
    + filepathname + +

    the font file pathname (standard C string).

    +
    + face_index + +

    Certain font formats allow several font faces to be embedded + in a single file.

    + +

    This index tells which face you want to load. An error will + be returned if its value is too large.

    + +

    Index 0 always work though.

    +
    + face + +

    A pointer to the handle that will be set to describe + the new face object.

    + +

    It is set to NULL in case of error.

    +
    + +

    To know how many faces a given font file contains, simply load its + first face (use face_index=0), then see the value of + face->num_faces which indicates how many faces are embedded + in the font file.

    + +

    + b. From memory +

    + +

    In the case where you have already loaded the font file in memory, + you can similarly create a new face object for it by calling + FT_New_Memory_Face as in

    + + +
    +    FT_Library   library;   /* handle to library     */
    +    FT_Face      face;      /* handle to face object */
    +
    +    error = FT_Init_FreeType( &library );
    +    if ( error ) { ... }
    +
    +    error = FT_New_Memory_Face( library,
    +                                buffer,    /* first byte in memory */
    +                                size,      /* size in bytes        */
    +                                0,         /* face_index           */
    +                                &face );
    +    if ( error ) { ... }
    +
    + +

    As you can see, FT_New_Memory_Face() simply takes a + pointer to the font file buffer and its size in bytes instead of a + file pathname. Other than that, it has exactly the same semantics as + FT_New_Face().

    + +

    + c. From other sources (compressed files, network, etc.) +

    + +

    There are cases where using a file pathname or preloading the file + in memory is simply not enough. With FreeType 2, it is possible + to provide your own implementation of i/o routines.

    + +

    This is done through the FT_Open_Face() function, which + can be used to open a new font face with a custom input stream, select + a specific driver for opening, or even pass extra parameters to the + font driver when creating the object. We advise you to refer to the + FreeType 2 reference manual in order to learn how to use it.

    + +

    Note that providing a custom stream might also be used to access a + TrueType font embedded in a Postscript Type 42 wrapper.

    + +
    + +

    + 4. Accessing face content +

    + +

    A face object models all information that globally describes + the face. Usually, this data can be accessed directly by dereferencing + a handle, like

    + + + + + + + + + + + + + + + + + + + + + + +
    + face->num_glyphs + +

    Gives the number of glyphs available in the font face. + A glyph is simply a character image. It doesn't necessarily + correspond to a character code though.

    +
    + face->flags + +

    A 32-bit integer containing bit flags used to describe some + face properties. For example, the flag + FT_FACE_FLAG_SCALABLE is used to indicate that the face's + font format is scalable and that glyph images can be rendered for + all character pixel sizes. For more information on face flags, + please read the FreeType 2 API Reference.

    +
    + face->units_per_EM + +

    This field is only valid for scalable formats (it is set to 0 + otherwise). It indicates the number of font units covered by the + EM.

    +
    + face->num_fixed_sizes + +

    This field gives the number of embedded bitmap strikes + in the current face. A strike is simply a series of + glyph images for a given character pixel size. For example, a + font face could include strikes for pixel sizes 10, 12 + and 14. Note that even scalable font formats can have + embedded bitmap strikes!

    +
    + face->fixed_sizes + +

    this is a pointer to an array of FT_Bitmap_Size + elements. Each FT_Bitmap_Size indicates the horizontal + and vertical pixel sizes for each of the strikes that are + present in the face.

    +
    + +

    For a complete listing of all face properties and fields, please read + the FreeType 2 API Reference.

    + +


    + +

    + 5. Setting the current pixel size +

    + +

    FreeType 2 uses "size objects" to model all + information related to a given character size for a given face. + For example, a size object will hold the value of certain metrics + like the ascender or text height, expressed in 1/64th of a pixel, + for a character size of 12 points.

    + +

    When the FT_New_Face function is called (or one of its + cousins), it automatically creates a new size object for + the returned face. This size object is directly accessible as + face->size.

    + +

    NOTA BENE: a single face object can deal with one or more size + objects at a time, however, this is something that few programmers + really need to do. We have thus have decided to simplify the API for + the most common use (i.e. one size per face), while keeping this + feature available through additional fuctions.

    + +

    When a new face object is created, its size object defaults to the + character size of 10 pixels (both horizontally and vertically) for + scalable formats. For fixed-sizes formats, the size is more or less + undefined, which is why you must set it before trying to load a + glyph.

    + +

    To do that, simply call FT_Set_Char_Size(). Here is an + example where the character size is set to 16pt for a 300x300 dpi + device:

    + + +
    +    error = FT_Set_Char_Size(
    +              face,    /* handle to face object           */
    +              0,       /* char_width in 1/64th of points  */
    +              16*64,   /* char_height in 1/64th of points */
    +              300,     /* horizontal device resolution    */
    +              300 );   /* vertical device resolution      */
    +
    + +

    You will notice that:

    + +
      +
    • +

      The character width and heights are specified in 1/64th of + points. A point is a physical distance, equaling 1/72th + of an inch, it's not a pixel..

      +

    • +
    • +

      The horizontal and vertical device resolutions are expressed in + dots-per-inch, or dpi. You can use 72 or + 96 dpi for display devices like the screen. The resolution + is used to compute the character pixel size from the character + point size.

      +
    • +
    • +

      A value of 0 for the character width means "same as + character height", a value of 0 for the character height + means "same as character width". Otherwise, it is possible + to specify different char widths and heights.

      +
    • +
    • +

      Using a value of 0 for the horizontal or vertical resolution means + 72 dpi, which is the default.

      +
    • +
    • +

      The first argument is a handle to a face object, not a size + object. That's normal, and must be seen as a convenience.

      +
    • +
    + +

    This function computes the character pixel size that corresponds to + the character width and height and device resolutions. However, if you + want to specify the pixel sizes yourself, you can simply call + FT_Set_Pixel_Sizes(), as in

    + + +
    +    error = FT_Set_Pixel_Sizes(
    +              face,   /* handle to face object            */
    +              0,      /* pixel_width                      */
    +              16 );   /* pixel_height                     */
    +
    + +

    This example will set the character pixel sizes to 16x16 pixels. + As previously, a value of 0 for one of the dimensions means + "same as the other".

    + +

    Note that both functions return an error code. Usually, an error + occurs with a fixed-size font format (like FNT or PCF) when trying to + set the pixel size to a value that is not listed in the + face->fixed_sizes array.

    + +
    + +

    + 6. Loading a glyph image +

    + +

    + a. Converting a character code into a glyph index +

    + +

    Usually, an application wants to load a glyph image based on its + character code, which is a unique value that defines the + character for a given encoding. For example, the character + code 65 represents the `A' in ASCII encoding.

    + +

    A face object contains one or more tables, called + charmaps, that are used to convert character codes to glyph + indices. For example, most TrueType fonts contain two charmaps. One + is used to convert Unicode character codes to glyph indices, the other + is used to convert Apple Roman encoding into glyph indices. Such + fonts can then be used either on Windows (which uses Unicode) and + Macintosh (which uses Apple Roman, bwerk). Note also that a given + charmap might not map to all the glyphs present in the font.

    + +

    By default, when a new face object is created, it lists all the + charmaps contained in the font face and selects the one that supports + Unicode character codes if it finds one. Otherwise, it tries to find + support for Latin-1, then ASCII.

    + +

    We will describe later how to look for specific charmaps in a face. + For now, we will assume that the face contains at least a Unicode + charmap that was selected during FT_New_Face(). To convert a + Unicode character code to a font glyph index, we use + FT_Get_Char_Index() as in

    + + +
    +    glyph_index = FT_Get_Char_Index( face, charcode );
    +
    + +

    This will look the glyph index corresponding to the given + charcode in the charmap that is currently selected for the + face. If charmap is selected, the function simply returns the + charcode.

    + +

    Note that this is one of the rare FreeType functions that do not + return an error code. However, when a given character code has no + glyph image in the face, the value 0 is returned. By convention, + it always correspond to a special glyph image called the missing + glyph, which usually is represented as a box or a space.

    + +

    + b. Loading a glyph from the face +

    + +

    Once you have a glyph index, you can load the corresponding glyph + image. Note that the glyph image can be in several formats. For + example, it will be a bitmap for fixed-size formats like FNT, FON, or + PCF. It will also be a scalable vector outline for formats like + TrueType or Type 1. The glyph image can also be stored in an + alternate way that is not known at the time of writing this + documentation.

    + +

    The glyph image is always stored in a special object called a + glyph slot. As its name suggests, a glyph slot is simply a + container that is able to hold one glyph image at a time, be it a + bitmap, an outline, or something else. Each face object has a single + glyph slot object that can be accessed as + face->glyph.

    + +

    Loading a glyph image into the slot is performed by calling + FT_Load_Glyph() as in

    + + +
    +    error = FT_Load_Glyph( 
    +              face,          /* handle to face object */
    +              glyph_index,   /* glyph index           */
    +              load_flags );  /* load flags, see below */
    +
    + +

    The load_flags value is a set of bit flags used to + indicate some special operations. The default value + FT_LOAD_DEFAULT is 0.

    + +

    This function will try to load the corresponding glyph image + from the face. Basically, this means that:

    + +
      +
    • +

      If a bitmap is found for the corresponding glyph and pixel + size, it will in the slot (embedded bitmaps are always + favored over native image formats, because we assume that + they are higher-quality versions of the same image. This + can be ignored by using the FT_LOAD_NO_BITMAP flag)

      +
    • + +
    • +

      Otherwise, a native image for the glyph will be loaded. + It will also be scaled to the current pixel size, as + well as hinted for certain formats like TrueType and + Type1.

      +
    • +
    + +

    The field glyph->format describe the format + used to store the glyph image in the slot. If it is not + ft_glyph_format_bitmap, one can immediately + convert it to a bitmap through FT_Render_Glyph, + as in:

    + + +
    +   error = FT_Render_Glyph(
    +                  face->glyph,      /* glyph slot  */
    +		  render_mode );    /* render mode */
    +      
    +
    + +

    The parameter render_mode is a set of bit flags used + to specify how to render the glyph image. Set it to 0 to render + a monochrome bitmap, or to ft_render_mode_antialias to + generate a high-quality (256 gray levels) anti-aliased bitmap + from the glyph image.

    + +

    Once you have a bitmap glyph image, you can access it directly + through glyph->bitmap (a simple bitmap descriptor), + and position it through glyph->bitmap_left and + glyph->bitmap_top.

    + +

    Note that bitmap_left is the horizontal distance from the + current pen position to the left-most border of the glyph bitmap, + while bitmap_top is the vertical distance from the + pen position (on the baseline) to the top-most border of the + glyph bitmap. It is positive to indicate an upwards + distance.

    + +

    The next section will detail the content of a glyph slot and + how to access specific glyph information (including metrics).

    + +

    + c. Using other charmaps +

    + +

    As said before, when a new face object is created, it will look for + a Unicode, Latin-1, or ASCII charmap and select it. The currently + selected charmap is accessed via face->charmap. This + field is NULL when no charmap is selected, which typically happens + when you create a new FT_Face object from a font file that + doesn't contain an ASCII, Latin-1, or Unicode charmap (rare + stuff).

    + +

    There are two ways to select a different charmap with FreeType 2. + The easiest is when the encoding you need already has a corresponding + enumeration defined in <freetype/freetype.h>, as + ft_encoding_big5. In this case, you can simply call + FT_Select_CharMap as in:

    + +
    +    error = FT_Select_CharMap(
    +                    face,                 /* target face object */
    +		    ft_encoding_big5 );   /* encoding..         */
    +      
    + +

    Another way is to manually parse the list of charmaps for the + face, this is accessible through the fields + num_charmaps and charmaps + (notice the 's') of the face object. As you could expect, + the first is the number of charmaps in the face, while the + second is a table of pointers to the charmaps + embedded in the face.

    + +

    Each charmap has a few visible fields used to describe it more + precisely. Mainly, one will look at + charmap->platform_id and + charmap->encoding_id that define a pair of + values that can be used to describe the charmap in a rather + generic way.

    + +

    Each value pair corresponds to a given encoding. For example, + the pair (3,1) corresponds to Unicode. Their list is + defined in the TrueType specification but you can also use the + file <freetype/ftnameid.h> which defines several + helpful constants to deal with them..

    + +

    To look for a specific encoding, you need to find a corresponding + value pair in the specification, then look for it in the charmaps + list. Don't forget that some encoding correspond to several + values pair (yes it's a real mess, but blame Apple and Microsoft + on such stupidity..). Here's some code to do it:

    + + +
    +    FT_CharMap  found = 0;
    +    FT_CharMap  charmap;
    +    int         n;
    +
    +    for ( n = 0; n < face->num_charmaps; n++ )
    +    {
    +      charmap = face->charmaps[n];
    +      if ( charmap->platform_id == my_platform_id &&
    +           charmap->encoding_id == my_encoding_id )
    +      {
    +        found = charmap;
    +        break;
    +      }
    +    }
    +
    +    if ( !found ) { ... }
    +
    +    /* now, select the charmap for the face object */
    +    error = FT_Set_CharMap( face, found );
    +    if ( error ) { ... }
    +
    + +

    Once a charmap has been selected, either through + FT_Select_CharMap or FT_Set_CharMap, + it is used by all subsequent calls to + FT_Get_Char_Index().

    + + +

    + d. Glyph Transforms: +

    + +

    It is possible to specify an affine transformation to be applied + to glyph images when they're loaded. Of course, this will only + work for scalable (vectorial) font formats.

    + +

    To do that, simply call FT_Set_Transform, as in:

    + +
    +   error = FT_Set_Transform(
    +                    face,           /* target face object    */
    +		    &matrix,    /* pointer to 2x2 matrix */
    +		    &delta );   /* pointer to 2d vector  */
    +     
    + +

    This function will set the current transform for a given face + object. Its second parameter is a pointer to a simple + FT_Matrix structure that describes a 2x2 affine matrix. + The third parameter is a pointer to a FT_Vector structure + that describe a simple 2d vector.

    + +

    Note that the matrix pointer can be set to NULL, (in which case + the identity transform will be used). Coefficients of the matrix + are in 16.16 fixed float units.

    + +

    The vector pointer can also be set to NULL (in which case a delta + of (0,0) will be used). The vector coordinates are expressed in + 1/64th of a pixel (also known as 26.6 fixed floats).

    + +

    NOTA BENE: The transform is applied every glyph that is loaded + through FT_Load_Glyph. Note that loading a glyph bitmap + with a non-trivial transform will produce an error..

    + +
    + +

    + 7. Accessing glyph image data +

    + +

    Glyph image data is accessible through face->glyph. + See the definition of the FT_GlyphSlot type for more details. + As stated previously, each face has a single glyph slot, where + one glyph image at a time can be loaded. Each time + you call FT_Load_Glyph(), you erase the content of the glyph + slot with a new glyph image.

    + +

    Note however that the glyph slot object itself doesn't change, only + its content, which means that you can perfectly create a "shortcut" to + access it as in

    + + +
    +    {
    +      /* shortcut to glyph slot */
    +      FT_GlyphSlot  glyph = face->glyph;
    +
    +      for ( n = 0; n < face->num_glyphs; n++ )
    +      {
    +        ... load glyph n ...
    +        ... access glyph data as glyph->xxxx
    +      }
    +    }
    +
    + +

    The glyph variable will be valid until its parent + face is destroyed. Here are a few important fields of the + glyph slot:

    + + + + + + + + + + + + + + + + + + +
    + glyph->format + +

    Indicates the type of the loaded glyph image. Can be either + ft_glyph_format_bitmap, ft_glyph_format_outline, + or other values.

    +
    + glyph->metrics + +

    A simple structure used to hold the glyph image's metrics. + Note that most distances are expressed in 1/64th of + pixels! See the API reference or the user guide for a + description of the FT_Glyph_Metrics structure.

    +
    + glyph->bitmap + +

    If the glyph slot contains a bitmap, a simple + FT_Bitmap that describes it. See the API reference or + user guide for a description of the FT_Bitmap + structure.

    +
    + glyph->outline + +

    When the glyph slot contains a scalable outline, this structure + describes it. See the definition of the FT_Outline + structure.

    +
    + +

    + 8. Rendering glyph outlines into bitmaps +

    + +

    You can easily test the format of the glyph image by inspecting the + face->glyph->format variable. If its value is + ft_glyph_format_bitmap, the glyph image that was loaded is a + bitmap that can be directly blit to your own surfaces through your + favorite graphics library (FreeType 2 doesn't provide bitmap + blitting routines, as you may imagine :-)

    + +

    If the format is ft_glyph_format_outline or something else, + the library provides a means to convert such glyph images to bitmaps + through what are called rasters.

    + +

    On the other hand, if the image is a scalable outline or something + else, FreeType provides a function to convert the glyph image into a + pre-existing bitmap that you will handle to it, named + FT_Get_Glyph_Bitmap. Here's a simple example code + that renders an outline into a monochrome bitmap:

    + + +
    +    {
    +      FT_GlyphSlot  glyph;
    +
    +      ... load glyph ...
    +
    +      glyph = face->glyph;   /* shortcut to glyph data */
    +      if ( glyph->format == ft_glyph_format_outline )
    +      {
    +        FT_Bitmap  bit;
    +
    +        /* set-up a bitmap descriptor for our target bitmap */
    +        bit.rows       = bitmap_height;
    +        bit.width      = bitmap_width;
    +        bit.pitch      = bitmap_row_bytes;
    +        /* render into a mono bitmap */
    +        bit.pixel_mode = ft_pixel_mode_mono;
    +        bit.buffer     = bitmap_buffer;
    +
    +        /* render the outline directly into the bitmap */
    +        error = FT_Get_Glyph_Bitmap( face, &bit );
    +        if ( error ) { ... }
    +      }
    +    }
    +
    + +

    You should note that FT_Get_Glyph_Bitmap() doesn't + create the bitmap. It only needs a descriptor, of type + FT_Bitmap, and writes directly into it.

    + +

    Note that the FreeType scan-converter for outlines can also generate + anti-aliased glyph bitmaps with 128 level of grays. For now, it is + restricted to rendering to 8-bit gray-level bitmaps, though this may + change in the future. Here is some code to do just that:

    + + +
    +    {
    +      FT_GlyphSlot  glyph;
    +
    +      ... load glyph ...
    +
    +      glyph = face->glyph;   /* shortcut to glyph data */
    +      if ( glyph->format == ft_glyph_format_outline )
    +      {
    +        FT_Bitmap  bit;
    +
    +        /* set-up a bitmap descriptor for our target bitmap */
    +        bit.rows       = bitmap_height;
    +        bit.width      = bitmap_width;
    +        bit.pitch      = bitmap_row_bytes;
    +        /* 8-bit gray-level bitmap */
    +        bit.pixel_mode = ft_pixel_mode_gray;
    +        /* MUST be 128 for now     */
    +        bit.grays      = 128;
    +        bit.buffer     = bitmap_buffer;
    +
    +        /* clean the bitmap - IMPORTANT */
    +        memset( bit.buffer, 0, bit.rows*bit.pitch );
    +
    +        /* render the outline directly into the bitmap */
    +        error = FT_Get_Glyph_Bitmap( face, &bit );
    +        if ( error ) { ... }
    +      }
    +    }
    +
    + +

    You will notice that

    + +
      +
    • +

      As previously, FT_Get_Glyph_Bitmap() doesn't generate + the bitmap, it simply renders to it.

      +
    • +
    • +

      The target bitmap must be cleaned before calling the function. + This is a limitation of our current anti-aliasing algorithm and is + EXTREMELY important.

      +
    • +
    • +

      The anti-aliaser uses 128 levels of grays exclusively for + now (this will probably change in a near future). This means that + you must set bit.grays to 128. The generated + image uses values from 0 (back color) to 127 (foreground color).

      +
    • +
    • +

      It is not possible to render directly an anti-aliased + outline into a pre-existing gray-level bitmap, or even any + colored-format one (like RGB16 or paletted 8-bits). We will not + discuss this issue in great details here, but the reason is that we + do not want to deal with graphics composition (or alpha-blending) + within FreeType.

      +

    • +
    +
    +
    + + + diff --git a/reactos/subsys/win32k/freetype/docs/tutorial/step1.html b/reactos/subsys/win32k/freetype/docs/tutorial/step1.html new file mode 100644 index 00000000000..e184be7b929 --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/tutorial/step1.html @@ -0,0 +1,956 @@ + + + + + + FreeType 2 Tutorial + + + + +

    + FreeType 2.0 Tutorial
    + Step 1 - simple glyph loading +

    + +

    + © 2000 David Turner + (david@freetype.org)
    + © 2000 The FreeType Development Team + (www.freetype.org) +

    + +
    + + +
    + +
    + +

    + Introduction +

    + +

    This is the first section of the FreeType 2 tutorial. It will teach + you to do the following:

    + +
      +
    • initialise the library
    • +
    • open a font file by creating a new face object
    • +
    • select a character size in points or in pixels
    • +
    • load a single glyph image and convert it to a bitmap
    • +
    • render a very simple string of text
    • +
    • render a rotated string of text easily
    • +
    + +
    + +

    + 1. Header files +

    + +

    To include the main FreeType header file, simply say

    + + +
    +    #include <freetype/freetype.h>
    +
    + +

    in your application code. Note that other files are available in the + FreeType include directory, most of them being included by + "freetype.h". They will be described later in this + tutorial.

    + +
    + +

    + 2. Initialize the library +

    + +

    Simply create a variable of type FT_Library named, for + example, library, and call the function + FT_Init_FreeType() as in

    + + +
    +    #include <freetype/freetype.h>
    +
    +    FT_Library  library;
    +
    +    ...
    +
    +    {
    +      ...
    +      error = FT_Init_FreeType( &library );
    +      if ( error )
    +      {
    +        ... an error occurred during library initialization ...
    +      }
    +    }
    +
    + +

    This function is in charge of the following:

    + +
      +
    • +

      Creating a new instance of the FreeType 2 library, and set + the handle library to it.

      +
    • +
    • +

      Load each modules that FreeType knows about in the library. + This means that by default, your new library object is able + to handle TrueType, Type 1, CID-keyed & OpenType/CFF fonts + gracefully.

      +
    • +
    + +

    As you can see, the function returns an error code, like most others + in the FreeType API. An error code of 0 always means that + the operation was successful; otherwise, the value describes the error, + and library is set to NULL.

    + +
    + +

    + 3. Load a font face +

    + +

    + a. From a font file +

    + +

    Create a new face object by calling FT_New_Face. + A face describes a given typeface and style. For example, + "Times New Roman Regular" and "Times New Roman Italic" correspond to + two different faces.

    + + +
    +    FT_Library   library;   /* handle to library     */
    +    FT_Face      face;      /* handle to face object */
    +
    +    error = FT_Init_FreeType( &library );
    +    if ( error ) { ... }
    +
    +    error = FT_New_Face( library,
    +                         "/usr/share/fonts/truetype/arial.ttf",
    +                         0,
    +                         &face );
    +    if ( error == FT_Err_Unknown_File_Format )
    +    {
    +      ... the font file could be opened and read, but it appears
    +      ... that its font format is unsupported
    +    }
    +    else if ( error )
    +    {
    +      ... another error code means that the font file could not
    +      ... be opened or read, or simply that it is broken...
    +    }
    +
    + +

    As you can certainly imagine, FT_New_Face opens a font + file, then tries to extract one face from it. Its parameters are

    + + + + + + + + + + + + + + + + + + +
    + library + +

    handle to the FreeType library instance where the face object + is created

    +
    + filepathname + +

    the font file pathname (standard C string).

    +
    + face_index + +

    Certain font formats allow several font faces to be embedded + in a single file.

    + +

    This index tells which face you want to load. An error will + be returned if its value is too large.

    + +

    Index 0 always work though.

    +
    + face + +

    A pointer to the handle that will be set to describe + the new face object.

    + +

    It is set to NULL in case of error.

    +
    + +

    To know how many faces a given font file contains, simply load its + first face (use face_index=0), then see the value of + face->num_faces which indicates how many faces are embedded + in the font file.

    + +

    + b. From memory +

    + +

    In the case where you have already loaded the font file in memory, + you can similarly create a new face object for it by calling + FT_New_Memory_Face as in

    + + +
    +    FT_Library   library;   /* handle to library     */
    +    FT_Face      face;      /* handle to face object */
    +
    +    error = FT_Init_FreeType( &library );
    +    if ( error ) { ... }
    +
    +    error = FT_New_Memory_Face( library,
    +                                buffer,    /* first byte in memory */
    +                                size,      /* size in bytes        */
    +                                0,         /* face_index           */
    +                                &face );
    +    if ( error ) { ... }
    +
    + +

    As you can see, FT_New_Memory_Face() simply takes a + pointer to the font file buffer and its size in bytes instead of a + file pathname. Other than that, it has exactly the same semantics as + FT_New_Face().

    + +

    + c. From other sources (compressed files, network, etc.) +

    + +

    There are cases where using a file pathname or preloading the file + in memory is simply not enough. With FreeType 2, it is possible + to provide your own implementation of i/o routines.

    + +

    This is done through the FT_Open_Face() function, which + can be used to open a new font face with a custom input stream, select + a specific driver for opening, or even pass extra parameters to the + font driver when creating the object. We advise you to refer to the + FreeType 2 reference manual in order to learn how to use it.

    + +

    Note that providing a custom stream might also be used to access a + TrueType font embedded in a Postscript Type 42 wrapper.

    + +
    + +

    + 4. Accessing face content +

    + +

    A face object models all information that globally describes + the face. Usually, this data can be accessed directly by dereferencing + a handle, like

    + + + + + + + + + + + + + + + + + + + + + + +
    + face->num_glyphs + +

    Gives the number of glyphs available in the font face. + A glyph is simply a character image. It doesn't necessarily + correspond to a character code though.

    +
    + face->flags + +

    A 32-bit integer containing bit flags used to describe some + face properties. For example, the flag + FT_FACE_FLAG_SCALABLE is used to indicate that the face's + font format is scalable and that glyph images can be rendered for + all character pixel sizes. For more information on face flags, + please read the FreeType 2 API Reference.

    +
    + face->units_per_EM + +

    This field is only valid for scalable formats (it is set to 0 + otherwise). It indicates the number of font units covered by the + EM.

    +
    + face->num_fixed_sizes + +

    This field gives the number of embedded bitmap strikes + in the current face. A strike is simply a series of + glyph images for a given character pixel size. For example, a + font face could include strikes for pixel sizes 10, 12 + and 14. Note that even scalable font formats can have + embedded bitmap strikes!

    +
    + face->fixed_sizes + +

    this is a pointer to an array of FT_Bitmap_Size + elements. Each FT_Bitmap_Size indicates the horizontal + and vertical pixel sizes for each of the strikes that are + present in the face.

    +
    + +

    For a complete listing of all face properties and fields, please read + the FreeType 2 API Reference.

    + +


    + +

    + 5. Setting the current pixel size +

    + +

    FreeType 2 uses "size objects" to model all + information related to a given character size for a given face. + For example, a size object will hold the value of certain metrics + like the ascender or text height, expressed in 1/64th of a pixel, + for a character size of 12 points.

    + +

    When the FT_New_Face function is called (or one of its + cousins), it automatically creates a new size object for + the returned face. This size object is directly accessible as + face->size.

    + +

    NOTA BENE: a single face object can deal with one or more size + objects at a time, however, this is something that few programmers + really need to do. We have thus have decided to simplify the API for + the most common use (i.e. one size per face), while keeping this + feature available through additional fuctions.

    + +

    When a new face object is created, its size object defaults to the + character size of 10 pixels (both horizontally and vertically) for + scalable formats. For fixed-sizes formats, the size is more or less + undefined, which is why you must set it before trying to load a + glyph.

    + +

    To do that, simply call FT_Set_Char_Size(). Here is an + example where the character size is set to 16pt for a 300x300 dpi + device:

    + + +
    +    error = FT_Set_Char_Size(
    +              face,    /* handle to face object           */
    +              0,       /* char_width in 1/64th of points  */
    +              16*64,   /* char_height in 1/64th of points */
    +              300,     /* horizontal device resolution    */
    +              300 );   /* vertical device resolution      */
    +
    + +

    You will notice that:

    + +
      +
    • +

      The character width and heights are specified in 1/64th of + points. A point is a physical distance, equaling 1/72th + of an inch, it's not a pixel..

      +

    • +
    • +

      The horizontal and vertical device resolutions are expressed in + dots-per-inch, or dpi. You can use 72 or + 96 dpi for display devices like the screen. The resolution + is used to compute the character pixel size from the character + point size.

      +
    • +
    • +

      A value of 0 for the character width means "same as + character height", a value of 0 for the character height + means "same as character width". Otherwise, it is possible + to specify different char widths and heights.

      +
    • +
    • +

      Using a value of 0 for the horizontal or vertical resolution means + 72 dpi, which is the default.

      +
    • +
    • +

      The first argument is a handle to a face object, not a size + object. That's normal, and must be seen as a convenience.

      +
    • +
    + +

    This function computes the character pixel size that corresponds to + the character width and height and device resolutions. However, if you + want to specify the pixel sizes yourself, you can simply call + FT_Set_Pixel_Sizes(), as in

    + + +
    +    error = FT_Set_Pixel_Sizes(
    +              face,   /* handle to face object            */
    +              0,      /* pixel_width                      */
    +              16 );   /* pixel_height                     */
    +
    + +

    This example will set the character pixel sizes to 16x16 pixels. + As previously, a value of 0 for one of the dimensions means + "same as the other".

    + +

    Note that both functions return an error code. Usually, an error + occurs with a fixed-size font format (like FNT or PCF) when trying to + set the pixel size to a value that is not listed in the + face->fixed_sizes array.

    + +
    + +

    + 6. Loading a glyph image +

    + +

    + a. Converting a character code into a glyph index +

    + +

    Usually, an application wants to load a glyph image based on its + character code, which is a unique value that defines the + character for a given encoding. For example, the character + code 65 represents the `A' in ASCII encoding.

    + +

    A face object contains one or more tables, called + charmaps, that are used to convert character codes to glyph + indices. For example, most TrueType fonts contain two charmaps. One + is used to convert Unicode character codes to glyph indices, the other + is used to convert Apple Roman encoding into glyph indices. Such + fonts can then be used either on Windows (which uses Unicode) and + Macintosh (which uses Apple Roman, bwerk). Note also that a given + charmap might not map to all the glyphs present in the font.

    + +

    By default, when a new face object is created, it lists all the + charmaps contained in the font face and selects the one that supports + Unicode character codes if it finds one. Otherwise, it tries to find + support for Latin-1, then ASCII.

    + +

    We will describe later how to look for specific charmaps in a face. + For now, we will assume that the face contains at least a Unicode + charmap that was selected during FT_New_Face(). To convert a + Unicode character code to a font glyph index, we use + FT_Get_Char_Index() as in

    + + +
    +    glyph_index = FT_Get_Char_Index( face, charcode );
    +
    + +

    This will look the glyph index corresponding to the given + charcode in the charmap that is currently selected for the + face. If charmap is selected, the function simply returns the + charcode.

    + +

    Note that this is one of the rare FreeType functions that do not + return an error code. However, when a given character code has no + glyph image in the face, the value 0 is returned. By convention, + it always correspond to a special glyph image called the missing + glyph, which usually is represented as a box or a space.

    + +

    + b. Loading a glyph from the face +

    + +

    Once you have a glyph index, you can load the corresponding glyph + image. The latter can be stored in various formats within the font file. + For fixed-size formats like FNT or PCF, each image is a bitmap. Scalable + formats like TrueType or Type 1 use vectorial shapes, named "outlines" + to describe each glyph. Some formats may have even more exotic ways + of representing glyph (e.g. MetaFont). Fortunately, FreeType 2 is + flexible enough to support any kind of glyph format through + a simple API.

    + +

    The glyph image is always stored in a special object called a + glyph slot. As its name suggests, a glyph slot is simply a + container that is able to hold one glyph image at a time, be it a + bitmap, an outline, or something else. Each face object has a single + glyph slot object that can be accessed as + face->glyph.

    + +

    Loading a glyph image into the slot is performed by calling + FT_Load_Glyph() as in

    + + +
    +    error = FT_Load_Glyph( 
    +              face,          /* handle to face object */
    +              glyph_index,   /* glyph index           */
    +              load_flags );  /* load flags, see below */
    +
    + +

    The load_flags value is a set of bit flags used to + indicate some special operations. The default value + FT_LOAD_DEFAULT is 0.

    + +

    This function will try to load the corresponding glyph image + from the face. Basically, this means that:

    + +
      +
    • +

      If a bitmap is found for the corresponding glyph and pixel + size, it will be loaded into the slot (embedded bitmaps are always + favored over native image formats, because we assume that + they are higher-quality versions of the same glyph. This + can be ignored by using the FT_LOAD_NO_BITMAP flag)

      +
    • + +
    • +

      Otherwise, a native image for the glyph will be loaded. + It will also be scaled to the current pixel size, as + well as hinted for certain formats like TrueType and + Type1.

      +
    • +
    + +

    The field glyph->format describe the format + used to store the glyph image in the slot. If it is not + ft_glyph_format_bitmap, one can immediately + convert it to a bitmap through FT_Render_Glyph, + as in:

    + + +
    +   error = FT_Render_Glyph(
    +                  face->glyph,      /* glyph slot  */
    +                  render_mode );    /* render mode */
    +      
    +
    + +

    The parameter render_mode is a set of bit flags used + to specify how to render the glyph image. Set it to 0, or the + equivalent ft_render_mode_normal to render a high-quality + anti-aliased (256 gray levels) bitmap, as this is the default. + You can alternatively use ft_render_mode_mono if you + want to generate a 1-bit monochrome bitmap.

    + +

    Once you have a bitmapped glyph image, you can access it directly + through glyph->bitmap (a simple bitmap descriptor), + and position it through glyph->bitmap_left and + glyph->bitmap_top.

    + +

    Note that bitmap_left is the horizontal distance from the + current pen position to the left-most border of the glyph bitmap, + while bitmap_top is the vertical distance from the + pen position (on the baseline) to the top-most border of the + glyph bitmap. It is positive to indicate an upwards + distance.

    + +

    The next section will detail the content of a glyph slot and + how to access specific glyph information (including metrics).

    + +

    + c. Using other charmaps +

    + +

    As said before, when a new face object is created, it will look for + a Unicode, Latin-1, or ASCII charmap and select it. The currently + selected charmap is accessed via face->charmap. This + field is NULL when no charmap is selected, which typically happens + when you create a new FT_Face object from a font file that + doesn't contain an ASCII, Latin-1, or Unicode charmap (rare + stuff).

    + +

    There are two ways to select a different charmap with FreeType 2. + The easiest is when the encoding you need already has a corresponding + enumeration defined in <freetype/freetype.h>, as + ft_encoding_big5. In this case, you can simply call + FT_Select_CharMap as in:

    + +
    +    error = FT_Select_CharMap(
    +                    face,                 /* target face object */
    +                    ft_encoding_big5 );   /* encoding..         */
    +      
    + +

    Another way is to manually parse the list of charmaps for the + face, this is accessible through the fields + num_charmaps and charmaps + (notice the 's') of the face object. As you could expect, + the first is the number of charmaps in the face, while the + second is a table of pointers to the charmaps + embedded in the face.

    + +

    Each charmap has a few visible fields used to describe it more + precisely. Mainly, one will look at + charmap->platform_id and + charmap->encoding_id that define a pair of + values that can be used to describe the charmap in a rather + generic way.

    + +

    Each value pair corresponds to a given encoding. For example, + the pair (3,1) corresponds to Unicode. Their list is + defined in the TrueType specification but you can also use the + file <freetype/ftnameid.h> which defines several + helpful constants to deal with them..

    + +

    To look for a specific encoding, you need to find a corresponding + value pair in the specification, then look for it in the charmaps + list. Don't forget that some encoding correspond to several + values pair (yes it's a real mess, but blame Apple and Microsoft + on such stupidity..). Here's some code to do it:

    + + +
    +    FT_CharMap  found = 0;
    +    FT_CharMap  charmap;
    +    int         n;
    +
    +    for ( n = 0; n < face->num_charmaps; n++ )
    +    {
    +      charmap = face->charmaps[n];
    +      if ( charmap->platform_id == my_platform_id &&
    +           charmap->encoding_id == my_encoding_id )
    +      {
    +        found = charmap;
    +        break;
    +      }
    +    }
    +
    +    if ( !found ) { ... }
    +
    +    /* now, select the charmap for the face object */
    +    error = FT_Set_CharMap( face, found );
    +    if ( error ) { ... }
    +
    + +

    Once a charmap has been selected, either through + FT_Select_CharMap or FT_Set_CharMap, + it is used by all subsequent calls to + FT_Get_Char_Index().

    + + +

    + d. Glyph Transforms: +

    + +

    It is possible to specify an affine transformation to be applied + to glyph images when they're loaded. Of course, this will only + work for scalable (vectorial) font formats.

    + +

    To do that, simply call FT_Set_Transform, as in:

    + +
    +   error = FT_Set_Transform(
    +                    face,       /* target face object    */
    +                    &matrix,    /* pointer to 2x2 matrix */
    +                    &delta );   /* pointer to 2d vector  */
    +     
    + +

    This function will set the current transform for a given face + object. Its second parameter is a pointer to a simple + FT_Matrix structure that describes a 2x2 affine matrix. + The third parameter is a pointer to a FT_Vector structure + that describe a simple 2d vector that is used to translate the + glyph image after the 2x2 transform.

    + +

    Note that the matrix pointer can be set to NULL, (in which case + the identity transform will be used). Coefficients of the matrix + are otherwise in 16.16 fixed float units.

    + +

    The vector pointer can also be set to NULL (in which case a delta + of (0,0) will be used). The vector coordinates are expressed in + 1/64th of a pixel (also known as 26.6 fixed floats).

    + + +

    NOTA BENE: The transform is applied to every glyph that is loaded + through FT_Load_Glyph and is completely independent + of any hinting process. This means that you won't get the same + results if you load a glyph at the size of 24 pixels, or a glyph at + the size at 12 pixels scaled by 2 through a transform, because the + hints will have been computed differently (unless, of course you + disabled hints).

    + +

    If you ever need to use a non-orthogonal transform with optimal + hints, you first need to decompose your transform into a scaling part + and a rotation/shearing part. Use the scaling part to compute a new + character pixel size, then the other one to call FT_Set_Transform. + This is explained in details in a later section of this tutorial.

    + +

    Note also that loading a glyph bitmap with a non-identity transform + will produce an error..

    +
    + +

    + 7. Simple Text Rendering: +

    + +

    We will now present you with a very simple example used to render + a string of 8-bit Latin-1 text, assuming a face that contains a + Unicode charmap

    + +

    The idea is to create a loop that will, on each iteration, load one + glyph image, convert it to an anti-aliased bitmap, draw it on the + target surface, then increment the current pen position

    + +

    a. basic code :

    + +

    The following code performs our simple text rendering with the + functions previously described.

    + +
    +       FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +       int           pen_x, pen_y, n;
    +
    +       .. initialise library ..
    +       .. create face object ..
    +       .. set character size ..
    +       
    +       pen_x = 300;
    +       pen_y = 200;
    +       
    +       for ( n = 0; n < num_chars; n++ )
    +       {
    +         FT_UInt  glyph_index;
    +         
    +         // retrieve glyph index from character code
    +         glyph_index = FT_Get_Char_Index( face, text[n] );
    +         
    +         // load glyph image into the slot (erase previous one)
    +         error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
    +         if (error) continue;  // ignore errors
    +         
    +         // convert to an anti-aliased bitmap
    +         error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
    +         if (error) continue;
    +         
    +         // now, draw to our target surface
    +         my_draw_bitmap( &slot->bitmap,
    +                         pen_x + slot->bitmap_left,
    +                         pen_y - slot->bitmap_top );
    +                         
    +         // increment pen position 
    +         pen_x += slot->advance.x >> 6;
    +         pen_y += slot->advance.y >> 6;   // unuseful for now..
    +       }
    +    
    + +

    This code needs a few explanations:

    +
      +
    • + we define a handle named slot that points to the + face object's glyph slot. (the type FT_GlyphSlot is + a pointer). That's a convenience to avoid using + face->glyph->XXX every time. +

    • + +
    • + we increment the pen position with the vector slot->advance, + which correspond to the glyph's advance width (also known + as its escapement). The advance vector is expressed in + 64/th of pixels, and is truncated to integer pixels on each + iteration.

      +

    • + +
    • + The function my_draw_bitmap is not part of FreeType, but + must be provided by the application to draw the bitmap to the target + surface. In this example, it takes a pointer to a FT_Bitmap descriptor + and the position of its top-left corner as arguments. +

    • + +
    • + The value of slot->bitmap_top is positive for an + upwards vertical distance. Assuming that the coordinates + taken by my_draw_bitmap use the opposite convention + (increasing Y corresponds to downwards scanlines), we substract + it to pen_y, instead of adding it.. +

    • + +
    + +

    b. refined code:

    + +

    The following code is a refined version of the example above. It + uses features and functions of FreeType 2 that have not yet been + introduced, and they'll be explained below:

    + +
    +       FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +       FT_UInt       glyph_index;
    +       int           pen_x, pen_y, n;
    +
    +       .. initialise library ..
    +       .. create face object ..
    +       .. set character size ..
    +       
    +       pen_x = 300;
    +       pen_y = 200;
    +       
    +       for ( n = 0; n < num_chars; n++ )
    +       {
    +         // load glyph image into the slot (erase previous one)
    +         error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );
    +         if (error) continue;  // ignore errors
    +         
    +         // now, draw to our target surface
    +         my_draw_bitmap( &slot->bitmap,
    +                         pen_x + slot->bitmap_left,
    +                         pen_y - slot->bitmap_top );
    +                         
    +         // increment pen position 
    +         pen_x += slot->advance.x >> 6;
    +       }
    +    
    + +

    We've reduced the size of our code, but it does exactly the same thing, + as:

    + +
      +
    • + We use the function FT_Load_Char instead of + FT_Load_Glyph. As you probably imagine, it's equivalent + to calling FT_Get_Char_Index then FT_Get_Load_Glyph. +

    • + +
    • + We do not use FT_LOAD_DEFAULT for the loading mode, but + the bit flag FT_LOAD_RENDER. It indicates that + the glyph image must be immediately converted to an anti-aliased + bitmap. This is of course a shortcut that avoids calling + FT_Render_Glyph explicitely but is strictly equivalent.

      + +

      + Note that you can also specify that you want a monochrome bitmap + instead by using the addition FT_LOAD_MONOCHROME + load flag. +

    • +
    + +

    c. more advanced rendering:

    + +

    Let's try to render transformed text now (for example through a + rotation). We can do this using FT_Set_Transform. Here's + how to do it:

    + +
    +       FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +       FT_Matrix     matrix;              // transformation matrix
    +       FT_UInt       glyph_index;
    +       FT_Vector     pen;                 // untransformed origin
    +       int           pen_x, pen_y, n;
    +
    +       .. initialise library ..
    +       .. create face object ..
    +       .. set character size ..
    +
    +       // set up matrix
    +       matrix.xx = (FT_Fixed)( cos(angle)*0x10000);
    +       matrix.xy = (FT_Fixed)(-sin(angle)*0x10000);
    +       matrix.yx = (FT_Fixed)( sin(angle)*0x10000);
    +       matrix.yy = (FT_Fixed)( cos(angle)*0x10000);
    +              
    +       // the pen position in 26.6 cartesian space coordinates
    +       pen.x = 300 * 64;
    +       pen.y = ( my_target_height - 200 ) * 64;
    +       
    +       for ( n = 0; n < num_chars; n++ )
    +       {
    +         // set transform
    +         FT_Set_Transform( face, &matrix, &pen );
    +         
    +         // load glyph image into the slot (erase previous one)
    +         error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );
    +         if (error) continue;  // ignore errors
    +         
    +         // now, draw to our target surface (convert position)
    +         my_draw_bitmap( &slot->bitmap,
    +                         slot->bitmap_left,
    +                         my_target_height - slot->bitmap_top );
    +                         
    +         // increment pen position 
    +         pen.x += slot->advance.x;
    +         pen.y += slot->advance.y;
    +       }
    +    
    + +

    You'll notice that:

    + +
      +
    • + we now use a vector, of type FT_Vector to store the pen + position, with coordinates expressed as 1/64th of pixels, hence + a multiplication. The position is expressed in cartesian space. +

    • + +
    • + glyph images are always loaded, transformed and described in the + cartesian coordinate system in FreeType (which means that + increasing Y corresponds to upper scanlines), unlike the system + typically used for bitmaps (where the top-most scanline has + coordinate 0). We must thus convert between the two systems + when we define the pen position, and when we compute the top-left + position of the bitmap. +

    • + +
    • + we set the transform on each glyph, to indicate the rotation + matrix, as well as a delta that will move the transformed image + to the current pen position (in cartesian space, not bitmap space). +

    • + +
    • + the advance is always returned transformed, which is why it can + be directly added to the current pen position. Note that it is + not rounded this time. +

    • + +
    + +

    It is important to note that, while this example is a bit more + complex than the previous one, it is strictly equivalent + for the case where the transform is the identity.. Hence it can + be used as a replacement (but a more powerful one).

    + +

    It has however a few short comings that we will explain, and solve, + in the next part of this tutorial.

    + +
    + +

    + Conclusion +

    + +

    In this first section, you have learned the basics of FreeType 2, + as well as sufficient knowledge to know how to render rotated text. + Woww ! Congratulations..

    + +

    The next section will dive into more details of the API in order + to let you access glyph metrics and images directly, as well as + how to deal with scaling, hinting, kerning, etc..

    + +

    The third section will discuss issues like modules, caching and a + few other advanced topics like how to use multiple size objects + with a single face. +

    + +
    +
    + + + diff --git a/reactos/subsys/win32k/freetype/docs/tutorial/step2.html b/reactos/subsys/win32k/freetype/docs/tutorial/step2.html new file mode 100644 index 00000000000..d8cc1505cdf --- /dev/null +++ b/reactos/subsys/win32k/freetype/docs/tutorial/step2.html @@ -0,0 +1,1399 @@ + + + + + + FreeType 2 Tutorial + + + + +

    + FreeType 2.0 Tutorial
    + Step 2 - managing glyphs +

    + +

    + © 2000 David Turner + (david@freetype.org)
    + © 2000 The FreeType Development Team + (www.freetype.org) +

    + +
    + + +
    + +
    + +

    + Introduction +

    + +

    This is the second section of the FreeType 2 tutorial. It will teach + you the following:

    + +
      +
    • how to retrieve glyph metrics
    • +
    • how to easily manage glyph images
    • +
    • how to retrieve global metrics (including kerning)
    • +
    • how to render a simple string of text, with kerning
    • +
    • how to render a centered string of text (with kerning)
    • +
    • how to render a transformed string of text (with centering)
    • +
    • finally, how to access metrics in design font units when needed, + and how to scale them to device space.
    • +
    + +
    + +

    + 1. Glyph metrics: +

    + +

    Glyph metrics are, as their name suggests, certain distances associated + to each glyph in order to describe how to use it to layout text.

    + +

    There are usually two sets of metrics for a single glyph: those used to + layout the glyph in horizontal text layouts (like latin, cyrillic, + arabic, hebrew, etc..), and those used to layout the glyph in vertical + text layouts (like some layouts of Chinese, Japanese, Korean, and + others..).

    + +

    Note that only a few font formats provide vertical metrics. You can + test wether a given face object contains them by using the macro + FT_HAS_VERTICAL(face), which is true when appropriate.

    + +

    Individual glyph metrics can be accessed by first loading the glyph + in a face's glyph slot, then accessing them through the + face->glyph->metrics structure. This will be detailed + later, for now, we'll see that it contains the following fields:

    + +
    + width + +

    This is the width of the glyph image's bounding box. It is independent + of layout direction.

    +
    + height + +

    This is the height of the glyph image's bounding box. It is independent + of layout direction.

    +
    + horiBearingX + +

    For horizontal text layouts, this is the horizontal distance from + the current cursor position to the left-most border of the glyph image's + bounding box.

    +
    + horiBearingY + +

    For horizontal text layouts, this is the vertical distance from + the current cursor position (on the baseline) to the top-most border of + the glyph image's bounding box.

    +
    + horiAdvance + +

    For horizontal text layouts, this is the horizontal distance + used to increment the pen position when the glyph is drawn as part of + a string of text.

    +
    + vertBearingX + +

    For vertical text layouts, this is the horizontal distance from + the current cursor position to the left-most border of the glyph image's + bounding box.

    +
    + vertBearingY + +

    For vertical text layouts, this is the vertical distance from + the current cursor position (on the baseline) to the top-most border of + the glyph image's bounding box.

    +
    + vertAdvance + +

    For vertical text layouts, this is the vertical distance + used to increment the pen position when the glyph is drawn as part of + a string of text.

    +
    + +

    NOTA BENE: As all fonts do not contain vertical + metrics, the values of vertBearingX, vertBearingY + and vertAdvance should not be considered reliable when + FT_HAS_VERTICAL(face) is false.

    + +

    The following graphics illustrate the metrics more clearly. First, for + horizontal metrics, where the baseline is the horizontal axis :

    + +
    + +

    For vertical text layouts, the baseline is vertical and is the + vertical axis:

    + +
    + + +

    The metrics found in face->glyph->metrics are normally + expressed in 26.6 pixels (i.e 1/64th of pixels), unless you use + the FT_LOAD_NO_SCALE flag when calling + FT_Load_Glyph or FT_Load_Char. In this case, + the metrics will be expressed in original font units.

    + +

    The glyph slot object has also a few other interesting fields + that will ease a developer's work. You can access them though + face->glyph->??? :

    + +
    + advance + +

    This field is a FT_Vector which holds the transformed + advance for the glyph. That's useful when you're using a transform + through FT_Set_Transform, as shown in the rotated text + example of section I. Other than that, its value is + by default (metrics.horiAdvance,0), unless you specify + FT_LOAD_VERTICAL when loading the glyph image; + it will then be (0,metrics.vertAdvance)

    +
    + linearHoriAdvance + +

    + This field contains the linearly-scaled value of the glyph's horizontal + advance width. Indeed, the value of metrics.horiAdvance that is + returned in the glyph slot is normally rounded to integer pixel + coordinates (i.e., it will be a multiple of 64) by the font driver used + to load the glyph image. linearHoriAdvance is a 16.16 fixed float + number that gives the value of the original glyph advance width in + 1/65536th of pixels. It can be use to perform pseudo device-independent + text layouts.

    +
    + linearVertAdvance + +

    This is the same thing as linearHoriAdvance for the + glyph's vertical advance height. Its value is only reliable if the font + face contains vertical metrics.

    +
    + + + +
    + +

    + 2. Managing glyph images: +

    + +

    The glyph image that is loaded in a glyph slot can be converted into + a bitmap, either by using FT_LOAD_RENDER when loading it, or + by calling FT_Render_Glyph. Each time you load a new glyph + image, the previous one is erased from the glyph slot.

    + +

    There are times however where you may need to extract this image from + the glyph slot, in order to cache it within your application, and + even perform additional transforms and measures on it before converting + it to a bitmap. +

    + +

    The FreeType 2 API has a specific extension which is capable of dealing + with glyph images in a flexible and generic way. To use it, you first need + to include the "ftglyph.h" header file, as in:

    + +
    
    +      #include <freetype/ftglyph.h>
    +  
    + +

    We will now explain how to use the functions defined in this file:

    + +

    a. Extracting the glyph image:

    + +

    You can extract a single glyph image very easily. Here's some code + that shows how to do it:

    + +
    
    +       FT_Glyph    glyph;    // handle to glyph image
    +       
    +       ....
    +       error = FT_Load_Glyph( face, glyph, FT_LOAD_NORMAL );
    +       if (error) { .... }
    +       
    +       error = FT_Get_Glyph( face->glyph, &glyph );
    +       if (error) { .... }
    +  
    + +

    As you see, we have:

    + +
      +
    • + Created a variable, named glyph, of type FT_Glyph. + This is a handle (pointer) to an individual glyph image. +

    • + +
    • + Loaded the glyph image normally in the face's glyph slot. We did not + use FT_LOAD_RENDER because we want to grab a scalable glyph + image, in order to later transform it. +

    • + +
    • + Copy the glyph image from the slot into a new FT_Glyph object, + by calling FT_Get_Glyph. This function returns an error + code and sets glyph. +

    • +
    + +

    It is important to note that the extracted glyph is in the same format + than the original one that is still in the slot. For example, if we're + loading a glyph from a TrueType font file, the glyph image will really + be a scalable vector outline.

    + +

    You can access the field glyph->format if you want to + know exactly how the glyph is modeled and stored. A new glyph object can + be destroyed with a call to FT_Done_Glyph.

    + +

    The glyph object contains exactly one glyph image and a 2D vector + representing the glyph's advance in 16.16 fixed float coordinates. + The latter can be accessed directly as glyph->advance +

    + +

    Note that unlike + other FreeType objects, the library doesn't keeps a list of all + allocated glyph objects. This means you'll need to destroy them + yourself, instead of relying on FT_Done_FreeType doing + all the clean-up.

    + +

    b. Transforming & copying the glyph image

    + +

    If the glyph image is scalable (i.e. if glyph->format is not + equal to ft_glyph_format_bitmap), it is possible to transform + the image anytime by a call to FT_Glyph_Transform.

    + +

    You can also copy a single glyph image with FT_Glyph_Copy. + Here's some example code:

    + +
    
    +    FT_Glyph  glyph, glyph2;
    +    FT_Matrix matrix;
    +    FT_Vector delta;
    +    
    +    ......
    +    .. load glyph image in "glyph" ..
    +    
    +    // copy glyph to glyph2
    +    //
    +    error = FT_Glyph_Copy( glyph, &glyph2 );
    +    if (error) { ... could not copy (out of memory) }
    +    
    +    // translate "glyph"
    +    //    
    +    delta.x = -100 * 64;   // coordinates are in 26.6 pixels
    +    delta.y =  50  * 64;
    +    
    +    FT_Glyph_Transform( glyph, 0, &delta );
    +    
    +    // transform glyph2 (horizontal shear)
    +    //
    +    matrix.xx = 0x10000;
    +    matrix.xy = 0;
    +    matrix.yx = 0.12 * 0x10000;
    +    matrix.yy = 0x10000;
    +    
    +    FT_Glyph_Transform( glyph2, &matrix, 0 );
    +  
    + +

    Note that the 2x2 transform matrix is always applied to the 16.16 + advance vector in the glyph, you thus don't need to recompute it..

    + +

    c. Measuring the glyph image

    + +

    You can also retrieve the control (bounding) box of any glyph image + (scalable or not), through the FT_Glyph_Get_CBox function, + as in: +

    + +
    
    +     FT_BBox   bbox;
    +     ...
    +     FT_Glyph_BBox(  glyph, bbox_mode, &bbox );
    +  
    + +

    Coordinates are relative to the glyph origin, i.e. (0,0), using the + Y_upwards convention. This function takes a special argument, the + "bbox mode", that is a set of bit flags used to indicate how + box coordinates are expressed. If ft_glyph_bbox_subpixels + is set in the bbox mode, the coordinates are returned in 26.6 pixels + (i.e. 1/64th of pixels). Otherwise, they're in integer pixels.

    + +

    Note that the box's maximum coordinates are exclusive, which means + that you can always compute the width and height of the glyph image, + be in in integer or 26.6 pixels with:

    + +
         
    +     width  = bbox.xMax - bbox.xMin;
    +     height = bbox.yMax - bbox.yMin;
    +  
    + +

    Note also that for 26.6 coordinates, if + ft_glyph_bbox_gridfit is set in the bbox mode, + 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)
    +  
    + +

    The default value for the bbox mode, which is 0, corresponds to + ft_glyph_bbox_pixels (i.e. integer pixel coordinates).

    + + +

    d. Converting the glyph image to a bitmap

    + +

    You may need to convert the glyph object to a bitmap once you have + convienently cached or transformed it. This can be done easily with + the FT_Glyph_To_Bitmap function. It is chared of + converting any glyph object into a bitmap, as in:

    + +
    
    +    FT_Vector  origin;
    +    
    +    origin.x = 32;   /* 1/2 pixel in 26.26 format */
    +    origin.y = 0;
    +    
    +    error = FT_Glyph_To_Bitmap( &glyph,
    +                                render_mode,
    +                                &origin,
    +                                1 );        // destroy original image == true
    +  
    + +

    We will know details this function's parameters:

    + +
      +
    • + the first parameter is the address of the source glyph's handle. + When the function is called, it reads its to access the source + glyph object. After the call, the handle will point to a + new glyph object that contains the rendered bitmap. +

    • + +
    • + the second parameter is a standard render mode, that is used to specify + what kind of bitmap we want. It can be ft_render_mode_default + for an 8-bit anti-aliased pixmap, or ft_render_mode_mono for + a 1-bit monochrome bitmap. +

    • + +
    • + the third parameter is a pointer to a 2D vector that is used to + translate the source glyph image before the conversion. Note that + the source image will be translated back to its original position + (and will thus be left unchanged) after the call. If you do not need + to translate the source glyph before rendering, set this pointer to 0. +

    • + +
    • + the last parameter is a boolean that indicates wether the source + glyph object should be destroyed by the function. By default, the + original glyph object is never destroyed, even if its handle is + lost (it's up to client applications to keep it). +

    • +
    + +

    The new glyph object always contain a bitmap (when no error is returned), + and you must typecast its handle to the + FT_BitmapGlyph type in order to access its content. + This type is a sort of "subclass" of FT_Glyph that contains + additional fields:

    + +
    + left + +

    Just like the bitmap_left field of a glyph slot, this is the + horizontal distance from the glyph origin (0,0) to the left-most pixel + of the glyph bitmap. It is expressed in integer pixels.

    +
    + top + +

    Just like the bitmap_top field of a glyph slot, this is the + vertical distance from the glyph origin (0,0) to the top-most pixel + of the glyph bitmap (more exactly, to the pixel just above the bitmap). + This distance is expressed in integer pixels, and is positive for upwards + Y.

    +
    + bitmap + +

    This is a bitmap descriptor for the glyph object, just like the + bitmap field in a glyph slot.

    +
    + +
    +

    + 3. Global glyph metrics: +

    + +

    Unlike glyph metrics, global ones are used to describe distances + and features of a whole font face. They can be expressed either in + 26.6 pixels or in design "font units" for scalable formats.

    + +

    + a. Design Global Metrics: +

    + +

    For scalable formats, all global metrics are expressed in font units + in order to be later scaled to device space, according to the rules + described in the last chapter of this section of the tutorial. You + can access them directly as simple fields of a FT_Face + handle.

    + +

    However, you need to check that the font face's format is scalable + before using them. One can do it by using the macro + FT_IS_SCALABLE(face) which returns true when + appropriate.

    + +

    In this case, you can access the global design metrics as:

    + +
    + units_per_EM + +

    This is the size of the EM square for the font face. It is used by scalable + formats to scale design coordinates to device pixels, as described by the + last chapter of this section. Its value usually is 2048 (for TrueType) + or 1000 (for Type1), but others are possible too. It is set to 1 for + fixed-size formats like FNT/FON/PCF/BDF.

    +
    + global_bbox + +

    The global bounding box is defined as the largest rectangle that can + enclose all the glyphs in a font face. It is defined for horizontal + layouts only.

    +
    + ascender + +

    The ascender is the vertical distance from the horizontal baseline to + the highest "character" coordinate in a font face. Unfortunately, font + formats define the ascender differently. For some, it represents + the ascent of all capital latin characters, without accents, for others + it's the ascent of the highest accented character, and finally, other + formats define it as being equal to global_bbox.yMax.

    +
    + descender + +

    The descender is the vertical distance from the horizontal baseline to + the lowest "character" coordinate in a font face. Unfortunately, font + formats define the descender differently. For some, it represents + the descent of all capital latin characters, without accents, for others + it's the ascent of the lowest accented character, and finally, other + formats define it as being equal to global_bbox.yMin. + This field is usually negative

    +
    + text_height + +

    This field is simply used to compute a default line spacing (i.e. the + baseline-to-baseline distance) when writing text with this font. Note that + it usually is larger than the sum of the ascender and descender taken in + absolute value. There is also no guarantee that no glyphs can extend + above or below subsequent baselines when using this distance.

    +
    + max_advance_width + +

    This field gives the maximum horizontal cursor advance for all glyphs + in the font. It can be used to quickly compute the maximum advance width + of a string of text. It doesn't correspond to the maximum glyph image + width !!

    +
    + max_advance_height + +

    Same as max_advance_width but for vertical text layout. It is + only available in fonts providing vertical glyph metrics.

    +
    + underline_position + +

    When displaying or rendering underlined text, this value corresponds to + the vertical position, relative to the baseline, of the underline bar. It + noramlly is negative (as it's below the baseline).

    +
    + underline_thickness + +

    When displaying or rendering underlined text, this value corresponds to + the vertical thickness of the underline.

    +
    + +

    Notice how, unfortunately, the values of the ascender and the descender + are not reliable (due to various discrepancies in font formats).

    + +

    + b. Scaled Global Metrics: +

    + +

    Each size object also contains a scaled versions of some of the global + metrics described above. They can be accessed directly through the + face->size->metrics structure.

    + +

    Note that these values correspond to scaled versions of the design + global metrics, with no rounding/grid-fitting performed.. + They are also completely independent of any hinting process. In other + words, don't rely on them to get exact metrics at the pixel level. + They're expressed in 26.6 pixels.

    + +
    + ascender + +

    This is the scaled version of the original design ascender.

    +
    + descender + +

    This is the scaled version of the original design descender.

    +
    + height + +

    This is the scaled version of the original design text height. + That probably is the only field you should really use in this structure.

    +
    + max_advance + +

    Thi is the scaled version of the original design max advance.

    +
    + +

    Note that the face->size->metrics structure contains other + fields that are used to scale design coordinates to device space. They're + described, in the last chapter.

    + +

    + c. Kerning: +

    + +

    Kerning is the process of adjusting the position of two subsequent + glyph images in a string of text, in order to improve the general + appearance of text. Basically, it means that when the glyph for an + "A" is followed by the glyph for a "V", the space between them can + be slightly reduced to avoid extra "diagonal whitespace".

    + +

    Note that in theory, kerning can happen both in the horizontal and + vertical direction between two glyphs; however, it only happens in + the horizontal direction in nearly all cases except really extreme + ones.

    + +

    Note all font formats contain kerning information. Instead, they sometimes + rely on an additional file that contains various glyph metrics, including + kerning, but no glyph images. A good example would be the Type 1 format, + where glyph images are stored in a file with extension ".pfa" or ".pfb", + and where kerning metrics can be found in an additional file with extension + ".afm" or ".pfm".

    + +

    FreeType 2 allows you to deal with this, by providing the + FT_Attach_File and FT_Attach_Stream APIs. + Both functions are used to load additional metrics into a face object, + by reading them from an additional format-specific file. For example, + you could open a Type 1 font by doing the following:

    + +
    
    +      error = FT_New_Face( library, "/usr/shared/fonts/cour.pfb", 0, &face );
    +      if (error) { ... }
    +      
    +      error = FT_Attach_File( face, "/usr/shared/fonts/cour.afm" );
    +      if (error) { .. could not read kerning and additional metrics .. }
    +  
    + +

    Note that FT_Attach_Stream is similar to + FT_Attach_File except that it doesn't take a C string + to name the extra file, but a FT_Stream handle. Also, + reading a metrics file is in no way, mandatory.

    + +

    Finally, the file attachment APIs are very generic and can be used to + load any kind of extra information for a given face. The nature of the + additional content is entirely font format specific.

    + +

    FreeType 2 allows you to retrieve the kerning information between + two glyphs through the FT_Get_Kerning function, whose + interface looks like:

    + +
    
    +     FT_Vector  kerning;
    +     ...
    +     error = FT_Get_Kerning( face,                  // handle to face object
    +                             left,                  // left glyph index
    +                             right,                 // right glyph index
    +                             kerning_mode,          // kerning mode
    +                             &kerning );            // target vector
    +  
    + +

    As you see, the function takes a handle to a face object, the indices + of the left and right glyphs for which the kerning value is desired, + as well as an integer, called the "kerning mode", and a pointer to + a destination vector that receives the corresponding distances.

    + +

    The kerning mode is very similar to the "bbox mode" described in a + previous chapter. It's a enumeration that indicates how the + kerning distances are expressed in the target vector.

    + +

    The default value is ft_kerning_mode_default which + has value 0. It corresponds to kerning distances expressed in 26.6 + grid-fitted pixels (which means that the values are multiples of 64). + For scalable formats, this means that the design kerning distance is + scaled then rounded.

    + +

    The value ft_kerning_mode_unfitted corresponds to kerning + distances expressed in 26.6 unfitted pixels (i.e. that do not correspond + to integer coordinates). It's the design kerning distance that is simply + scaled without rounding.

    + +

    Finally, the value ft_kerning_mode_unscaled is used to + return the design kerning distance, expressed in font units. You can + later scale it to device space using the computations explained in the + last chapter of this section.

    + +

    Note that the "left" and "right" positions correspond to the visual + order of the glyphs in the string of text. This is important for + + bi-directional text, or simply when writing right-to-left text..

    + +
    + +

    + 4. Simple text rendering: kerning + centering: +

    + +

    In order to show off what we just learned, we will now show how to modify + the example code that was provided in section I to render a string of text, + and enhance it to support kerning and delayed rendering.

    + +

    + a. Kerning support: +

    + +

    Adding support for kerning to our code is trivial, as long as we consider + that we're still dealing with a left-to-right script like Latin. We + simply need to retrieve the kerning distance between two glyphs in order + to alter the pen position appropriately. The code looks like:

    + +
    +      FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +      FT_UInt       glyph_index;
    +      FT_Bool       use_kerning;
    +      FT_UInt       previous;
    +      int           pen_x, pen_y, n;
    +
    +      .. initialise library ..
    +      .. create face object ..
    +      .. set character size ..
    +      
    +      pen_x = 300;
    +      pen_y = 200;
    +      
    +      use_kerning = FT_HAS_KERNING(face);
    +      previous    = 0;
    +      
    +      for ( n = 0; n < num_chars; n++ )
    +      {
    +        // convert character code to glyph index
    +        glyph_index = FT_Get_Char_Index( face, text[n] );
    +        
    +        // retrieve kerning distance and move pen position
    +        if ( use_kerning && previous && glyph_index )
    +        {
    +          FT_Vector  delta;
    +          
    +          FT_Get_Kerning( face, previous, glyph_index,
    +                          ft_kerning_mode_default, &delta );
    +                          
    +          pen_x += delta.x >> 6;
    +        }
    +      
    +        // load glyph image into the slot (erase previous one)
    +        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER );
    +        if (error) continue;  // ignore errors
    +        
    +        // now, draw to our target surface
    +        my_draw_bitmap( &slot->bitmap,
    +                        pen_x + slot->bitmap_left,
    +                        pen_y - slot->bitmap_top );
    +                        
    +        // increment pen position
    +        pen_x += slot->advance.x >> 6;
    +        
    +        // record current glyph index
    +        previous = glyph_index
    +      }
    +   
    + +

    That's it. You'll notice that:

    + +
      +
    • + As kerning is determined from glyph indices, we need to explicitely + convert our character code into a glyph index, then later call + FT_Load_Glyph instead of FT_Load_Char. No big + deal, if you ask me :-) +

    • + +
    • + We use a boolean named use_kerning which is set with the + result of the macro FT_HAS_KERNING(face). It's + certainly faster not to call FT_Get_Kerning when we know + that the font face does not contain kerning information. +

    • + +
    • + We move the position of the pen before a new glyph is drawn. +

    • + +
    • + We did initialize the variable previous with the value 0, + which always correspond to the "missing glyph" (also called + .notdef in the Postscript world). There is never any + kerning distance associated with this glyph. +

    • + +
    • + We do not check the error code returned by FT_get_Kerning. + This is because the function always set the content of delta + to (0,0) when an error occurs. +

    • +
    + +

    As you see, this is not terribly complex :-)

    + +

    + b. Centering: +

    + +

    Our code begins to become interesting but it's still a bit too simple + for normal uses. For example, the position of the pen is determined + before we do the rendering when in a normal situation, you would want + to layout the text and measure it before computing its final position + (e.g. centering) or perform things like word-wrapping.

    + +

    We're thus now going to decompose our text rendering function into two + distinct but successive parts: the first one will position individual + glyph images on the baseline, while the second one will render the + glyphs. As we'll see, this has many advantages.

    + +

    We will thus start by storing individual glyph images, as well as their + position on the baseline. This can be done with code like:

    + +
    +      FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +      FT_UInt       glyph_index;
    +      FT_Bool       use_kerning;
    +      FT_UInt       previous;
    +      int           pen_x, pen_y, n;
    +      
    +      FT_Glyph      glyphs[ MAX_GLYPHS ];   // glyph image
    +      FT_Vector     pos   [ MAX_GLYPHS ];   // glyph position
    +      FT_UInt       num_glyphs;
    +
    +      .. initialise library ..
    +      .. create face object ..
    +      .. set character size ..
    +      
    +      pen_x = 0;   /* start at (0,0) !! */
    +      pen_y = 0;
    +      
    +      num_glyphs  = 0;
    +      use_kerning = FT_HAS_KERNING(face);
    +      previous    = 0;
    +      
    +      for ( n = 0; n < num_chars; n++ )
    +      {
    +        // convert character code to glyph index
    +        glyph_index = FT_Get_Char_Index( face, text[n] );
    +        
    +        // retrieve kerning distance and move pen position
    +        if ( use_kerning && previous && glyph_index )
    +        {
    +          FT_Vector  delta;
    +          
    +          FT_Get_Kerning( face, previous, glyph_index,
    +                          ft_kerning_mode_default, &delta );
    +                          
    +          pen_x += delta.x >> 6;
    +        }
    +      
    +        // store current pen position
    +        pos[ num_glyphs ].x = pen_x;
    +        pos[ num_glyphs ].y = pen_y;
    +      
    +        // load glyph image into the slot. DO NOT RENDER IT !!
    +        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
    +        if (error) continue;  // ignore errors, jump to next glyph
    +        
    +        // extract glyph image and store it in our table
    +        error = FT_Get_Glyph( face->glyph, & glyphs[num_glyphs] );
    +        if (error) continue;  // ignore errors, jump to next glyph
    +        
    +        // increment pen position
    +        pen_x += slot->advance.x >> 6;
    +        
    +        // record current glyph index
    +        previous = glyph_index
    +        
    +        // increment number of glyphs
    +        num_glyphs++;
    +      }
    +   
    + +

    As you see, this is a very simple variation of our previous code + where we extract each glyph image from the slot, and store it, along + with the corresponding position, in our tables.

    + +

    Note also that "pen_x" contains the total advance for the string of + text. We can now compute the bounding box of the text string with + a simple function like:

    + + +
    +      void   compute_string_bbox( FT_BBox  *abbox )
    +      {
    +        FT_BBox  bbox;
    +        
    +        // initialise string bbox to "empty" values
    +        bbox.xMin = bbox.yMin =  32000;
    +        bbox.xMax = bbox.yMax = -32000;
    +        
    +        // for each glyph image, compute its bounding box, translate it,
    +        // and grow the string bbox
    +        for ( n = 0; n < num_glyphs; n++ )
    +        {
    +          FT_BBox   glyph_bbox;
    +
    +          FT_Glyph_Get_CBox( glyphs[n], &glyph_bbox );
    +
    +          glyph_bbox.xMin += pos[n].x;
    +          glyph_bbox.xMax += pos[n].x;
    +          glyph_bbox.yMin += pos[n].y;
    +          glyph_bbox.yMax += pos[n].y;
    +
    +          if (glyph_bbox.xMin < bbox.xMin)
    +            bbox.xMin = glyph_bbox.xMin;
    +
    +          if (glyph_bbox.yMin < bbox.yMin)
    +            bbox.yMin = glyph_bbox.yMin;
    +
    +          if (glyph_bbox.xMax > bbox.xMax)
    +            bbox.xMax = glyph_bbox.xMax;
    +
    +          if (glyph_bbox.yMax &gy; bbox.yMax)
    +            bbox.yMax = glyph_bbox.yMax;
    +        }
    +        
    +        // check that we really grew the string bbox
    +        if ( bbox.xMin > bbox.xMax )
    +        {
    +          bbox.xMin = 0;
    +          bbox.yMin = 0;
    +          bbox.xMax = 0;
    +          bbox.yMax = 0;
    +        }
    +        
    +        // return string bbox
    +        *abbox = bbox;
    +      }
    +   
    + +

    The resulting bounding box dimensions can then be used to compute the + final pen position before rendering the string as in:

    + +
    +      // compute string dimensions in integer pixels
    +      string_width  = (string_bbox.xMax - string_bbox.xMin)/64;
    +      string_height = (string_bbox.yMax - string_bbox.yMin)/64;
    +   
    +      // compute start pen position in 26.6 cartesian pixels
    +      start_x = (( my_target_width  - string_width )/2)*64;
    +      start_y = (( my_target_height - string_height)/2)*64;
    +      
    +      for ( n = 0; n < num_glyphs; n++ )
    +      {
    +        FT_Glyph  image;
    +        FT_Vector pen;
    +        
    +        image = glyphs[n];
    +        
    +        pen.x = start_x + pos[n].x;
    +        pen.y = start_y + pos[n].y;
    +        
    +        error = FT_Glyph_To_Bitmap( &image, ft_render_mode_normal,
    +                                    &pen.x, 0 );
    +        if (!error)
    +        {
    +          FT_BitmapGlyph  bit = (FT_BitmapGlyph)image;
    +          
    +          my_draw_bitmap( bitmap->bitmap,
    +                          bitmap->left,
    +                          my_target_height - bitmap->top );
    +                          
    +          FT_Done_Glyph( image );
    +        }
    +      }
    +   
    + +

    You'll take note that:

    + +
      +
    • + The pen position is expressed in the cartesian space (i.e. Y upwards). +

    • + +
    • + We call FT_Glyph_To_Bitmap with the destroy + parameter set to 0 (false), in order to avoid destroying the original + glyph image. The new glyph bitmap is accessed through image + after the call and is typecasted to a FT_BitmapGlyph. +

    • + +
    • + We use translation when calling FT_Glyph_To_Bitmap. This + ensures that the left and top fields + of the bitmap glyph object are already set to the correct pixel + coordinates in the cartesian space. +

    • + +
    • + Of course, we still need to convert pixel coordinates from cartesian + to device space before rendering, hence the my_target_height - + bitmap->top in the call to my_draw_bitmap. +

    • + +
    + +

    The same loop can be used to render the string anywhere on our display + surface, without the need to reload our glyph images each time.. We + could also decide to implement word wrapping, and only draw

    + +
    +

    + 5. Advanced text rendering: transform + centering + kerning: +

    + +

    We are now going to modify our code in order to be able to easily + transform the rendered string, for example to rotate it. We will + start by performing a few minor improvements:

    + +

    a. packing & translating glyphs:

    + +

    We'll start by packing the information related to a single glyph image + into a single structure, instead of parallel arrays. We thus define the + following structure type:

    + +
    +     typedef struct TGlyph_
    +     {
    +       FT_UInt    index;    // glyph index
    +       FT_Vector  pos;      // glyph origin on the baseline
    +       FT_Glyph   image;    // glyph image
    +     
    +     } TGlyph, *PGlyph;
    +  
    + +

    We will also translate each glyph image directly after it is loaded + to its position on the baseline at load time. As we'll see, this + as several advantages. Our glyph sequence loader thus becomes:

    + +
    +      FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +      FT_UInt       glyph_index;
    +      FT_Bool       use_kerning;
    +      FT_UInt       previous;
    +      int           pen_x, pen_y, n;
    +      
    +      TGlyph        glyphs[ MAX_GLYPHS ];   // glyphs table
    +      PGlyph        glyph;                  // current glyph in table
    +      FT_UInt       num_glyphs;
    +
    +      .. initialise library ..
    +      .. create face object ..
    +      .. set character size ..
    +      
    +      pen_x = 0;   /* start at (0,0) !! */
    +      pen_y = 0;
    +      
    +      num_glyphs  = 0;
    +      use_kerning = FT_HAS_KERNING(face);
    +      previous    = 0;
    +
    +      glyph = glyphs;      
    +      for ( n = 0; n < num_chars; n++ )
    +      {
    +        glyph->index = FT_Get_Char_Index( face, text[n] );
    +        
    +        if ( use_kerning && previous && glyph->index )
    +        {
    +          FT_Vector  delta;
    +          
    +          FT_Get_Kerning( face, previous, glyph->index,
    +                          ft_kerning_mode_default, &delta );
    +                          
    +          pen_x += delta.x >> 6;
    +        }
    +      
    +        // store current pen position
    +        glyph->pos.x = pen_x;
    +        glyph->pos.y = pen_y;
    +      
    +        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
    +        if (error) continue;
    +        
    +        error = FT_Get_Glyph( face->glyph, &glyph->image );
    +        if (error) continue;
    +        
    +        // translate the glyph image now..
    +        FT_Glyph_Transform( glyph->image, 0, &glyph->pos );
    +        
    +        pen_x   += slot->advance.x >> 6;
    +        previous = glyph->index
    +        
    +        // increment number of glyphs
    +        glyph++;
    +      }
    +      // count number of glyphs loaded..
    +      num_glyphs = glyph - glyphs;
    +   
    + +

    Note that translating glyphs now has several advantages. The first + one, is that we don't need to translate the glyph bbox when we compute + the string's bounding box. The code becomes:

    + +
    +      void   compute_string_bbox( FT_BBox  *abbox )
    +      {
    +        FT_BBox  bbox;
    +        
    +        bbox.xMin = bbox.yMin =  32000;
    +        bbox.xMax = bbox.yMax = -32000;
    +        
    +        for ( n = 0; n < num_glyphs; n++ )
    +        {
    +          FT_BBox   glyph_bbox;
    +
    +          FT_Glyph_Get_CBox( glyphs[n], &glyph_bbox );
    +
    +          if (glyph_bbox.xMin < bbox.xMin)
    +            bbox.xMin = glyph_bbox.xMin;
    +
    +          if (glyph_bbox.yMin < bbox.yMin)
    +            bbox.yMin = glyph_bbox.yMin;
    +
    +          if (glyph_bbox.xMax > bbox.xMax)
    +            bbox.xMax = glyph_bbox.xMax;
    +
    +          if (glyph_bbox.yMax &gy; bbox.yMax)
    +            bbox.yMax = glyph_bbox.yMax;
    +        }
    +        
    +        if ( bbox.xMin > bbox.xMax )
    +        {
    +          bbox.xMin = 0;
    +          bbox.yMin = 0;
    +          bbox.xMax = 0;
    +          bbox.yMax = 0;
    +        }
    +        
    +        *abbox = bbox;
    +      }
    +   
    + +

    Now take a closer look, the compute_string_bbox can now + compute the bounding box of a transformed glyph string. For example, + we can do something like:

    + +
    
    +      FT_BBox    bbox;
    +      FT_Matrix  matrix;
    +      FT_Vector  delta;
    +   
    +      ... load glyph sequence
    +      
    +      ... setup "matrix" and "delta"
    +      
    +      // transform glyphs
    +      for ( n = 0; n < num_glyphs; n++ )
    +        FT_Glyph_Transform( glyphs[n].image, &matrix, &delta );
    +      
    +      // compute bounding box of transformed glyphs
    +      compute_string_bbox( &bbox );
    +   
    + +

    + b. Rendering a transformed glyph sequence: +

    + +

    However, directly transforming the glyphs in our sequence is not an idea + if we want to re-use them in order to draw the text string with various + angles or transforms. It's better to perform the affine transformation + just before the glyph is rendered, as in the following code:

    + +
    +      FT_Vector  start;
    +      FT_Matrix  transform;
    +   
    +      // get bbox of original glyph sequence
    +      compute_string_bbox( &string_bbox );
    +   
    +      // compute string dimensions in integer pixels
    +      string_width  = (string_bbox.xMax - string_bbox.xMin)/64;
    +      string_height = (string_bbox.yMax - string_bbox.yMin)/64;
    +   
    +      // set up start position in 26.6 cartesian space
    +      start.x = (( my_target_width  - string_width )/2)*64;
    +      start.y = (( my_target_height - string_height)/2)*64;
    +      
    +      // set up transform (a rotation here)
    +      matrix.xx = (FT_Fixed)( cos(angle)*0x10000);
    +      matrix.xy = (FT_Fixed)(-sin(angle)*0x10000);
    +      matrix.yx = (FT_Fixed)( sin(angle)*0x10000);
    +      matrix.yy = (FT_Fixed)( cos(angle)*0x10000);
    +      
    +      for ( n = 0; n < num_glyphs; n++ )
    +      {
    +        FT_Glyph  image;
    +        FT_Vector pen;
    +        FT_BBox   bbox;
    +        
    +        // create a copy of the original glyph
    +        error = FT_Glyph_Copy( glyphs[n].image, &image );
    +        if (error) continue;
    +
    +        // transform copy (this will also translate it to the correct
    +        // position
    +        FT_Glyph_Transform( image, &matrix, &start );
    +        
    +        // check bounding box, if the transformed glyph image
    +        // is not in our target surface, we can avoid rendering it
    +        FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox );
    +        if ( bbox.xMax <= 0 || bbox.xMin >= my_target_width  ||
    +             bbox.yMax <= 0 || bbox.yMin >= my_target_height )
    +          continue;
    +        
    +        // convert glyph image to bitmap (destroy the glyph copy !!)
    +        //
    +        error = FT_Glyph_To_Bitmap( &image,
    +                                    ft_render_mode_normal,
    +                                    0,      // no additional translation
    +                                    1 );    // destroy copy in "image"
    +        if (!error)
    +        {
    +          FT_BitmapGlyph  bit = (FT_BitmapGlyph)image;
    +          
    +          my_draw_bitmap( bitmap->bitmap,
    +                          bitmap->left,
    +                          my_target_height - bitmap->top );
    +                          
    +          FT_Done_Glyph( image );
    +        }
    +      }
    +   
    + +

    You'll notice a few changes compared to the original version of this + code:

    + +
      +
    • + We keep the original glyph images untouched, by transforming a + copy. +

    • + +
    • + We perform clipping computations, in order to avoid rendering & + drawing glyphs that are not within our target surface +

    • + +
    • + We always destroy the copy when calling FT_Glyph_To_Bitmap + in order to get rid of the transformed scalable image. Note that + the image is destroyed even when the function returns an error + code (which is why FT_Done_Glyph is only called within + the compound statement. +

    • + +
    • + The translation of the glyph sequence to the start pen position is + integrated in the call to FT_Glyph_Transform intead of + FT_Glyph_To_Bitmap. +

    • +
    + +

    It's possible to call this function several times to render the string + width different angles, or even change the way "start" is computed in + order to move it to different place.

    + +

    This code is the basis of the FreeType 2 demonstration program + named"ftstring.c". It could be easily extended to perform + advanced text layout or word-wrapping in the first part, without + changing the second one.

    + +

    Note however that a normal implementation would use a glyph cache in + order to reduce memory needs. For example, let's assume that our text + string is "FreeType". We would store three identical glyph images in + our table for the letter "e", which isn't optimal (especially when you + consider longer lines of text, or even whole pages..). +

    + +
    + +

    + 6. Accessing metrics in design font units, and scaling them: +

    + +

    Scalable font formats usually store a single vectorial image, called + an "outline", for each in a face. Each outline is defined in an abstract + grid called the "design space", with coordinates expressed in nominal + "font units". When a glyph image is loaded, the font driver usually + scales the outline to device space according to the current character + pixel size found in a FT_Size object. The driver may also + modify the scaled outline in order to significantly improve its + appearance on a pixel-based surface (a process known as "hinting" + or "grid-fitting").

    + +

    This chapter describes how design coordinates are scaled to device + space, and how to read glyph outlines and metrics in font units. This + is important for a number of things:

    + +
      +
    • + In order to perform "true" WYSIWYG text layout +

    • + +
    • + In order to access font content for conversion or analysis purposes +

    • +
    + +

    a.Scaling distances to device space:

    + +

    Design coordinates are scaled to device space using a simple scaling + transform, whose coefficients are computed with the help of the + character pixel size:

    + +
    
    +     device_x = design_x * x_scale
    +     device_y = design_y * y_scale
    +
    +     x_scale  = pixel_size_x / EM_size
    +     y_scale  = pixel_size_y / EM_size
    +  
    + +

    Here, the value EM_size is font-specific and correspond + to the size of an abstract square of the design space (called the "EM"), + which is used by font designers to create glyph images. It is thus + expressed in font units. It is also accessible directly for scalable + font formats as face->units_per_EM. You should + check that a font face contains scalable glyph images by using the + FT_IS_SCALABLE(face) macro, which returns true when + appropriate.

    + +

    When you call the function FT_Set_Pixel_Sizes, you're + specifying the value of pixel_size_x and pixel_size_y + you want to use to FreeType, which will immediately compute the values + of x_scale and y_scale.

    + +

    When you call the function FT_Set_Char_Size, you're + specifying the character size in physical "points", which is used, + along with the device's resolutions, to compute the character pixel + size, then the scaling factors.

    + +

    Note that after calling any of these two functions, you can access + the values of the character pixel size and scaling factors as fields + of the face->size->metrics structure. These fields are:

    + +
    + +
    + x_ppem + +

    Which stands for "X Pixels Per EM", this is the size in integer pixels + of the EM square, which also is the horizontal character pixel size, + called pixel_size_x in the above example.

    +
    + y_ppem + +

    Which stands for "Y Pixels Per EM", this is the size in integer pixels + of the EM square, which also is the vertical character pixel size, + called pixel_size_y in the above example.

    +
    + x_scale + +

    This is a 16.16 fixed float scale that is used to directly + scale horizontal distances from design space to 1/64th of device pixels. +

    +
    + y_scale + +

    This is a 16.16 fixed float scale that is used to directly scale + vertical distances from design space to 1/64th of device pixels.

    +
    +
    + +

    Basically, this means that you can scale a distance expressed in + font units to 26.6 pixels directly with the help of the FT_MulFix + function, as in:

    + +
    
    +      // convert design distances to 1/64th of pixels
    +      //
    +      pixels_x = FT_MulFix( design_x, face->size->metrics.x_scale );
    +      pixels_y = FT_MulFix( design_y, face->size->metrics.y_scale );
    +  
    + +

    However, you can also scale the value directly with more accuracy + by using doubles and the equations:

    + +
    
    +      FT_Size_Metrics*  metrics = &face->size->metrics;    // shortcut
    +      double            pixels_x, pixels_y;
    +      double            em_size, x_scale, y_scale;
    +
    +      // compute floating point scale factors
    +      //
    +      em_size = 1.0 * face->units_per_EM;
    +      x_scale = metrics->x_ppem / em_size;
    +      y_scale = metrics->y_ppem / em_size;
    +      
    +      // convert design distances to floating point pixels
    +      //
    +      pixels_x = design_x * x_scale;
    +      pixels_y = design_y * y_scale;
    +  
    + +

    + b. Accessing design metrics (glyph & global): +

    + +

    You can access glyph metrics in font units simply by specifying the + FT_LOAD_NO_SCALE bit flag in FT_Load_Glyph + or FT_Load_Char. The metrics returned in + face->glyph->metrics will all be in font units.

    + +

    You can access unscaled kerning data using the + ft_kerning_mode_unscaled mode

    + +

    Finally, a few global metrics are available directly in font units + as fields of the FT_Face handle, as described in chapter 3 + of this section.

    + +
    + +

    + Conclusion +

    + +

    This is the end of the second section of the FreeType 2 tutorial, + you're now able to access glyph metrics, manage glyph images, and + render text much more intelligently (kerning, measuring, transforming + & caching).

    + +

    You have now sufficient knowledge to build a pretty decent text service + on top of FreeType 2, and you could possibly stop there if you want.

    + +

    The next section will deal with FreeType 2 internals (like modules, + vector outlines, font drivers, renderers), as well as a few font format + specific issues (mainly, how to access certain TrueType or Type 1 tables). +

    +
    +
    + + + diff --git a/reactos/subsys/win32k/freetype/ftbase.c b/reactos/subsys/win32k/freetype/ftbase.c new file mode 100644 index 00000000000..b1a99e62808 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftbase.c @@ -0,0 +1,44 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* ftbase.c */ +/* */ +/* Single object library component (body only). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ftcalc.c" +#include "ftobjs.c" +#include "ftstream.c" +#include "ftlist.c" +#include "ftoutln.c" +#include "ftextend.c" +#include "ftnames.c" + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include +#include +#include +#include +#include + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftcalc.c b/reactos/subsys/win32k/freetype/ftcalc.c new file mode 100644 index 00000000000..d27de265246 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftcalc.c @@ -0,0 +1,773 @@ +/***************************************************************************/ +/* */ +/* ftcalc.c */ +/* */ +/* Arithmetic computations (body). */ +/* */ +/* Copyright 1996-2000 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(), and FT_DivFix() are declared in freetype.h. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include /* for ABS() */ + + + /*************************************************************************/ + /* */ + /* 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 + + +#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 + + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt32 */ + /* */ + /* */ + /* Computes the square root of an Int32 integer (which will be */ + /* handled as an unsigned long value). */ + /* */ + /* */ + /* x :: The value to compute the root for. */ + /* */ + /* */ + /* The result of `sqrt(x)'. */ + /* */ + FT_EXPORT_FUNC( 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 + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* */ + /* 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_FUNC( FT_Long ) FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ) + { + FT_Int s; + + + s = 1; + if ( a < 0 ) { a = -a; s = -s; } + if ( b < 0 ) { b = -b; s = -s; } + if ( c < 0 ) { c = -c; s = -s; } + + return s * ( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c + : 0x7FFFFFFFL ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* */ + /* 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_FUNC( FT_Long ) FT_MulFix( FT_Long a, + FT_Long b ) + { + FT_Int s; + + + s = 1; + if ( a < 0 ) { a = -a; s = -s; } + if ( b < 0 ) { b = -b; s = -s; } + + return s * (FT_Long)( ( (FT_Int64)a * b + 0x8000 ) >> 16 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DivFix */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* */ + /* 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_FUNC( 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 + /* compute result directly */ + q = ( (FT_Int64)a << 16 ) / b; + + return (FT_Int32)( s < 0 ? -q : 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt64 */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* l :: A 64-bit integer. */ + /* */ + /* */ + /* The 32-bit square-root. */ + /* */ + FT_EXPORT_FUNC( 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 r; + } + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + +#else /* FT_LONG64 */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* */ + /* 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'. */ + /* */ + /* */ + /* The FT_MulDiv() function has been optimized thanks to ideas from */ + /* Graham Asher. The trick is to optimize computation if everything */ + /* fits within 32 bits (a rather common case). */ + /* */ + /* We compute `a*b+c/2', then divide it by `c' (positive values). */ + /* */ + /* 46340 is FLOOR(SQRT(2^31-1)). */ + /* */ + /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */ + /* */ + /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */ + /* */ + /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */ + /* */ + /* and 2*0x157F0 = 176096. */ + /* */ + FT_EXPORT_FUNC( 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 <= 46340 && b <= 46340 && 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 = (FT_Int32)( c >> 31 ); + temp2.lo = (FT_UInt32)( c / 2 ); + FT_Add64( &temp, &temp2, &temp ); + a = FT_Div64by32( &temp, c ); + } + else + a = 0x7FFFFFFFL; + + return ( s < 0 ? -a : a ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* */ + /* The optimization for FT_MulFix() is different. We could simply be */ + /* happy by applying the same principles as with FT_MulDiv(), because */ + /* */ + /* c = 0x10000 < 176096 */ + /* */ + /* However, in most cases, we have a `b' with a value around 0x10000 */ + /* which is greater than 46340. */ + /* */ + /* According to some testing, most cases have `a' < 2048, so a good */ + /* idea is to use bounds like 2048 and 1048576 (=floor((2^31-1)/2048) */ + /* for `a' and `b', respectively. */ + /* */ + FT_EXPORT_FUNC( 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 ) >> 16 ); + } + + return ( s < 0 ? -(FT_Long)ua : ua ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DivFix */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* */ + /* The optimization for FT_DivFix() is simple: If (a << 16) fits into */ + /* 32 bits, then the division is computed directly. Otherwise, we */ + /* use a specialized version of the old FT_MulDiv64(). */ + /* */ + FT_EXPORT_FUNC( 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 ) / (FT_UInt32)b; + } + else + { + /* we need more bits; we have to do it by hand */ + FT_UInt32 c; + + + q = ( a / b ) << 16; + c = a % b; + + /* we must compute C*0x10000/B: we simply shift C and B so */ + /* C becomes smaller than 16 bits */ + while ( c >> 16 ) + { + c >>= 1; + b <<= 1; + } + + q += ( c << 16 ) / b; + } + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add64 */ + /* */ + /* */ + /* Add two Int64 values. */ + /* */ + /* */ + /* x :: A pointer to the first value to be added. */ + /* y :: A pointer to the second value to be added. */ + /* */ + /* */ + /* z :: A pointer to the result of `x + y'. */ + /* */ + /* */ + /* Will be wrapped by the ADD_64() macro. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Add64( FT_Int64* x, + FT_Int64* y, + FT_Int64* z ) + { + register FT_UInt32 lo, hi; + + + lo = x->lo + y->lo; + hi = x->hi + y->hi + ( lo < x->lo ); + + z->lo = lo; + z->hi = hi; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulTo64 */ + /* */ + /* */ + /* Multiplies two Int32 integers. Returns an Int64 integer. */ + /* */ + /* */ + /* x :: The first multiplier. */ + /* y :: The second multiplier. */ + /* */ + /* */ + /* z :: A pointer to the result of `x * y'. */ + /* */ + /* */ + /* Will be wrapped by the MUL_64() macro. */ + /* */ + FT_EXPORT_FUNC( 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_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2; + + + lo1 = x & 0x0000FFFF; hi1 = x >> 16; + lo2 = y & 0x0000FFFF; hi2 = y >> 16; + + lo = lo1 * lo2; + i1 = lo1 * hi2; + i2 = lo2 * hi1; + hi = hi1 * hi2; + + /* Check carry overflow of i1 + i2 */ + i1 += i2; + if ( i1 < i2 ) + hi += 1L << 16; + + hi += i1 >> 16; + i1 = i1 << 16; + + /* Check carry overflow of i1 + lo */ + lo += i1; + hi += ( lo < i1 ); + + z->lo = lo; + z->hi = hi; + } + + if ( s < 0 ) + { + z->lo = (FT_UInt32)-(FT_Int32)z->lo; + z->hi = ~z->hi + !( z->lo ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Div64by32 */ + /* */ + /* */ + /* Divides an Int64 value by an Int32 value. Returns an Int32 */ + /* integer. */ + /* */ + /* */ + /* x :: A pointer to the dividend. */ + /* y :: The divisor. */ + /* */ + /* */ + /* The result of `x / y'. */ + /* */ + /* */ + /* Will be wrapped by the DIV_64() macro. */ + /* */ + FT_EXPORT_FUNC( FT_Int32 ) FT_Div64by32( FT_Int64* x, + FT_Int32 y ) + { + FT_Int32 s; + FT_UInt32 q, r, i, lo; + + + 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; + else + q = 0x7FFFFFFFL; + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + + r = x->hi; + lo = x->lo; + + if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */ + return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL ); + /* Return Max/Min Int32 if division overflow. */ + /* This includes division by zero! */ + q = 0; + for ( i = 0; i < 32; i++ ) + { + r <<= 1; + q <<= 1; + r |= lo >> 31; + + if ( r >= (FT_UInt32)y ) + { + r -= y; + q |= 1; + } + lo <<= 1; + } + + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt64 */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* z :: A pointer to a 64-bit integer. */ + /* */ + /* */ + /* The 32-bit square-root. */ + /* */ + FT_EXPORT_FUNC( 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 */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftdebug.c b/reactos/subsys/win32k/freetype/ftdebug.c new file mode 100644 index 00000000000..da8b3b4aa3b --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftdebug.c @@ -0,0 +1,124 @@ +/***************************************************************************/ +/* */ +/* ftdebug.c */ +/* */ +/* Debugging and logging component (body). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef FT_DEBUG_LEVEL_TRACE + char ft_trace_levels[trace_max]; +#endif + + +#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE ) + + +#include +#include +#include + + + FT_EXPORT_FUNC( void ) FT_Message( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); +/* vprintf( fmt, ap ); FIXME */ + va_end( ap ); + } + + + FT_EXPORT_FUNC( void ) FT_Panic( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); +/* vprintf( fmt, ap ); FIXME */ + va_end( ap ); + +/* exit( EXIT_FAILURE ); FIXME */ + } + + +#ifdef FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* */ + /* FT_SetTraceLevel */ + /* */ + /* */ + /* Sets the trace level for debugging. */ + /* */ + /* */ + /* component :: The component which should be traced. See ftdebug.h */ + /* for a complete list. If set to `trace_any', all */ + /* components will be traced. */ + /* level :: The tracing level. */ + /* */ + FT_EXPORT_FUNC( 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 */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftextend.c b/reactos/subsys/win32k/freetype/ftextend.c new file mode 100644 index 00000000000..f298b19a8aa --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftextend.c @@ -0,0 +1,332 @@ +/***************************************************************************/ +/* */ +/* ftextend.h */ +/* */ +/* FreeType extensions implementation (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + + /*************************************************************************/ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Init_Extensions */ + /* */ + /* */ + /* Initializes the extension component. */ + /* */ + /* */ + /* driver :: A handle to the driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Extensions */ + /* */ + /* */ + /* Finalizes the extension component. */ + /* */ + /* */ + /* driver :: A handle to the driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error FT_Done_Extensions( FT_Driver driver ) + { + FT_Memory memory = driver->root.memory; + + + FREE( driver->extensions ); + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Register_Extension */ + /* */ + /* */ + /* Registers a new extension. */ + /* */ + /* */ + /* driver :: A handle to the driver object. */ + /* class :: A pointer to a class describing the extension. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Extension */ + /* */ + /* */ + /* Queries an extension block by an extension ID string. */ + /* */ + /* */ + /* face :: A handle to the face object. */ + /* extension_id :: An ID string identifying the extension. */ + /* */ + /* */ + /* extension_interface :: A generic pointer, usually pointing to a */ + /* table of functions implementing the */ + /* extension interface. */ + /* */ + /* */ + /* A generic pointer to the extension block. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Destroy_Extensions */ + /* */ + /* */ + /* Destroys all extensions within a face object. */ + /* */ + /* */ + /* face :: A handle to the face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Called by the face object destructor. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Create_Extensions */ + /* */ + /* */ + /* Creates an extension object within a face object for all */ + /* registered extensions. */ + /* */ + /* */ + /* face :: A handle to the face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Called by the face object constructor. */ + /* */ + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/ftglyph.c b/reactos/subsys/win32k/freetype/ftglyph.c new file mode 100644 index 00000000000..4052e6e4f88 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftglyph.c @@ -0,0 +1,1184 @@ +/***************************************************************************/ +/* */ +/* ftglyph.c */ +/* */ +/* FreeType convenience functions to handle glyphs (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + + /*************************************************************************/ + /* */ + /* 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 ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Multiply */ + /* */ + /* */ + /* Performs the matrix operation `b = a*b'. */ + /* */ + /* */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `a' or `b' is zero. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Invert */ + /* */ + /* */ + /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */ + /* */ + /* */ + /* matrix :: A pointer to the target matrix. Remains untouched in */ + /* case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_FUNC( 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( source->buffer, target->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->xMax - ( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Copy */ + /* */ + /* */ + /* A function used to copy a glyph image. */ + /* */ + /* */ + /* source :: A handle to the source glyph object. */ + /* */ + /* */ + /* target :: A handle to the target glyph object. 0 in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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, © ); + if ( error ) + goto Exit; + + if ( clazz->glyph_copy ) + error = clazz->glyph_copy( source, copy ); + + if ( error ) + FT_Done_Glyph( copy ); + else + *target = copy; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph */ + /* */ + /* */ + /* A function used to extract a glyph image from a slot. */ + /* */ + /* */ + /* slot :: A handle to the source glyph slot. */ + /* */ + /* */ + /* aglyph :: A handle to the glyph object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Transform */ + /* */ + /* */ + /* Transforms a glyph image if its format is scalable. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code (the glyph format is not scalable if it is */ + /* not zero). */ + /* */ + /* */ + /* The 2x2 transformation matrix is also applied to the glyph's */ + /* advance vector. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Get_CBox */ + /* */ + /* */ + /* Returns the glyph image's bounding box. */ + /* */ + /* */ + /* glyph :: A handle to the source glyph object. */ + /* */ + /* mode :: A set of bit flags that indicate how to interpret the */ + /* returned bounding box values. */ + /* */ + /* */ + /* box :: The glyph bounding box. Coordinates are expressed in */ + /* 1/64th of pixels if it is grid-fitted. */ + /* */ + /* */ + /* Coordinates are relative to the glyph origin, using the Y-upwards */ + /* convention. */ + /* */ + /* If `ft_glyph_bbox_subpixels' is set in `mode', the bbox */ + /* coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels). */ + /* Otherwise, coordinates are expressed in integer 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 the */ + /* `ft_glyph_bbox_gridfit' flag is set in `mode;, 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); */ + /* */ + /* The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Glyph_Get_CBox( FT_Glyph glyph, + FT_UInt bbox_mode, + FT_BBox* cbox ) + { + const FT_Glyph_Class* clazz; + FT_Error error = FT_Err_Ok; + + + if ( !cbox || !glyph || !glyph->clazz ) + error = FT_Err_Invalid_Argument; + else + { + clazz = glyph->clazz; + if ( !clazz->glyph_bbox ) + error = FT_Err_Invalid_Glyph_Format; + else + { + /* retrieve bbox in 26.6 coordinates */ + clazz->glyph_bbox( glyph, cbox ); + + /* perform grid fitting if needed */ + if ( bbox_mode & ft_glyph_bbox_gridfit ) + { + cbox->xMin &= -64; + cbox->yMin &= -64; + cbox->xMax = ( cbox->xMax + 63 ) & -64; + cbox->yMax = ( cbox->yMax + 63 ) & -64; + } + + /* convert to integer pixels if needed */ + if ( !( bbox_mode & ft_glyph_bbox_subpixels ) ) + { + cbox->xMin >>= 6; + cbox->yMin >>= 6; + cbox->xMax >>= 6; + cbox->yMax >>= 6; + } + } + } + return; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_To_Bitmap */ + /* */ + /* */ + /* Converts a given glyph object to a bitmap glyph object. */ + /* */ + /* */ + /* glyph :: A pointer to a handle to the target glyph. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 ) || + FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); + + if ( !destroy && origin ) + { + FT_Vector v; + + + v.x = -origin->x; + v.y = -origin->y; + FT_Glyph_Transform( glyph, 0, &v ); + } + + /* in case of succes, 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; + } + + if ( destroy ) + FT_Done_Glyph( glyph ); + + *the_glyph = FT_GLYPH( bitmap ); + } + + Exit: + return error; + + Bad: + error = FT_Err_Invalid_Argument; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Glyph */ + /* */ + /* */ + /* Destroys a given glyph. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + FT_EXPORT_FUNC( 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 ); + } + } + + +#if 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 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 */ + return ft_test_extrema( outline, indices.xMin ) || + ft_test_extrema( outline, indices.yMin ) || + ft_test_extrema( outline, indices.xMax ) || + ft_test_extrema( outline, indices.yMax ) || + 1; /* this is an empty glyph? */ + } + + + static + FT_Error ft_embolden( FT_Face original, + FT_Outline* outline, + FT_Pos* advance ) + { + FT_Vector u, v; + FT_Vector* points; + FT_Vector cur, prev, next; + FT_Pos distance; + int c, n, first, orientation; + + FT_UNUSED( advance ); + + + /* compute control distance */ + distance = FT_MulFix( original->em_size / 60, + original->size->metrics.y_scale ); + + orientation = ft_get_orientation( &original->glyph->outline ); + + points = original->glyph->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->flags[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; + } + +#endif /* 0 -- EXPERIMENTAL STUFF! */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftgrays.c b/reactos/subsys/win32k/freetype/ftgrays.c new file mode 100644 index 00000000000..7ed08388503 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftgrays.c @@ -0,0 +1,1969 @@ +/***************************************************************************/ +/* */ +/* ftgrays.c */ +/* */ +/* A new `perfect' anti-aliasing renderer (body). */ +/* */ +/* Copyright 2000 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_grays_raster.grays_raster_new'; an anti-aliased bitmap can be */ + /* generated with a call to `ft_grays_raster.grays_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 /* for memcpy() */ + + + /*************************************************************************/ + /* */ + /* 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 + + +#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_ */ + + +#ifdef FT_FLAT_COMPILE + +#include "ftgrays.h" + +#else + +#include + +#endif + + +#include /* for FT_UNUSED() */ +#include /* for FT_TRACE() and FT_ERROR() */ +#include /* for FT_Outline_Decompose() */ + +#define ErrRaster_Invalid_Mode FT_Err_Cannot_Render_Glyph +#define ErrRaster_Invalid_Outline FT_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 */ + /* */ + typedef int TScan; /* integer scanline/pixel coordinate */ + typedef long TPos; /* sub-pixel coordinate */ + + /* 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; + int 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; + + int area; + int cover; + int invalid; + + TScan ex, ey; + TScan cx, cy; + TPos x, y; + + TScan last_ey; + + FT_Vector bez_stack[32 * 3]; + int lev_stack[32]; + + FT_Outline outline; + FT_Bitmap target; + + 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; + + } TRaster, *PRaster; + + + /*************************************************************************/ + /* */ + /* Initialize the cells table. */ + /* */ + static + void 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 compute_cbox( RAS_ARG_ FT_Outline* 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 + int record_cell( RAS_ARG ) + { + PCell cell; + + + if ( !ras.invalid && ( ras.area | ras.cover ) ) + { + if ( ras.num_cells >= ras.max_cells ) + return 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; + } + + return 0; + } + + + /*************************************************************************/ + /* */ + /* Set the current cell to a new position. */ + /* */ + static + int 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 ) && record_cell( RAS_VAR ) ) + return 1; + + if ( clean ) + { + ras.area = 0; + ras.cover = 0; + } + + ras.invalid = invalid; + ras.ex = ex; + ras.ey = ey; + return 0; + } + + + /*************************************************************************/ + /* */ + /* Start a new contour at a given cell. */ + /* */ + static + void 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; + + (void)set_cell( RAS_VAR_ ex, ey ); + } + + + /*************************************************************************/ + /* */ + /* Render a scanline as one or more cells. */ + /* */ + static + int 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 ) + return set_cell( RAS_VAR_ ex2, ey ); + + /* everything is located in a single cell. That is easy! */ + /* */ + if ( ex1 == ex2 ) + { + delta = y2 - y1; + ras.area += ( fx1 + fx2 ) * delta; + ras.cover += delta; + return 0; + } + + /* 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 += ( fx1 + first ) * delta; + ras.cover += delta; + + ex1 += incr; + if ( set_cell( RAS_VAR_ ex1, ey ) ) + goto Error; + 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 += ONE_PIXEL * delta; + ras.cover += delta; + y1 += delta; + ex1 += incr; + if ( set_cell( RAS_VAR_ ex1, ey ) ) + goto Error; + } + } + + delta = y2 - y1; + ras.area += ( fx2 + ONE_PIXEL - first ) * delta; + ras.cover += delta; + + return 0; + + Error: + return 1; + } + + + /*************************************************************************/ + /* */ + /* Render a given line as a series of scanlines. */ + /* */ + static + int 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 ) + { + if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 ) ) + goto Error; + 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; + if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first ) ) + goto Error; + + ey1 += incr; + if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) ) + goto Error; + + 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; + if ( render_scanline( RAS_VAR_ ey1, + x, ONE_PIXEL - first, x2, first ) ) + goto Error; + x = x2; + ey1 += incr; + if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) ) + goto Error; + } + } + + if ( render_scanline( RAS_VAR_ ey1, + x, ONE_PIXEL - first, to_x, fy2 ) ) + goto Error; + + End: + ras.x = to_x; + ras.y = to_y; + ras.last_ey = SUBPIXELS( ey2 ); + + return 0; + + Error: + return 1; + } + + + static + void 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 + int 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 >>= 1; + level++; + } + + /* a shortcut to speed things up */ + if ( level <= 1 ) + { + /* we compute the mid-point directly in order to avoid */ + /* calling 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; + + return render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ); + } + + 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; + + 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; + + if ( render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ) ) + return 1; + + top--; + arc -= 2; + } + } + return 0; + } + + + static + void 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 + int 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 >>= 1; + db >>= 2; + 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; + + return render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ); + } + + 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; + 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; + + if ( render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ) ) + return 1; + top --; + arc -= 3; + } + } + return 0; + } + + + /* 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 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 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 = 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 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 Move_To( FT_Vector* to, + FT_Raster raster ) + { + TPos x, y; + + + /* record current cell, if any */ + record_cell( (PRaster)raster ); + + /* start to a new position */ + x = UPSCALE( to->x ); + y = UPSCALE( to->y ); + start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) ); + ((PRaster)raster)->x = x; + ((PRaster)raster)->y = y; + return 0; + } + + + static + int Line_To( FT_Vector* to, + FT_Raster raster ) + { + return render_line( (PRaster)raster, + UPSCALE( to->x ), UPSCALE( to->y ) ); + } + + + static + int Conic_To( FT_Vector* control, + FT_Vector* to, + FT_Raster raster ) + { + return render_conic( (PRaster)raster, control, to ); + } + + + static + int Cubic_To( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + FT_Raster raster ) + { + return render_cubic( (PRaster)raster, control1, control2, to ); + } + + + static + void grays_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 + + static + void 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 grays_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 += acount; + return; + } + + if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS ) + { + if ( ras.render_span ) + 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 grays_sweep( RAS_ARG_ FT_Bitmap* target ) + { + TScan x, y, cover, area; + PCell start, cur, limit; + + FT_UNUSED( target ); + + + 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 ) + { + grays_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 ) + grays_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 ) + grays_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. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Decompose */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* Error code. 0 means sucess. */ + /* */ + static + int FT_Outline_Decompose( FT_Outline* outline, + 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; + + int n; /* index of contour in outline */ + int first; /* index of first point in contour */ + int error; + char tag; /* current point's state */ + + int shift = interface->shift; + FT_Pos delta = interface->delta; + + + 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 grays_convert_glyph( RAS_ARG_ FT_Outline* outline ) + { + static + FT_Outline_Funcs interface = + { + (FT_Outline_MoveTo_Func) Move_To, + (FT_Outline_LineTo_Func) Line_To, + (FT_Outline_ConicTo_Func)Conic_To, + (FT_Outline_CubicTo_Func)Cubic_To, + 0, + 0 + }; + + TBand bands[40], *band; + int n, num_bands; + TPos min, max, max_y; + + + /* Set up state in the raster object */ + compute_cbox( RAS_VAR_ outline ); + + /* clip to target bitmap, exit if nothing to do */ + if ( ras.max_ex <= 0 || ras.min_ex >= ras.target.width || + ras.max_ey <= 0 || ras.min_ey >= ras.target.rows ) + return 0; + + if ( ras.min_ex < 0 ) ras.min_ex = 0; + if ( ras.min_ey < 0 ) ras.min_ey = 0; + + if ( ras.max_ex > ras.target.width ) ras.max_ex = ras.target.width; + if ( ras.max_ey > ras.target.rows ) ras.max_ey = ras.target.rows; + + /* simple heuristic used to speed-up the bezier decomposition -- see */ + /* the code in render_conic() and 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 += 2; + + 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; + + error = FT_Outline_Decompose( outline, &interface, &ras ) || + record_cell( RAS_VAR ); + + if ( !error ) + { +#ifdef SHELL_SORT + shell_sort( ras.cells, ras.num_cells ); +#else + quick_sort( ras.cells, ras.num_cells ); +#endif + +#ifdef DEBUG_GRAYS + check_sort( ras.cells, ras.num_cells ); + dump_cells( RAS_VAR ); +#endif + + grays_sweep( RAS_VAR_ &ras.target ); + band--; + continue; + } + + /* 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 grays_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 ( !target_map || !target_map->buffer ) + return -1; + + /* XXX: this version does not support monochrome rendering yet! */ + if ( !(params->flags & ft_raster_flag_aa) ) + return ErrRaster_Invalid_Mode; + + ras.outline = *outline; + ras.target = *target_map; + ras.num_cells = 0; + ras.invalid = 1; + + ras.render_span = (FT_Raster_Span_Func)grays_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 grays_convert_glyph( (PRaster)raster, outline ); + } + + + /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/ + /**** a static object. *****/ + +#ifdef _STANDALONE_ + + static + int grays_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 grays_raster_done( FT_Raster raster ) + { + /* nothing */ + FT_UNUSED( raster ); + } + +#else /* _STANDALONE_ */ + + static + int grays_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 grays_raster_done( FT_Raster raster ) + { + FT_Memory memory = (FT_Memory)((PRaster)raster)->memory; + + + FREE( raster ); + } + +#endif /* _STANDALONE_ */ + + + static + void grays_raster_reset( FT_Raster raster, + const char* pool_base, + long pool_size ) + { + PRaster rast = (PRaster)raster; + + + if ( raster && pool_base && pool_size >= 4096 ) + init_cells( rast, (char*)pool_base, pool_size ); + + rast->band_size = ( pool_size / sizeof ( TCell ) ) / 8; + } + + + FT_Raster_Funcs ft_grays_raster = + { + ft_glyph_format_outline, + + (FT_Raster_New_Func) grays_raster_new, + (FT_Raster_Reset_Func) grays_raster_reset, + (FT_Raster_Set_Mode_Func)0, + (FT_Raster_Render_Func) grays_raster_render, + (FT_Raster_Done_Func) grays_raster_done + }; + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftgrays.h b/reactos/subsys/win32k/freetype/ftgrays.h new file mode 100644 index 00000000000..2423a0e45ef --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftgrays.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ftgrays.h */ +/* */ +/* FreeType smooth renderer declaration */ +/* */ +/* Copyright 1996-2000 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 +#endif + + /*************************************************************************/ + /* */ + /* To make ftgrays.h independent from configuration files we check */ + /* whether FT_EXPORT_DEF 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( FT_Raster_Funcs ) ft_grays_raster; + +#ifdef __cplusplus + } +#endif + +#endif /* FTGRAYS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftinit.c b/reactos/subsys/win32k/freetype/ftinit.c new file mode 100644 index 00000000000..cc754eb856c --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftinit.c @@ -0,0 +1,155 @@ +/***************************************************************************/ +/* */ +/* ftinit.c */ +/* */ +/* FreeType initialization layer (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* 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 +#define FT_USE_MODULE( x ) extern const FT_Module_Class* x; + +#ifdef macintosh + FT_USE_MODULE(fond_driver_class) +#endif +#include + +#undef FT_USE_MODULE +#define FT_USE_MODULE( x ) (const FT_Module_Class*)&x, + +static +const FT_Module_Class* ft_default_modules[] = + { +#ifdef macintosh + FT_USE_MODULE(fond_driver_class) +#endif +#include + 0 + }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Default_Modules */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Add_Default_Modules( FT_Library library ) + { + FT_Error error; + const FT_Module_Class** 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++; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Init_FreeType */ + /* */ + /* */ + /* Initializes a new FreeType library object. The set of drivers */ + /* that are registered by this function is determined at build time. */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Init_FreeType( FT_Library* library ) + { + 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, library ); + if ( !error ) + FT_Add_Default_Modules( *library ); + + return error; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftlist.c b/reactos/subsys/win32k/freetype/ftlist.c new file mode 100644 index 00000000000..0158ba4434c --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftlist.c @@ -0,0 +1,301 @@ +/***************************************************************************/ +/* */ +/* ftlist.c */ +/* */ +/* Generic list support for FreeType (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Find */ + /* */ + /* */ + /* Finds the list node for a given listed object. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* data :: The address of the listed object. */ + /* */ + /* */ + /* List node. NULL if it wasn't found. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Add */ + /* */ + /* */ + /* Appends an element to the end of a list. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* node :: The node to append. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Insert */ + /* */ + /* */ + /* Inserts an element at the head of a list. */ + /* */ + /* */ + /* list :: A pointer to parent list. */ + /* node :: The node to insert. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Remove */ + /* */ + /* */ + /* Removes a node from a list. This function doesn't check whether */ + /* the node is in the list! */ + /* */ + /* */ + /* node :: The node to remove. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Up */ + /* */ + /* */ + /* Moves a node to the head/top of a list. Used to maintain LRU */ + /* lists. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* node :: The node to move. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Iterate */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The result (a FreeType error code) of the last iterator call. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Finalize */ + /* */ + /* */ + /* Destroys all elements in the list as well as the list itself. */ + /* */ + /* */ + /* 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. */ + /* */ + BASE_FUNC( 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/reactos/subsys/win32k/freetype/ftmm.c b/reactos/subsys/win32k/freetype/ftmm.c new file mode 100644 index 00000000000..0f6fddea28b --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftmm.c @@ -0,0 +1,176 @@ +/***************************************************************************/ +/* */ +/* ftmm.c */ +/* */ +/* Multiple Master font support (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Multi_Master */ + /* */ + /* */ + /* Retrieves the Multiple Master descriptor of a given font. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* */ + /* master :: The Multiple Masters descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master* master ) + { + 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, master ); + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Design_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through design coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Blend_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through normalized blend coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates (each one must be between 0 */ + /* and 1.0). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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/reactos/subsys/win32k/freetype/ftnames.c b/reactos/subsys/win32k/freetype/ftnames.c new file mode 100644 index 00000000000..43a0d12d073 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftnames.c @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* ftnames.c */ +/* */ +/* Simple interface to access SFNT name tables (which are used */ +/* to hold font names, copyright info, notices, etc.). */ +/* */ +/* This is _not_ used to retrieve glyph names! */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_CONFIG_OPTION_SFNT_NAMES + + + FT_EXPORT_FUNC( FT_UInt ) FT_Get_Sfnt_Name_Count( FT_Face face ) + { + return face && ( FT_IS_SFNT( face ) ? ((TT_Face)face)->num_names : 0 ); + } + + + FT_EXPORT_FUNC( 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 < 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 /* FT_CONFIG_OPTION_SFNT_NAMES */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftobjs.c b/reactos/subsys/win32k/freetype/ftobjs.c new file mode 100644 index 00000000000..de74882554b --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftobjs.c @@ -0,0 +1,3246 @@ +/***************************************************************************/ +/* */ +/* ftobjs.c */ +/* */ +/* The FreeType private base classes (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + +#include + +#include /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Alloc */ + /* */ + /* */ + /* Allocates a new block of memory. The returned area is always */ + /* zero-filled; this is a strong convention in many FreeType parts. */ + /* */ + /* */ + /* memory :: A handle to a given `memory object' which handles */ + /* allocation. */ + /* */ + /* size :: The size in bytes of the block to allocate. */ + /* */ + /* */ + /* P :: A pointer to the fresh new block. It should be set to */ + /* NULL if `size' is 0, or in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Realloc */ + /* */ + /* */ + /* Reallocates a block of memory pointed to by `*P' to `Size' bytes */ + /* from the heap, possibly changing `*P'. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* P :: A pointer to the fresh new block. It should be set to */ + /* NULL if `size' is 0, or in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* All callers of FT_Realloc() _must_ provide the current block size */ + /* as well as the new one. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Free */ + /* */ + /* */ + /* Releases a given block of memory allocated through FT_Alloc(). */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If P or *P are NULL, this function should return successfully. */ + /* This is a strong convention within all of FreeType and its */ + /* drivers. */ + /* */ + BASE_FUNC( 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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* ft_new_input_stream */ + /* */ + /* */ + /* Creates a new input stream object from an FT_Open_Args structure. */ + /* */ + /* */ + /* 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, + 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 ) + { + *stream = *(args->stream); + stream->memory = memory; + } + else + error = FT_Err_Invalid_Argument; + + if ( error ) + FREE( stream ); + + *astream = stream; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Stream */ + /* */ + /* */ + /* Closes and destroys a stream object. */ + /* */ + /* */ + /* stream :: The stream to be closed and destroyed. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Done_Stream( FT_Stream stream ) + { + if ( stream && stream->close ) + stream->close( stream ); + } + + + static + void ft_done_stream( FT_Stream* astream ) + { + FT_Stream stream = *astream; + FT_Memory memory = stream->memory; + + + if ( stream->close ) + stream->close( stream ); + + 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 */ + BASE_FUNC( 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 */ + BASE_FUNC( 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 */ + BASE_FUNC( 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 */ + BASE_FUNC( 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; + } + + + BASE_FUNC( 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! */ + /* */ + BASE_FUNC( 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; + + + /* check points & tags */ + new_max = base->n_points + current->n_points + n_points; + if ( new_max > loader->max_points ) + { + new_max = ( new_max + 7 ) & -8; + if ( REALLOC_ARRAY( base->points, base->n_points, + new_max, FT_Vector ) || + REALLOC_ARRAY( base->tags, base->n_points, + new_max, FT_Byte ) ) + goto Exit; + + if ( loader->use_extra && + REALLOC_ARRAY( loader->base.extra_points, base->n_points, + new_max, FT_Vector ) ) + goto Exit; + + adjust = 1; + loader->max_points = new_max; + } + + /* check contours */ + new_max = base->n_contours + current->n_contours + + n_contours; + if ( new_max > loader->max_contours ) + { + new_max = ( new_max + 3 ) & -4; + if ( REALLOC_ARRAY( base->contours, base->n_contours, + 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! */ + /* */ + BASE_FUNC( 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; + + FT_GlyphLoad* base = &loader->base; + FT_GlyphLoad* current = &loader->current; + + + new_max = base->num_subglyphs + current->num_subglyphs + n_subs; + if ( new_max > loader->max_subglyphs ) + { + new_max = ( new_max + 1 ) & -2; + if ( REALLOC_ARRAY( base->subglyphs, base->num_subglyphs, + 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 */ + BASE_FUNC( 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 */ + BASE_FUNC( 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 += current->outline.n_points; + 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] += n_base_points; + + /* prepare for another new glyph image */ + FT_GlyphLoader_Prepare( loader ); + } + + + BASE_FUNC( 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 = num_points; + out->n_contours = 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; + + + slot->library = driver->root.library; + + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + error = FT_GlyphLoader_New( memory, &slot->loader ); + + if ( !error && clazz->init_slot ) + error = clazz->init_slot( slot ); + + 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; + + + /* 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->loader ); + slot->loader = 0; + } + + if ( clazz->done_slot ) + clazz->done_slot( slot ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_GlyphSlot */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to a parent face object. */ + /* */ + /* */ + /* aslot :: A handle to a new glyph slot object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_GlyphSlot */ + /* */ + /* */ + /* Destroys a given glyph slot. Remember however that all slots are */ + /* automatically destroyed with its parent. Using this function is */ + /* not always mandatory. */ + /* */ + /* */ + /* slot :: A handle to a target glyph slot. */ + /* */ + FT_EXPORT_FUNC( 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; + } + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Transform */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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_FUNC( void ) FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ) + { + if ( !face ) + return; + + face->transform_flags = 0; + + if ( !matrix ) + { + face->transform_matrix.xx = 0x10000L; + face->transform_matrix.xy = 0; + face->transform_matrix.yx = 0; + face->transform_matrix.yy = 0x10000L; + matrix = &face->transform_matrix; + } + else + face->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 ) + face->transform_flags |= 1; + + if ( !delta ) + { + face->transform_delta.x = 0; + face->transform_delta.y = 0; + delta = &face->transform_delta; + } + else + face->transform_delta = *delta; + + /* set transform_flags bit flag 1 if `delta' isn't the null vector */ + if ( delta->x | delta->y ) + face->transform_flags |= 2; + } + + + static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Glyph */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* */ + /* face :: A handle to the target face object where the glyph */ + /* will be 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). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + /* do we need to load the glyph through the auto-hinter? */ + library = driver->root.library; + hinter = library->auto_hinter; + autohint = hinter && + !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ); + 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; + } + + /* now, transform the glyph image when needed */ + if ( face->transform_flags ) + { + /* get renderer */ + FT_Renderer renderer = ft_lookup_glyph_renderer( slot ); + + + if ( renderer ) + error = renderer->clazz->transform_glyph( renderer, slot, + &face->transform_matrix, + &face->transform_delta ); + /* transform advance */ + FT_Vector_Transform( &slot->advance, &face->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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Char */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size, according to its character code. */ + /* */ + /* */ + /* face :: A handle to a target face object where the glyph */ + /* will be loaded. */ + /* */ + /* 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). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 ); + } + + + /* 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->slot' */ + 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 */ + if ( ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) == 0 ) + ft_done_stream( &face->stream ); + + /* get rid of it */ + 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* open_face */ + /* */ + /* */ + /* 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; + + + clazz = driver->clazz; + memory = driver->root.memory; + + /* allocate the face object and perform basic initialization */ + if ( ALLOC( face, clazz->face_object_size ) ) + goto Fail; + + 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 ); + *aface = 0; + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a pathname to the font file. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* pathname :: A path to the font file. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* 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 */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_FUNC( 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a font file already loaded into memory. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* 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. */ + /* */ + /* face :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* 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 */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Memory_Face( FT_Library library, + FT_Byte* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face* face ) + { + 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, face ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Face */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* 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. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* 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 resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_FUNC( 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; + + + /* test for valid `library' and `args' delayed to */ + /* ft_new_input_stream() */ + + if ( !aface ) + return FT_Err_Invalid_Argument; + + *aface = 0; + + /* 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 ); + 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 ( error != FT_Err_Unknown_File_Format ) + goto Fail; + } + } + + ft_done_stream( &stream ); + + /* no driver is able to handle this format */ + error = FT_Err_Unknown_File_Format; + goto Fail; + } + + Success: + FT_TRACE4(( "FT_New_Face: New face object, adding to list\n" )); + + /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */ + if ( args->flags & ft_open_stream && args->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 transformation for convenience functions */ + face->transform_matrix.xx = 0x10000L; + face->transform_matrix.xy = 0; + face->transform_matrix.yx = 0; + face->transform_matrix.yy = 0x10000L; + + face->transform_delta.x = 0; + face->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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_File */ + /* */ + /* */ + /* `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. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* */ + /* filepathname :: An 8-bit pathname naming the `metrics' file. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_Stream */ + /* */ + /* */ + /* This function is similar to FT_Attach_File() with the exception */ + /* that it reads the attachment from an arbitrary stream. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* parameters :: A pointer to an FT_Open_Args structure used to */ + /* describe the input stream to FreeType. */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 */ + if ( !parameters->stream || ( parameters->flags & ft_open_stream ) ) + ft_done_stream( &stream ); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Face */ + /* */ + /* */ + /* Discards a given face object, as well as all of its child slots */ + /* and sizes. */ + /* */ + /* */ + /* face :: A handle to a target face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Size */ + /* */ + /* */ + /* Creates a new size object from a given face object. */ + /* */ + /* */ + /* face :: A handle to a parent face object. */ + /* */ + /* */ + /* asize :: A handle to a new size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Size */ + /* */ + /* */ + /* Discards a given size object. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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 FT_Err_Ok; + } + + + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Char_Size */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* When dealing with fixed-size faces (i.e., non-scalable formats), */ + /* use the function FT_Set_Pixel_Sizes(). */ + /* */ + FT_EXPORT_FUNC( 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_Memory memory; + 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; + memory = driver->root.memory; + + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Pixel_Sizes */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* pixel_width :: The character width, in integer pixels. */ + /* */ + /* pixel_height :: The character height, in integer pixels. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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_Memory memory; + 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; + memory = driver->root.memory; + + /* 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 = pixel_width; + metrics->y_ppem = 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Kerning */ + /* */ + /* */ + /* Returns the kerning vector between two glyphs of a same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( FT_Error ) FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_UInt kern_mode, + FT_Vector* kerning ) + { + FT_Error error = FT_Err_Ok; + FT_Driver driver; + FT_Memory memory; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + if ( !kerning ) + return FT_Err_Invalid_Argument; + + driver = face->driver; + memory = driver->root.memory; + + kerning->x = 0; + kerning->y = 0; + + if ( driver->clazz->get_kerning ) + { + error = driver->clazz->get_kerning( face, + left_glyph, + right_glyph, + kerning ); + if ( !error ) + { + if ( kern_mode != ft_kerning_unscaled ) + { + kerning->x = FT_MulFix( kerning->x, face->size->metrics.x_scale ); + kerning->y = FT_MulFix( kerning->y, face->size->metrics.y_scale ); + + if ( kern_mode != ft_kerning_unfitted ) + { + kerning->x = ( kerning->x + 32 ) & -64; + kerning->y = ( kerning->y + 32 ) & -64; + } + } + } + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Select_Charmap */ + /* */ + /* */ + /* Selects a given charmap by its encoding tag (as listed in */ + /* `freetype.h'). */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* encoding :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function will return an error if no charmap in the face */ + /* corresponds to the encoding queried here. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Charmap */ + /* */ + /* */ + /* Selects a given charmap for character code to glyph index */ + /* decoding. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* charmap :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Char_Index */ + /* */ + /* */ + /* Returns the glyph index of a given character code. This function */ + /* uses a charmap object to do the translation. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph_Name */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to a source face object. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* buffer :: A pointer to a target buffer where the name will be */ + /* copied to. */ + /* */ + /* buffer_max :: The maximal number of bytes available in the */ + /* buffer. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Sfnt_Table */ + /* */ + /* */ + /* Returns a pointer to a given SFNT table within a face. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* tag :: An index of an SFNT table. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 the FT_Sfnt_Tag */ + /* enumeration in `tttables.h' for a list. */ + /* */ + /* You can load any table with a different function.. XXX */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** R E N D E R E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* lookup a renderer by glyph format in the library's list */ + BASE_FUNC( 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 ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Renderer */ + /* */ + /* */ + /* Retrieves the current renderer for a given glyph format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* format :: The glyph format. */ + /* */ + /* */ + /* A renderer handle. 0 if none found. */ + /* */ + /* */ + /* 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_FUNC( 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Renderer */ + /* */ + /* */ + /* Sets the current renderer to use, and set additional mode. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* renderer :: A handle to the renderer object. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* parameters :: Additional parameters. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_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; + } + + + LOCAL_FUNC + 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 || 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Render_Glyph */ + /* */ + /* */ + /* Converts a given glyph image to a bitmap. It does so by */ + /* inspecting the glyph image format, find the relevant renderer, and */ + /* invoke it. */ + /* */ + /* */ + /* slot :: A handle to the glyph slot containing the image to */ + /* convert. */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Destroy_Module */ + /* */ + /* */ + /* Destroys a given module object. For drivers, this also destroys */ + /* all child faces. */ + /* */ + /* */ + /* module :: A handle to the target driver object. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Module */ + /* */ + /* */ + /* Adds a new module to a given library instance. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* clazz :: A pointer to class descriptor for the module. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module */ + /* */ + /* */ + /* Finds a module by its name. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module handle. 0 if none was found. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for :-) */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module_Interface */ + /* */ + /* */ + /* Finds a module and returns its specific interface as a typeless */ + /* pointer. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module-specific interface if available, 0 otherwise. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for, and what its interface is :-) */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Remove_Module */ + /* */ + /* */ + /* Removes a given module from a library instance. */ + /* */ + /* */ + /* library :: A handle to a library object. */ + /* */ + /* module :: A handle to a module object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The module object is destroyed by the function in case of success. */ + /* */ + FT_EXPORT_FUNC( 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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Library */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* memory :: A handle to the original memory object. */ + /* */ + /* */ + /* alibrary :: A pointer to handle of a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Library */ + /* */ + /* */ + /* Discards a given library object. This closes all drivers and */ + /* discards all resource objects. */ + /* */ + /* */ + /* library :: A handle to the target library. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Debug_Hook */ + /* */ + /* */ + /* Sets a debug hook function for debugging the interpreter of a font */ + /* format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* 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. */ + /* */ + /* */ + /* Currently, four debug hook slots are available, but only two (for */ + /* the TrueType and the Type 1 interpreter) are defined. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_FreeType */ + /* */ + /* */ + /* Destroys a given FreeType library object and all of its childs, */ + /* including resources, drivers, faces, sizes, etc. */ + /* */ + /* */ + /* library :: A handle to the target library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Done_FreeType( FT_Library library ) + { + /* test for valid `library' delayed to FT_Done_Library() */ + + /* Discard the library object */ + FT_Done_Library( library ); + + return FT_Err_Ok; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftoutln.c b/reactos/subsys/win32k/freetype/ftoutln.c new file mode 100644 index 00000000000..20292d0c3ae --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftoutln.c @@ -0,0 +1,842 @@ +/***************************************************************************/ +/* */ +/* ftoutln.c */ +/* */ +/* FreeType outline management (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + + /*************************************************************************/ + /* */ + /* 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 }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Decompose */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means sucess. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Outline_Decompose( + FT_Outline* outline, + 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 */ + char 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_FUNC( FT_Error ) FT_Outline_New_Internal( + FT_Memory memory, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ) + { + FT_Error error; + + + if ( !outline || !memory ) + return FT_Err_Invalid_Argument; + + *outline = null_outline; + + if ( ALLOC_ARRAY( outline->points, numPoints * 2L, FT_Pos ) || + ALLOC_ARRAY( outline->tags, numPoints, FT_Byte ) || + ALLOC_ARRAY( outline->contours, numContours, FT_UShort ) ) + goto Fail; + + outline->n_points = (FT_UShort)numPoints; + outline->n_contours = (FT_Short)numContours; + outline->flags |= ft_outline_owner; + + return FT_Err_Ok; + + Fail: + outline->flags |= ft_outline_owner; + FT_Outline_Done_Internal( memory, outline ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_New */ + /* */ + /* */ + /* Creates a new outline of a given size. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* outline :: A handle to the new outline. NULL in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* The reason why this function takes a `library' parameter is simply */ + /* to use the library's memory allocator. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Outline_New( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ) + { + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + return FT_Outline_New_Internal( library->memory, numPoints, + numContours, outline ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Copy */ + /* */ + /* */ + /* Copies an outline into another one. Both objects must have the */ + /* same sizes (number of points & number of contours) when this */ + /* function is called. */ + /* */ + /* */ + /* source :: A handle to the source outline. */ + /* */ + /* */ + /* target :: A handle to the target outline. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Done */ + /* */ + /* */ + /* Destroys an outline created with FT_Outline_New(). */ + /* */ + /* */ + /* library :: A handle of the library object used to allocate the */ + /* outline. */ + /* */ + /* outline :: A pointer to the outline object to be discarded. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* If the outline's `owner' field is not set, only the outline */ + /* descriptor will be released. */ + /* */ + /* The reason why this function takes an `outline' parameter is */ + /* simply to use FT_Free(). */ + /* */ + FT_EXPORT_FUNC( 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_CBox */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* */ + /* cbox :: The outline's control box. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Outline_Get_CBox( FT_Outline* outline, + FT_BBox* cbox ) + { + FT_Pos xMin, yMin, xMax, yMax; + + + if ( outline && cbox ) + { + 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; + } + } + cbox->xMin = xMin; + cbox->xMax = xMax; + cbox->yMin = yMin; + cbox->yMax = yMax; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Translate */ + /* */ + /* */ + /* Applies a simple translation to the points of an outline. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* xOffset :: The horizontal offset. */ + /* */ + /* yOffset :: The vertical offset. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_FUNC( 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++; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Reverse */ + /* */ + /* */ + /* Reverses the drawing direction of an outline. This is used to */ + /* ensure consistent fill conventions for mirrored glyphs. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* */ + /* This functions toggles the bit flag `ft_outline_reverse_fill' in */ + /* the outline's `flags' field. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Render */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* params :: A pointer to a FT_Raster_Params structure used to */ + /* describe the rendering operation. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* 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_FUNC( 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 || 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_Bitmap */ + /* */ + /* */ + /* Renders an outline within a bitmap. The outline's image is simply */ + /* OR-ed to the target bitmap. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* map :: A pointer to the target bitmap descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* 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_FUNC( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap* bitmap ) + { + FT_Raster_Params params; + + + if ( !bitmap ) + return FT_Err_Invalid_Argument; + + /* other checks are delayed to FT_Outline_Render() */ + + params.target = bitmap; + params.flags = 0; + + if ( bitmap->pixel_mode == ft_pixel_mode_grays ) + params.flags |= ft_raster_flag_aa; + + return FT_Outline_Render( library, outline, ¶ms ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector_Transform */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* vector :: The target vector to transform. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Transform */ + /* */ + /* */ + /* Applies a simple 2x2 matrix to all of an outline's points. Useful */ + /* for applying rotations, slanting, flipping, etc. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* matrix :: A pointer to the transformation matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* You can use FT_Outline_Translate() if you need to translate the */ + /* outline's points. */ + /* */ + FT_EXPORT_FUNC( 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/reactos/subsys/win32k/freetype/ftraster.c b/reactos/subsys/win32k/freetype/ftraster.c new file mode 100644 index 00000000000..65d04057d70 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftraster.c @@ -0,0 +1,3300 @@ +/***************************************************************************/ +/* */ +/* ftraster.c */ +/* */ +/* The FreeType glyph rasterizer (body). */ +/* */ +/* Copyright 1996-2000 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 "ftraster.h" +#include /* 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 +#include /* for FT_TRACE() and FT_ERROR() */ + +#define Raster_Err_None FT_Err_Ok +#define Raster_Err_Not_Ini FT_Err_Raster_Uninitialized +#define Raster_Err_Overflow FT_Err_Raster_Overflow +#define Raster_Err_Neg_Height FT_Err_Raster_Negative_Height +#define Raster_Err_Invalid FT_Err_Invalid_Outline +#define Raster_Err_Unsupported FT_Err_Unimplemented_Feature + + +#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 */ + + UShort 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[2 * 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 **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Set_High_Precision */ + /* */ + /* */ + /* Sets precision variables according to param flag. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* New_Profile */ + /* */ + /* */ + /* Creates a new profile in the render pool. */ + /* */ + /* */ + /* aState :: The state/orientation of the new profile. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* End_Profile */ + /* */ + /* */ + /* Finalizes the current profile. */ + /* */ + /* */ + /* SUCCESS on success. FAILURE in case of overflow or incoherency. */ + /* */ + static + Bool End_Profile( RAS_ARG ) + { + Long h; + PProfile oldProfile; + + + h = 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Insert_Y_Turn */ + /* */ + /* */ + /* Inserts a salient into the sorted list placed on top of the render */ + /* pool. */ + /* */ + /* */ + /* New y scanline position. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Finalize_Profile_Table */ + /* */ + /* */ + /* Adjusts all links in the profiles list. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Split_Conic */ + /* */ + /* */ + /* Subdivides one conic Bezier into two joint sub-arcs in the Bezier */ + /* stack. */ + /* */ + /* */ + /* None (subdivided Bezier is taken from the top of the stack). */ + /* */ + /* */ + /* 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 ;-) */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Split_Cubic */ + /* */ + /* */ + /* Subdivides a third-order Bezier arc into two joint sub-arcs in the */ + /* Bezier stack. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_Up */ + /* */ + /* */ + /* Computes the x-coordinates of an ascending line segment and stores */ + /* them in the render pool. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 = ( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_Down */ + /* */ + /* */ + /* Computes the x-coordinates of an descending line segment and */ + /* stores them in the render pool. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* Bezier_Up */ + /* */ + /* */ + /* Computes the x-coordinates of an ascending Bezier arc and stores */ + /* them in the render pool. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 = 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Bezier_Down */ + /* */ + /* */ + /* Computes the x-coordinates of an descending Bezier arc and stores */ + /* them in the render pool. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_To */ + /* */ + /* */ + /* Injects a new line segment and adjusts Profiles list. */ + /* */ + /* */ + /* 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'). */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Conic_To */ + /* */ + /* */ + /* Injects a new conic arc and adjusts the profile list. */ + /* */ + /* */ + /* 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'). */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Cubic_To */ + /* */ + /* */ + /* Injects a new cubic arc and adjusts the profile list. */ + /* */ + /* */ + /* 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'). */ + /* */ + /* */ + /* 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 ) + + + /*************************************************************************/ + /* */ + /* */ + /* Decompose_Curve */ + /* */ + /* */ + /* 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! */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + char 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Convert_Glyph */ + /* */ + /* */ + /* Converts a glyph into a series of segments and arcs and makes a */ + /* profiles list with them. */ + /* */ + /* */ + /* flipped :: If set, flip the direction of curve. */ + /* */ + /* */ + /* SUCCESS on success, FAILURE if any error was encountered during */ + /* rendering. */ + /* */ + static + Bool Convert_Glyph( RAS_ARGS int flipped ) + { + Short i; + UShort 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 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 ( 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 = ¤t->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 = ¤t->link; + current = *old; + } + + /* we should never get there, unless the profile was not part of */ + /* the list. */ + } + + + /*************************************************************************/ + /* */ + /* Update */ + /* */ + /* Update all X offsets of a drawing list. */ + /* */ + static + void Update( PProfile first ) + { + PProfile current = first; + + + while ( current ) + { + current->X = *current->offset; + current->offset += current->flow; + current->height--; + current = current->link; + } + } + + + /*************************************************************************/ + /* */ + /* 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 */ + Update( *list ); + + /* Then sort them */ + old = list; + current = *old; + + if ( !current ) + return; + + next = current->link; + + while ( next ) + { + if ( current->X <= next->X ) + { + old = ¤t->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; + Short 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 = (unsigned char)0xFF >> ( e1 & 7 ); + f2 = ~( (unsigned char)0x7F >> ( e2 & 7 ) ); + + if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1; + if ( ras.gray_max_x < c2 ) ras.gray_max_x = 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 = 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 = 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 = 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 = 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 */ + + { + PProfile Q, P; + + + P = draw_left; + while ( P ) + { + Q = P->link; + if ( P->height == 0 ) + DelOld( &draw_left, P ); + P = Q; + } + } + + { + PProfile 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Render_Single_Pass */ + /* */ + /* */ + /* Performs one sweep with sub-banding. */ + /* */ + /* */ + /* flipped :: If set, flip the direction of the outline. */ + /* */ + /* */ + /* 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 = ( 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 = k - 1; + + ras.band_top++; + } + else + { + if ( ras.fProfile ) + if ( Draw_Sweep( RAS_VAR ) ) + return ras.error; + ras.band_top--; + } + } + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Render_Glyph */ + /* */ + /* */ + /* Renders a glyph in a bitmap. Sub-banding if needed. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* XXX Fixme: ftraster's error codes don't harmonize with FT2's ones! */ + /* */ + LOCAL_FUNC + 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 = !( 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 = ras.target.rows - 1; + + ras.bWidth = 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 = ras.target.width - 1; + + if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 ) + return error; + } + + return FT_Err_Ok; + } + + +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + + /*************************************************************************/ + /* */ + /* */ + /* Render_Gray_Glyph */ + /* */ + /* */ + /* Renders a glyph with grayscaling. Sub-banding if needed. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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 FT_Err_Ok; + } + +#else /* FT_RASTER_OPTION_ANTI_ALIASING */ + + LOCAL_FUNC + FT_Error Render_Gray_Glyph( RAS_ARG ) + { + FT_UNUSED_RASTER; + + return FT_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; + + if ( !outline || !outline->contours || !outline->points ) + return Raster_Err_Invalid; + + /* return immediately if the outline is empty */ + if ( outline->n_points == 0 || outline->n_contours <= 0 ) + return Raster_Err_None; + + if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 ) + return Raster_Err_Invalid; + + if ( !target_map || !target_map->buffer ) + 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; + + ras.outline = *outline; + ras.target = *target_map; + + return ( ( params->flags & ft_raster_flag_aa ) + ? Render_Gray_Glyph( raster ) + : Render_Glyph( raster ) ); + } + + + 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/reactos/subsys/win32k/freetype/ftraster.h b/reactos/subsys/win32k/freetype/ftraster.h new file mode 100644 index 00000000000..5c7faae5a26 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftraster.h @@ -0,0 +1,50 @@ +/***************************************************************************/ +/* */ +/* ftraster.h */ +/* */ +/* The FreeType glyph rasterizer (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef __cplusplus + extern "C" { +#endif + +#include + + + /*************************************************************************/ + /* */ + /* Uncomment the following line if you are using ftraster.c as a */ + /* standalone module, fully independent of FreeType. */ + /* */ +/* #define _STANDALONE_ */ + +#ifndef FT_EXPORT_VAR +#define FT_EXPORT_VAR( x ) extern x +#endif + + FT_EXPORT_VAR( FT_Raster_Funcs ) ft_standard_raster; + +#ifdef __cplusplus + } +#endif + + +#endif /* FTRASTER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftrend1.c b/reactos/subsys/win32k/freetype/ftrend1.c new file mode 100644 index 00000000000..d774cf1d404 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftrend1.c @@ -0,0 +1,275 @@ +/***************************************************************************/ +/* */ +/* ftrend1.c */ +/* */ +/* The FreeType glyph rasterizer interface (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ftrend1.h" +#include "ftraster.h" + +#else + +#include +#include + +#endif + + + /* 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 FT_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 = FT_Err_Ok; + + + if ( slot->format != render->glyph_format ) + { + error = FT_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 = FT_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 FT_Err_Cannot_Render_Glyph; + } + else + { + /* raster5 is only capable of producing 5-gray-levels bitmaps */ + if ( render->clazz == &ft_raster5_renderer_class ) + return FT_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, ¶ms ); + 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; + } + + + 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'll need */ + /* to register it by hand in your application. It should only be */ + /* used for backwards-compatibility with FT 1.x anyway. */ + 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/reactos/subsys/win32k/freetype/ftrend1.h b/reactos/subsys/win32k/freetype/ftrend1.h new file mode 100644 index 00000000000..b8fff83114a --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftrend1.h @@ -0,0 +1,37 @@ +/***************************************************************************/ +/* */ +/* ftrend1.h */ +/* */ +/* The FreeType glyph rasterizer interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + + 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; + + +#endif /* FTREND1_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftsmooth.c b/reactos/subsys/win32k/freetype/ftsmooth.c new file mode 100644 index 00000000000..f67ea58e493 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftsmooth.c @@ -0,0 +1,223 @@ +// ReactOS adjustments: +// * pitch rounded up to DWORD + +/***************************************************************************/ +/* */ +/* ftsmooth.c */ +/* */ +/* Anti-aliasing renderer interface (body). */ +/* */ +/* Copyright 2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ftsmooth.h" +#include "ftgrays.h" + +#else + +#include +#include + +#endif + + + /* 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 = FT_Err_Ok; + + + if ( slot->format != render->glyph_format ) + { + error = FT_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 = FT_Err_Invalid_Argument; + goto Exit; + } + + /* check mode */ + if ( mode != ft_render_mode_normal ) + return FT_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) + 3) & ~3; // round up to DWORD (adjusted for use by ReactOS' win32k) + 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, ¶ms ); + 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; + } + + + 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/reactos/subsys/win32k/freetype/ftsmooth.h b/reactos/subsys/win32k/freetype/ftsmooth.h new file mode 100644 index 00000000000..4b8a5334376 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftsmooth.h @@ -0,0 +1,35 @@ +/***************************************************************************/ +/* */ +/* ftsmooth.h */ +/* */ +/* Anti-aliasing renderer interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#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 + +#endif /* FTSMOOTH_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ftstream.c b/reactos/subsys/win32k/freetype/ftstream.c new file mode 100644 index 00000000000..768586ebbf4 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftstream.c @@ -0,0 +1,818 @@ +/***************************************************************************/ +/* */ +/* ftstream.c */ +/* */ +/* I/O stream support (body). */ +/* */ +/* Copyright 2000 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 +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( FT_Error ) FT_Skip_Stream( FT_Stream stream, + FT_Long distance ) + { + return FT_Seek_Stream( stream, (FT_ULong)( stream->pos + distance ) ); + } + + + BASE_FUNC( FT_Long ) FT_Stream_Pos( FT_Stream stream ) + { + return stream->pos; + } + + + BASE_FUNC( FT_Error ) FT_Read_Stream( FT_Stream stream, + FT_Byte* buffer, + FT_ULong count ) + { + return FT_Read_Stream_At( stream, stream->pos, buffer, count ); + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( void ) FT_Release_Frame( FT_Stream stream, + FT_Byte** pbytes ) + { + if ( stream->read ) + { + FT_Memory memory = stream->memory; + + + FREE( *pbytes ); + } + *pbytes = 0; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( FT_Error ) FT_Read_Fields( FT_Stream stream, + const FT_Frame_Field* fields, + void* structure ) + { + FT_Error error; + FT_Bool frame_accessed = 0; + + + 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; + fields++; + continue; /* loop! */ + + case ft_frame_bytes: /* read a byte sequence */ + case ft_frame_skip: /* skip some bytes */ + { + FT_Int len = fields->size; + + + if ( stream->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, stream->cursor, len ); + } + stream->cursor += len; + fields++; + continue; + } + + case ft_frame_byte: + case ft_frame_schar: /* read a single byte */ + value = GET_Byte(); + sign_shift = 24; + break; + + case ft_frame_short_be: + case ft_frame_ushort_be: /* read a 2-byte big-endian short */ + value = GET_UShort(); + sign_shift = 16; + break; + + case ft_frame_short_le: + case ft_frame_ushort_le: /* read a 2-byte little-endian short */ + { + FT_Byte* p; + + + value = 0; + p = stream->cursor; + + if ( p + 1 < stream->limit ) + { + value = ( FT_UShort)p[0] | ((FT_UShort)p[1] << 8 ); + stream->cursor += 2; + } + sign_shift = 16; + break; + } + + case ft_frame_long_be: + case ft_frame_ulong_be: /* read a 4-byte big-endian long */ + value = GET_ULong(); + sign_shift = 0; + break; + + case ft_frame_long_le: + case ft_frame_ulong_le: /* read a 4-byte little-endian long */ + { + FT_Byte* p; + + + value = 0; + p = stream->cursor; + + if ( p + 3 < stream->limit ) + { + value = (FT_ULong)p[0] | + ( (FT_ULong)p[1] << 8 ) | + ( (FT_ULong)p[2] << 16 ) | + ( (FT_ULong)p[3] << 24 ); + stream->cursor += 4; + } + sign_shift = 0; + break; + } + + case ft_frame_off3_be: + case ft_frame_uoff3_be: /* read a 3-byte big-endian long */ + value = GET_UOffset(); + sign_shift = 8; + break; + + case ft_frame_off3_le: + case ft_frame_uoff3_le: /* read a 3-byte little-endian long */ + { + FT_Byte* p; + + + value = 0; + p = stream->cursor; + + if ( p + 2 < stream->limit ) + { + value = (FT_ULong)p[0] | + ( (FT_ULong)p[1] << 8 ) | + ( (FT_ULong)p[2] << 16 ); + stream->cursor += 3; + } + sign_shift = 8; + break; + } + + default: + /* otherwise, exit the loop */ + 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/reactos/subsys/win32k/freetype/ftsystem.c b/reactos/subsys/win32k/freetype/ftsystem.c new file mode 100644 index 00000000000..090e550e218 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ftsystem.c @@ -0,0 +1,313 @@ +/***************************************************************************/ +/* */ +/* ftsystem.c */ +/* */ +/* ANSI-specific FreeType low-level system interface (body). */ +/* */ +/* Copyright 1996-2000 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 + +#include +#include +#include +#include +#include + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* 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(). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* ft_alloc */ + /* */ + /* */ + /* The memory allocation function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* size :: The requested size in bytes. */ + /* */ + /* */ + /* block :: The address of newly allocated block. */ + /* */ + static + void* ft_alloc( FT_Memory memory, + long size ) + { +PVOID newmem; + FT_UNUSED( memory ); + +/* return malloc( size ); */ + + return ExAllocatePool(NonPagedPool, size); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_realloc */ + /* */ + /* */ + /* The memory reallocation function. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The address of the reallocated memory block. */ + /* */ + static + 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 ); */ + ExFreePool(block); + return ExAllocatePool(NonPagedPool, new_size); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_free */ + /* */ + /* */ + /* The memory release function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* block :: The address of block in memory to be freed. */ + /* */ + static + void ft_free( FT_Memory memory, + void* block ) + { + FT_UNUSED( memory ); + +/* free( block ); */ + ExFreePool(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 ) + + + /*************************************************************************/ + /* */ + /* */ + /* ft_close_stream */ + /* */ + /* */ + /* The function to close a stream. */ + /* */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + static + void ft_close_stream( FT_Stream stream ) + { +DbgPrint("ftsystem.c: UNIMPLEMENTED CALL\n"); +/* fclose( STREAM_FILE( stream ) ); FIXME */ + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_io_stream */ + /* */ + /* */ + /* The function to open a stream. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The number of bytes actually read. */ + /* */ + static + unsigned long ft_io_stream( FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count ) + { + FILE* file; + + + file = STREAM_FILE( stream ); + +DbgPrint("ftsystem.c: UNIMPLEMENTED CALL\n"); +/* fseek( file, offset, SEEK_SET ); FIXME */ + +/* return (unsigned long)fread( buffer, 1, count, file ); FIXME */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Stream */ + /* */ + /* */ + /* Creates a new stream object. */ + /* */ + /* */ + /* filepathname :: The name of the stream (usually a file) to be */ + /* opened. */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Stream( const char* filepathname, + FT_Stream stream ) + { +/* FILE* file; FIXME */ + + +DbgPrint("ftsystem.c: UNIMPLEMENTED CALL\n"); + + if ( !stream ) + 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 ); + stream->size = ftell( file ); + fseek( file, 0, SEEK_SET ); + + stream->descriptor.pointer = file; + stream->pathname.pointer = (char*)filepathname; + stream->pos = 0; + + stream->read = ft_io_stream; + stream->close = ft_close_stream; FIXME */ + + FT_TRACE1(( "FT_New_Stream:" )); + FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", + filepathname, stream->size )); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory */ + /* */ + /* */ + /* Creates a new memory object. */ + /* */ + /* */ + /* A pointer to the new memory object. 0 in case of error. */ + /* */ + FT_EXPORT_FUNC( FT_Memory ) FT_New_Memory( void ) + { + FT_Memory memory; + + +/* memory = (FT_Memory)malloc( sizeof ( *memory ) ); FIXME */ + + memory = ExAllocatePool(NonPagedPool, sizeof(*memory)); + + if ( memory ) + { + memory->user = 0; + memory->alloc = ft_alloc; + memory->realloc = ft_realloc; + memory->free = ft_free; + } + + return memory; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/config/ftconfig.h b/reactos/subsys/win32k/freetype/include/freetype/config/ftconfig.h new file mode 100644 index 00000000000..338e22cb2a3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/config/ftconfig.h @@ -0,0 +1,187 @@ +/***************************************************************************/ +/* */ +/* ftconfig.h */ +/* */ +/* ANSI-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-2000 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/', 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 the header file containing all developer build options */ +#include + + + /*************************************************************************/ + /* */ + /* 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/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + + /* We use values to know the sizes of the types. */ +#include + + /* The number of bytes in an `int' type. */ +#if UINT_MAX == 0xFFFFFFFF +#define FT_SIZEOF_INT 4 +#elif UINT_MAX == 0xFFFF +#define FT_SIZEOF_INT 2 +#elif UINT_MAX > 0xFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF +#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 == 0xFFFFFFFF +#define FT_SIZEOF_LONG 4 +#elif ULONG_MAX > 0xFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF +#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 + +#if FT_SIZEOF_LONG == 8 + + /* FT_LONG64 must be defined if a 64-bit type is available */ +#define FT_LONG64 +#define FT_INT64 long + +#else + + + /*************************************************************************/ + /* */ + /* Many compilers provide the non-ANSI `long long' 64-bit type. You can */ + /* activate it by defining the FTCALC_USE_LONG_LONG macro in */ + /* `ftoption.h'. */ + /* */ + /* Note that this will produce many -ansi warnings during library */ + /* compilation, and that in many cases, the generated code will be */ + /* neither smaller nor faster! */ + /* */ +#ifdef FTCALC_USE_LONG_LONG + +#define FT_LONG64 +#define FT_INT64 long long + +#endif /* FTCALC_USE_LONG_LONG */ +#endif /* FT_SIZEOF_LONG == 8 */ + + +#ifdef FT_MAKE_OPTION_SINGLE_OBJECT +#define LOCAL_DEF static +#define LOCAL_FUNC static +#else +#define LOCAL_DEF extern +#define LOCAL_FUNC /* nothing */ +#endif + +#ifdef FT_MAKE_OPTION_SINGLE_LIBRARY_OBJECT +#define BASE_DEF( x ) static x +#define BASE_FUNC( x ) static x +#else +#define BASE_DEF( x ) extern x +#define BASE_FUNC( x ) extern x +#endif + +#ifndef FT_EXPORT_DEF +#define FT_EXPORT_DEF( x ) extern x +#endif + +#ifndef FT_EXPORT_FUNC +#define FT_EXPORT_FUNC( x ) extern x +#endif + +#ifndef FT_EXPORT_VAR +#define FT_EXPORT_VAR( x ) extern x +#endif + +#endif /* FTCONFIG_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/config/ftmodule.h b/reactos/subsys/win32k/freetype/include/freetype/config/ftmodule.h new file mode 100644 index 00000000000..50cc46b5c6c --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/config/ftmodule.h @@ -0,0 +1,10 @@ +FT_USE_MODULE(autohint_module_class) +FT_USE_MODULE(cff_driver_class) +FT_USE_MODULE(t1cid_driver_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/reactos/subsys/win32k/freetype/include/freetype/config/ftoption.h b/reactos/subsys/win32k/freetype/include/freetype/config/ftoption.h new file mode 100644 index 00000000000..a7e1f406a26 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/config/ftoption.h @@ -0,0 +1,395 @@ +/***************************************************************************/ +/* */ +/* ftoption.h */ +/* */ +/* User-selectable configuration macros (specification only). */ +/* */ +/* Copyright 1996-2000 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 + + + /*************************************************************************/ + /* */ + /* 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/' 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 + + + /*************************************************************************/ + /* */ + /* 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 the non-ANSI `long long' 64-bit type. You can */ + /* activate it by defining the FTCALC_USE_LONG_LONG macro. Note that */ + /* this will produce many -ansi warnings during library compilation, and */ + /* that in many cases the generated code will not be smaller or faster! */ + /* */ +#undef FTCALC_USE_LONG_LONG + + + /*************************************************************************/ + /* */ + /* 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_DEF and FT_EXPORT_FUNC. */ + /* */ + /* FT_EXPORT_DEF( return_type ) */ + /* */ + /* is used in a function declaration, as in */ + /* */ + /* FT_EXPORT_DEF( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ); */ + /* */ + /* */ + /* FT_EXPORT_FUNC( return_type ) */ + /* */ + /* is used in a function definition, as in */ + /* */ + /* FT_EXPORT_FUNC( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ) */ + /* { */ + /* ... some code ... */ + /* return FT_Err_Ok; */ + /* } */ + /* */ + /* You can provide your own implementation of FT_EXPORT_DEF and */ + /* FT_EXPORT_FUNC 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_DEF +#undef FT_EXPORT_FUNC + + + /*************************************************************************/ + /* */ + /* 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. */ + /* */ +#define 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 16384 + + + /*************************************************************************/ + /* */ + /* 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_STACK_DEPTH is the maximal depth of the token stack used by */ + /* the Type 1 parser (see t1load.c). A minimum of 16 is required. */ + /* */ +#define T1_MAX_STACK_DEPTH 16 + + + /*************************************************************************/ + /* */ + /* 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 8 + + + /*************************************************************************/ + /* */ + /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. */ + /* */ +#define T1_MAX_CHARSTRINGS_OPERANDS 32 + + + /*************************************************************************/ + /* */ + /* 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 + + +#endif /* FTOPTION_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/freetype.h b/reactos/subsys/win32k/freetype/include/freetype/freetype.h new file mode 100644 index 00000000000..29316c67bab --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/freetype.h @@ -0,0 +1,2286 @@ +/***************************************************************************/ +/* */ +/* freetype.h */ +/* */ +/* FreeType high-level API and common types (specification only). */ +/* */ +/* Copyright 1996-2000 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. */ + /* */ +#define _FREETYPE_ + + + /*************************************************************************/ + /* */ + /* 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 /* read configuration information */ +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S I C T Y P E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Metrics */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Generic_Finalizer */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Generic */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Bitmap_Size */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* FT_Library */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* Library objects are created through FT_Init_FreeType(). */ + /* */ + typedef struct FT_LibraryRec_ *FT_Library; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Module */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Driver */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Renderer */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Face */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Size */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_GlyphSlot */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_CharMap */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Encoding */ + /* */ + /* */ + /* An enumeration used to specify encodings supported by charmaps. */ + /* Used in the FT_Select_CharMap() API function. */ + /* */ + /* */ + /* Because of 32-bit charcodes defined in Unicode (i.e., surrogates), */ + /* all character codes must be expressed as FT_Longs. */ + /* */ + typedef enum FT_Encoding_ + { + ft_encoding_none = 0, + ft_encoding_symbol = FT_MAKE_TAG( 's', 'y', 'm', 'b' ), + ft_encoding_unicode = FT_MAKE_TAG( 'u', 'n', 'i', 'c' ), + ft_encoding_latin_2 = FT_MAKE_TAG( 'l', 'a', 't', '2' ), + ft_encoding_sjis = FT_MAKE_TAG( 's', 'j', 'i', 's' ), + ft_encoding_gb2312 = FT_MAKE_TAG( 'g', 'b', ' ', ' ' ), + ft_encoding_big5 = FT_MAKE_TAG( 'b', 'i', 'g', '5' ), + ft_encoding_wansung = FT_MAKE_TAG( 'w', 'a', 'n', 's' ), + ft_encoding_johab = FT_MAKE_TAG( 'j', 'o', 'h', 'a' ), + + ft_encoding_adobe_standard = FT_MAKE_TAG( 'A', 'D', 'O', 'B' ), + ft_encoding_adobe_expert = FT_MAKE_TAG( 'A', 'D', 'B', 'E' ), + ft_encoding_adobe_custom = FT_MAKE_TAG( 'A', 'D', 'B', 'C' ), + + ft_encoding_apple_roman = FT_MAKE_TAG( 'a', 'r', 'm', 'n' ) + + /* other encodings might be defined in the future */ + + } FT_Encoding; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_CharMapRec */ + /* */ + /* */ + /* The base charmap class. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* flags :: A set of bit flags used to describe the charmap. */ + /* Each bit indicates that a given encoding is */ + /* supported. */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* FreeType base face class */ + /* */ + /* */ + /* FT_FaceRec */ + /* */ + /* */ + /* FreeType root face class structure. A face object models the */ + /* resolution and point-size independent data found in a font file. */ + /* */ + /* */ + /* 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 it used */ + /* to hook and 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. */ + /* */ + /* 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. */ + /* */ + 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; + + /* the face's table of available charmaps */ + FT_Int num_charmaps; + FT_CharMap* charmaps; + + FT_Generic generic; + + /* the following are only relevant for 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; + + /************************************************************/ + /* The following fields should be considered private and */ + /* rarely, if ever, used directly by client applications. */ + + FT_Driver driver; + FT_Memory memory; + FT_Stream stream; + + FT_CharMap charmap; + FT_ListRec sizes_list; + + FT_Generic autohint; + void* extensions; + + FT_UShort max_points; + FT_Short max_contours; + + FT_Matrix transform_matrix; + FT_Vector transform_delta; + FT_Int transform_flags; + + } FT_FaceRec; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_SCALABLE */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_FIXED_SIZES */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_FIXED_WIDTH */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_SFNT */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_HORIZONTAL */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_VERTICAL */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_KERNING */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_FAST_GLYPHS */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_MULTIPLE_MASTERS */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_GLYPH_NAMES */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_EXTERNAL_STREAM */ + /* */ + /* */ + /* 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 + + +#define FT_HAS_HORIZONTAL( face ) \ + ( face->face_flags & FT_FACE_FLAG_HORIZONTAL ) +#define FT_HAS_VERTICAL( face ) \ + ( face->face_flags & FT_FACE_FLAG_VERTICAL ) +#define FT_HAS_KERNING( face ) \ + ( face->face_flags & FT_FACE_FLAG_KERNING ) +#define FT_IS_SCALABLE( face ) \ + ( face->face_flags & FT_FACE_FLAG_SCALABLE ) +#define FT_IS_SFNT( face ) \ + ( face->face_flags & FT_FACE_FLAG_SFNT ) +#define FT_IS_FIXED_WIDTH( face ) \ + ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) +#define FT_HAS_FIXED_SIZES( face ) \ + ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) +#define FT_HAS_FAST_GLYPHS( face ) \ + ( face->face_flags & FT_FACE_FLAG_FAST_GLYPHS ) +#define FT_HAS_GLYPH_NAMES( face ) \ + ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) + +#define FT_HAS_MULTIPLE_MASTERS( face ) \ + ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_STYLE_FLAG_ITALIC */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face is */ + /* italicized. */ + /* */ +#define FT_STYLE_FLAG_ITALIC 1 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_STYLE_FLAG_BOLD */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face is */ + /* emboldened. */ + /* */ +#define FT_STYLE_FLAG_BOLD 2 + + + /*************************************************************************/ + /* */ + /* FreeType base size metrics */ + /* */ + /* */ + /* FT_Size_Metrics */ + /* */ + /* */ + /* The size metrics structure returned scaled important distances for */ + /* a given size object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* x_resolution :: The horizontal device resolution for this size */ + /* object, expressed in integer dots per inches */ + /* (dpi). As a convention, fixed font formats set */ + /* this value to 72. */ + /* */ + /* y_resolution :: The vertical device resolution for this size */ + /* object, expressed in integer dots per inches */ + /* (dpi). As a convention, fixed font formats set */ + /* this value to 72. */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 */ + /* */ + /* */ + /* FT_SizeRec */ + /* */ + /* */ + /* FreeType root size class structure. A size object models the */ + /* resolution and pointsize dependent data of a given face. */ + /* */ + /* */ + /* 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_SizeRec; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_SubGlyph */ + /* */ + /* */ + /* The subglyph structure is an internal object used to describe */ + /* subglyphs (for example, in the case of composites). */ + /* */ + /* */ + /* The subglyph implementation is not part of the high-level API, */ + /* hence the forward structure declaration. */ + /* */ + typedef struct FT_SubGlyph_ FT_SubGlyph; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_GlyphLoader */ + /* */ + /* */ + /* The glyph loader is an internal object used to load several glyphs */ + /* together (for example, in the case of composites). */ + /* */ + /* */ + /* The glyph loader implementation is not part of the high-level API, */ + /* hence the forward structure declaration. */ + /* */ + typedef struct FT_GlyphLoader_ FT_GlyphLoader; + + + /*************************************************************************/ + /* */ + /* FreeType Glyph Slot base class */ + /* */ + /* */ + /* FT_GlyphSlotRec */ + /* */ + /* */ + /* FreeType root glyph slot class structure. A glyph slot is a */ + /* container where individual glyphs can be loaded, be they */ + /* vectorial or bitmap/graymaps. */ + /* */ + /* */ + /* 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 size 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_UNSCALED_LINEAR 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. */ + /* */ + /* loader :: This is a private object for the glyph slot. */ + /* Do not touch this. */ + /* */ + /* */ + /* If FT_Load_Glyph() is called with default flags (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; + + /* private fields */ + FT_GlyphLoader* loader; + + } FT_GlyphSlotRec; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* F U N C T I O N S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Init_FreeType */ + /* */ + /* */ + /* Initializes a new FreeType library object. The set of drivers */ + /* that are registered by this function is determined at build time. */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Init_FreeType( FT_Library* library ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_FreeType */ + /* */ + /* */ + /* Destroys a given FreeType library object and all of its childs, */ + /* including resources, drivers, faces, sizes, etc. */ + /* */ + /* */ + /* library :: A handle to the target library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Done_FreeType( FT_Library library ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Flags */ + /* */ + /* */ + /* An enumeration used to list the bit flags used within */ + /* FT_Open_Args(). */ + /* */ + /* */ + /* 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. */ + /* */ + 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Parameter */ + /* */ + /* */ + /* A simple structure used to pass more or less generic parameters */ + /* to FT_Open_Face(). */ + /* */ + /* */ + /* tag :: A 4-byte identification tag. */ + /* */ + /* data :: A pointer to the parameter data. */ + /* */ + /* */ + /* The id and function of parameters are driver-specific. */ + /* */ + typedef struct FT_Parameter_ + { + FT_ULong tag; + FT_Pointer data; + + } FT_Parameter; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Args */ + /* */ + /* */ + /* 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(). */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* `stream_type' determines which fields are used to create a new */ + /* input stream. */ + /* */ + /* If it is `ft_stream_memory', a new memory-based stream will be */ + /* created using the memory block specified by `memory_base' and */ + /* `memory_size'. */ + /* */ + /* If it is `ft_stream_pathname', a new stream will be created with */ + /* the `pathname' field, calling the system-specific FT_New_Stream() */ + /* function. */ + /* */ + /* If is is `ft_stream_copy', then the content of `stream' will be */ + /* copied to a new input stream object. The object will be closed */ + /* and destroyed when the face is destroyed itself. Note that this */ + /* means that you should not close the stream before the library */ + /* does! */ + /* */ + typedef struct FT_Open_Args_ + { + FT_Open_Flags flags; + 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a pathname to the font file. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* pathname :: A path to the font file. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* 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 */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_New_Face( FT_Library library, + const char* filepathname, + FT_Long face_index, + FT_Face* face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a font file already loaded into memory. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* 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. */ + /* */ + /* face :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* 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 */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_New_Memory_Face( FT_Library library, + FT_Byte* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face* face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Face */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* 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. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* 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 resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Open_Face( FT_Library library, + FT_Open_Args* args, + FT_Long face_index, + FT_Face* face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_File */ + /* */ + /* */ + /* `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. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* */ + /* filepathname :: An 8-bit pathname naming the `metrics' file. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Attach_File( FT_Face face, + const char* filepathname ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_Stream */ + /* */ + /* */ + /* This function is similar to FT_Attach_File() with the exception */ + /* that it reads the attachment from an arbitrary stream. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* parameters :: A pointer to an FT_Open_Args structure used to */ + /* describe the input stream to FreeType. */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Attach_Stream( FT_Face face, + FT_Open_Args* parameters ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Face */ + /* */ + /* */ + /* Discards a given face object, as well as all of its child slots */ + /* and sizes. */ + /* */ + /* */ + /* face :: A handle to a target face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Done_Face( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Char_Size */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* When dealing with fixed-size faces (i.e., non-scalable formats), */ + /* use the function FT_Set_Pixel_Sizes(). */ + /* */ + 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_Set_Pixel_Sizes */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* pixel_width :: The character width, in integer pixels. */ + /* */ + /* pixel_height :: The character height, in integer pixels. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Glyph */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* */ + /* face :: A handle to the target face object where the glyph */ + /* will be 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). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Load_Glyph( FT_Face face, + FT_UInt glyph_index, + FT_Int load_flags ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Char */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size, according to its character code. */ + /* */ + /* */ + /* face :: A handle to a target face object where the glyph */ + /* will be loaded. */ + /* */ + /* 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). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Load_Char( FT_Face face, + FT_ULong char_code, + FT_Int load_flags ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_SCALE */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_HINTING */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_RENDER */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_BITMAP */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_VERTICAL_LAYOUT */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_FORCE_AUTOHINT */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_CROP_BITMAP */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_PEDANTIC */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_RECURSE */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_IGNORE_TRANSFORM */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_MONOCHROME */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_LINEAR_DESIGN */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_DEFAULT */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Transform */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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_DEF( void ) FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Render_Mode */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Render_Glyph */ + /* */ + /* */ + /* Converts a given glyph image to a bitmap. It does so by */ + /* inspecting the glyph image format, find the relevant renderer, and */ + /* invoke it. */ + /* */ + /* */ + /* slot :: A handle to the glyph slot containing the image to */ + /* convert. */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Render_Glyph( FT_GlyphSlot slot, + FT_UInt render_mode ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Kerning_Mode */ + /* */ + /* */ + /* An enumeration used to specify which kerning values to return in */ + /* FT_Get_Kerning(). */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Kerning */ + /* */ + /* */ + /* Returns the kerning vector between two glyphs of a same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_UInt kern_mode, + FT_Vector* kerning ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph_Name */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to a source face object. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* buffer :: A pointer to a target buffer where the name will be */ + /* copied to. */ + /* */ + /* buffer_max :: The maximal number of bytes available in the */ + /* buffer. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Get_Glyph_Name( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Select_Charmap */ + /* */ + /* */ + /* Selects a given charmap by its encoding tag (as listed in */ + /* `freetype.h'). */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* encoding :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function will return an error if no charmap in the face */ + /* corresponds to the encoding queried here. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Select_Charmap( FT_Face face, + FT_Encoding encoding ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Charmap */ + /* */ + /* */ + /* Selects a given charmap for character code to glyph index */ + /* decoding. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* charmap :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Set_Charmap( FT_Face face, + FT_CharMap charmap ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Char_Index */ + /* */ + /* */ + /* Returns the glyph index of a given character code. This function */ + /* uses a charmap object to do the translation. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + FT_EXPORT_DEF( FT_UInt ) FT_Get_Char_Index( FT_Face face, + FT_ULong charcode ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* */ + /* 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_DEF( FT_Long ) FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* */ + /* 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_DEF( FT_Long ) FT_MulFix( FT_Long a, + FT_Long b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DivFix */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* */ + /* 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_DEF( FT_Long ) FT_DivFix( FT_Long a, + FT_Long b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector_Transform */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* vector :: The target vector to transform. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT_DEF( void ) FT_Vector_Transform( FT_Vector* vec, + FT_Matrix* matrix ); + + + +#ifdef __cplusplus + } +#endif + + +#endif /* FREETYPE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/ftbbox.h b/reactos/subsys/win32k/freetype/include/freetype/ftbbox.h new file mode 100644 index 00000000000..e1446647dfc --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/ftbbox.h @@ -0,0 +1,72 @@ +/***************************************************************************/ +/* */ +/* ftbbox.h */ +/* */ +/* FreeType bbox computation (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_GetBBox */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* outline :: A pointer to the source outline. */ + /* */ + /* */ + /* bbox :: The outline's exact bounding box. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + FT_EXPORT_DEF(FT_Error) FT_Raster_GetBBox( FT_Outline* outline, + FT_BBox* abbox ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTBBOX_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/fterrors.h b/reactos/subsys/win32k/freetype/include/freetype/fterrors.h new file mode 100644 index 00000000000..9fb8099b89b --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/fterrors.h @@ -0,0 +1,166 @@ +/***************************************************************************/ +/* */ +/* fterrors.h */ +/* */ +/* FreeType error codes (specification). */ +/* */ +/* Copyright 1996-2000 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 error enumeration constants */ + /* It can also be used to create an error message table easily with */ + /* something like: */ + /* */ + /* { */ + /* #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 */ + /* } */ + /* */ + /*************************************************************************/ + + +#ifndef FTERRORS_H +#define FTERRORS_H + + +#ifndef FT_ERRORDEF + +#define FT_ERRORDEF( e, v, s ) e = v, +#define FT_ERROR_START_LIST enum { +#define FT_ERROR_END_LIST FT_Err_Max }; + +#endif /* !FT_ERRORDEF */ + + +#ifdef FT_ERROR_START_LIST + FT_ERROR_START_LIST +#endif + + FT_ERRORDEF( FT_Err_Ok, 0x0000, \ + "no error" ) + FT_ERRORDEF( FT_Err_Cannot_Open_Resource, 0x0001, \ + "can't open stream" ) + FT_ERRORDEF( FT_Err_Unknown_File_Format, 0x0002, \ + "unknown file format" ) + FT_ERRORDEF( FT_Err_Invalid_File_Format, 0x0003, \ + "broken file" ) + + FT_ERRORDEF( FT_Err_Invalid_Argument, 0x0010, \ + "invalid argument" ) + FT_ERRORDEF( FT_Err_Invalid_Handle, 0x0011, \ + "invalid object handle" ) + FT_ERRORDEF( FT_Err_Invalid_Glyph_Index, 0x0012, \ + "invalid glyph index" ) + FT_ERRORDEF( FT_Err_Invalid_Character_Code, 0x0013, \ + "invalid character code" ) + + FT_ERRORDEF( FT_Err_Unimplemented_Feature, 0x0020, \ + "unimplemented feature" ) + FT_ERRORDEF( FT_Err_Invalid_Glyph_Format, 0x0021, \ + "unsupported glyph image format" ) + FT_ERRORDEF( FT_Err_Cannot_Render_Glyph, 0x0022, \ + "cannot render this glyph format" ) + + FT_ERRORDEF( FT_Err_Invalid_Library_Handle, 0x0030, \ + "invalid library handle" ) + FT_ERRORDEF( FT_Err_Invalid_Driver_Handle, 0x0031, \ + "invalid module handle" ) + FT_ERRORDEF( FT_Err_Invalid_Face_Handle, 0x0032, \ + "invalid face handle" ) + FT_ERRORDEF( FT_Err_Invalid_Size_Handle, 0x0033, \ + "invalid size handle" ) + FT_ERRORDEF( FT_Err_Invalid_Slot_Handle, 0x0034, \ + "invalid glyph slot handle" ) + FT_ERRORDEF( FT_Err_Invalid_CharMap_Handle, 0x0035, \ + "invalid charmap handle" ) + FT_ERRORDEF( FT_Err_Invalid_Outline, 0x0036, \ + "invalid outline" ) + FT_ERRORDEF( FT_Err_Invalid_Version, 0x0037, \ + "invalid FreeType version" ) + FT_ERRORDEF( FT_Err_Lower_Module_Version, 0x0038, \ + "module version is too low" ) + + FT_ERRORDEF( FT_Err_Too_Many_Drivers, 0x0040, \ + "too many modules" ) + FT_ERRORDEF( FT_Err_Too_Many_Extensions, 0x0041, \ + "too many extensions" ) + + FT_ERRORDEF( FT_Err_Out_Of_Memory, 0x0050, \ + "out of memory" ) + FT_ERRORDEF( FT_Err_Unlisted_Object, 0x0051, \ + "unlisted object" ) + + FT_ERRORDEF( FT_Err_Invalid_Stream_Handle, 0x0060, \ + "invalid stream handle" ) + FT_ERRORDEF( FT_Err_Cannot_Open_Stream, 0x0061, \ + "cannot open stream" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Seek, 0x0062, \ + "invalid stream seek" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Skip, 0x0063, \ + "invalid stream skip" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Read, 0x0064, \ + "invalid stream read" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Operation, 0x0065, \ + "invalid stream operation" ) + FT_ERRORDEF( FT_Err_Invalid_Frame_Operation, 0x0066, \ + "invalid frame operation" ) + FT_ERRORDEF( FT_Err_Nested_Frame_Access, 0x0067, \ + "nested frame access" ) + FT_ERRORDEF( FT_Err_Invalid_Frame_Read, 0x0068, \ + "invalid frame read" ) + + FT_ERRORDEF( FT_Err_Invalid_Composite, 0x0070, \ + "invalid composite glyph" ) + FT_ERRORDEF( FT_Err_Too_Many_Hints, 0x0071, \ + "too many hints" ) + + FT_ERRORDEF( FT_Err_Raster_Uninitialized, 0x0080, \ + "raster uninitialized" ) + FT_ERRORDEF( FT_Err_Raster_Corrupted, 0x0081, \ + "raster corrupted" ) + FT_ERRORDEF( FT_Err_Raster_Overflow, 0x0082, \ + "raster overflow" ) + FT_ERRORDEF( FT_Err_Raster_Negative_Height, 0x0083, \ + "negative height while rastering" ) + + /* range 0x400 - 0x4FF is reserved for TrueType specific stuff */ + + /* range 0x500 - 0x5FF is reserved for CFF specific stuff */ + + /* range 0x600 - 0x6FF is reserved for Type1 specific stuff */ + +#ifdef FT_ERROR_END_LIST + FT_ERROR_END_LIST +#endif + + +#undef FT_ERROR_START_LIST +#undef FT_ERROR_END_LIST +#undef FT_ERRORDEF + + +#endif /* FTERRORS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/ftglyph.h b/reactos/subsys/win32k/freetype/include/freetype/ftglyph.h new file mode 100644 index 00000000000..0647c883eb9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/ftglyph.h @@ -0,0 +1,422 @@ +/***************************************************************************/ +/* */ +/* ftglyph.h */ +/* */ +/* FreeType convenience functions to handle glyphs (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef __cplusplus + extern "C" { +#endif + + /* forward declaration to a private type */ + typedef struct FT_Glyph_Class_ FT_Glyph_Class; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_GlyphRec */ + /* */ + /* */ + /* The root glyph structure contains a given glyph image plus its */ + /* advance width in 16.16 fixed float format. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_BitmapGlyphRec */ + /* */ + /* */ + /* A structure used for bitmap glyph images. This really is a */ + /* `sub-class' of `FT_GlyphRec'. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_OutlineGlyphRec */ + /* */ + /* */ + /* A structure used for outline (vectorial) glyph images. This */ + /* really is a `sub-class' of `FT_GlyphRec'. */ + /* */ + /* */ + /* root :: The root FT_Glyph fields. */ + /* */ + /* outline :: A descriptor for the outline. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph */ + /* */ + /* */ + /* A function used to extract a glyph image from a slot. */ + /* */ + /* */ + /* slot :: A handle to the source glyph slot. */ + /* */ + /* */ + /* aglyph :: A handle to the glyph object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Get_Glyph( FT_GlyphSlot slot, + FT_Glyph* aglyph ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Copy */ + /* */ + /* */ + /* A function used to copy a glyph image. */ + /* */ + /* */ + /* source :: A handle to the source glyph object. */ + /* */ + /* */ + /* target :: A handle to the target glyph object. 0 in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Glyph_Copy( FT_Glyph source, + FT_Glyph* target ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Transform */ + /* */ + /* */ + /* Transforms a glyph image if its format is scalable. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code (the glyph format is not scalable if it is */ + /* not zero). */ + /* */ + /* */ + /* The 2x2 transformation matrix is also applied to the glyph's */ + /* advance vector. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Glyph_Transform( FT_Glyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ); + + + enum + { + ft_glyph_bbox_pixels = 0, + ft_glyph_bbox_subpixels = 1, + ft_glyph_bbox_gridfit = 2 + }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Get_CBox */ + /* */ + /* */ + /* Returns the glyph image's bounding box. */ + /* */ + /* */ + /* glyph :: A handle to the source glyph object. */ + /* */ + /* mode :: A set of bit flags that indicate how to interpret the */ + /* returned bounding box values. */ + /* */ + /* */ + /* box :: The glyph bounding box. Coordinates are expressed in */ + /* 1/64th of pixels if it is grid-fitted. */ + /* */ + /* */ + /* Coordinates are relative to the glyph origin, using the Y-upwards */ + /* convention. */ + /* */ + /* If `ft_glyph_bbox_subpixels' is set in `mode', the bbox */ + /* coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels). */ + /* Otherwise, coordinates are expressed in integer 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 the */ + /* `ft_glyph_bbox_gridfit' flag is set in `mode;, 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); */ + /* */ + /* The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'. */ + /* */ + FT_EXPORT_DEF( void ) FT_Glyph_Get_CBox( FT_Glyph glyph, + FT_UInt bbox_mode, + FT_BBox* cbox ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_To_Bitmap */ + /* */ + /* */ + /* Converts a given glyph object to a bitmap glyph object. */ + /* */ + /* */ + /* glyph :: A pointer to a handle to the target glyph. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, + FT_ULong render_mode, + FT_Vector* origin, + FT_Bool destroy ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Glyph */ + /* */ + /* */ + /* Destroys a given glyph. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + FT_EXPORT_DEF( void ) FT_Done_Glyph( FT_Glyph glyph ); + + + /* other helpful functions */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Multiply */ + /* */ + /* */ + /* Performs the matrix operation `b = a*b'. */ + /* */ + /* */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `a' or `b' is zero. */ + /* */ + FT_EXPORT_DEF( void ) FT_Matrix_Multiply( FT_Matrix* a, + FT_Matrix* b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Invert */ + /* */ + /* */ + /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */ + /* */ + /* */ + /* matrix :: A pointer to the target matrix. Remains untouched in */ + /* case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Matrix_Invert( FT_Matrix* matrix ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTGLYPH_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/ftimage.h b/reactos/subsys/win32k/freetype/include/freetype/ftimage.h new file mode 100644 index 00000000000..4dd1c3d213f --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/ftimage.h @@ -0,0 +1,1003 @@ +/***************************************************************************/ +/* */ +/* ftimage.h */ +/* */ +/* FreeType glyph image formats and default raster interface */ +/* (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Pos */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector */ + /* */ + /* */ + /* A simple structure used to store a 2D vector; coordinates are of */ + /* the FT_Pos type. */ + /* */ + /* */ + /* x :: The horizontal coordinate. */ + /* y :: The vertical coordinate. */ + /* */ + typedef struct FT_Vector_ + { + FT_Pos x; + FT_Pos y; + + } FT_Vector; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Pixel_Mode */ + /* */ + /* */ + /* An enumeration type used to describe the format of pixels in a */ + /* given bitmap. Note that additional formats may be added in the */ + /* future. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Palette_Mode */ + /* */ + /* */ + /* An enumeration type used to describe the format of a bitmap */ + /* palette, used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Bitmap */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline */ + /* */ + /* */ + /* This structure is used to describe an outline to the scan-line */ + /* converter. */ + /* */ + /* */ + /* 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 */ + /* 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 unset. */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Flags */ + /* */ + /* */ + /* A simple type used to enumerates the flags in an outline's */ + /* `outline_flags' field. */ + /* */ + /* */ + /* 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 ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_MoveTo_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_MoveTo_Func)( FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_LineTo_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_LineTo_Func)( FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_ConicTo_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_ConicTo_Func)( FT_Vector* control, + FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_CubicTo_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_CubicTo_Func)( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Funcs */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_IMAGE_TAG */ + /* */ + /* */ + /* This macro converts four letter tags into an unsigned long. */ + /* */ +#define FT_IMAGE_TAG( _x1, _x2, _x3, _x4 ) \ + ( ( (unsigned long)_x1 << 24 ) | \ + ( (unsigned long)_x2 << 16 ) | \ + ( (unsigned long)_x3 << 8 ) | \ + (unsigned long)_x4 ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Format */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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_glyph_format_none = 0, + ft_glyph_format_composite = FT_IMAGE_TAG( 'c', 'o', 'm', 'p' ), + ft_glyph_format_bitmap = FT_IMAGE_TAG( 'b', 'i', 't', 's' ), + ft_glyph_format_outline = FT_IMAGE_TAG( 'o', 'u', 't', 'l' ), + ft_glyph_format_plotter = FT_IMAGE_TAG( '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. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Span */ + /* */ + /* */ + /* A structure used to model a single span of gray (or black) pixels */ + /* when rendering a monochrome or anti-aliased bitmap. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Span_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_BitTest_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* y :: The pixel's y-coordinate. */ + /* */ + /* x :: The pixel's x-coordinate. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* */ + /* 1 if the pixel is `set', 0 otherwise. */ + /* */ + typedef int (*FT_Raster_BitTest_Func)( int y, + int x, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_BitSet_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* y :: The pixel's y-coordinate. */ + /* */ + /* x :: The pixel's x-coordinate. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* */ + /* 1 if the pixel is `set', 0 otherwise. */ + /* */ + typedef void (*FT_Raster_BitSet_Func)( int y, + int x, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Flag */ + /* */ + /* */ + /* An enumeration to list the bit flags as used in the `flags' field */ + /* of a FT_Raster_Params structure. */ + /* */ + /* */ + /* ft_raster_flag_default :: This value is 0. */ + /* */ + /* ft_raster_flag_aa :: Requests the rendering of an */ + /* anti-aliased glyph bitmap. If unset, a */ + /* monchrome bitmap will be rendered. */ + /* */ + /* ft_raster_flag_direct :: Requests direct rendering over the */ + /* target bitmap. Direct rendering uses */ + /* user-provided callbacks in order to */ + /* perform direct drawing or composition */ + /* over an existing bitmap. If this bit is */ + /* unset, the content of the target bitmap */ + /* *must be zeroed*! */ + /* */ + typedef enum + { + ft_raster_flag_default = 0, + ft_raster_flag_aa = 1, + ft_raster_flag_direct = 2 + + } FT_Raster_Flag; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Params */ + /* */ + /* */ + /* A structure to hold the arguments used by a raster's render */ + /* function. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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_Raster_Params; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_New_Func */ + /* */ + /* */ + /* A function used to create a new raster object. */ + /* */ + /* */ + /* memory :: A handle to the memory allocator. */ + /* */ + /* */ + /* raster :: A handle to the new raster object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Done_Func */ + /* */ + /* */ + /* A function used to destroy a given raster object. */ + /* */ + /* */ + /* raster :: A handle to the raster object. */ + /* */ + typedef void (*FT_Raster_Done_Func)( FT_Raster raster ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Reset_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Set_Mode_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Render_Func */ + /* */ + /* */ + /* Invokes a given raster to scan-convert a given glyph image into a */ + /* target bitmap. */ + /* */ + /* */ + /* raster :: A handle to the raster object. */ + /* */ + /* params :: A pointer to a FT_Raster_Params structure used to store */ + /* the rendering parameters. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Funcs */ + /* */ + /* */ + /* A structure used to describe a given raster class to the library. */ + /* */ + /* */ + /* 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; + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTIMAGE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/ftmm.h b/reactos/subsys/win32k/freetype/include/freetype/ftmm.h new file mode 100644 index 00000000000..db5db0464ca --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/ftmm.h @@ -0,0 +1,175 @@ +/***************************************************************************/ +/* */ +/* ftmm.h */ +/* */ +/* FreeType Multiple Master font interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MM_Axis */ + /* */ + /* */ + /* A simple structure used to model a given axis in design space for */ + /* Multiple Masters fonts. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Multi_Master */ + /* */ + /* */ + /* A structure used to model the axes and space of a Multiple Masters */ + /* font. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Multi_Master */ + /* */ + /* */ + /* Retrieves the Multiple Master descriptor of a given font. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* */ + /* master :: The Multiple Masters descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master* master ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Design_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through design coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_MM_Design_Coordinates( + FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Blend_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through normalized blend coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates (each one must be between 0 */ + /* and 1.0). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_MM_Blend_Coordinates( + FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTMM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/ftmodule.h b/reactos/subsys/win32k/freetype/include/freetype/ftmodule.h new file mode 100644 index 00000000000..3c09aa2afd0 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/ftmodule.h @@ -0,0 +1,274 @@ +/***************************************************************************/ +/* */ +/* ftmodule.h */ +/* */ +/* FreeType modules public interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Module_Class */ + /* */ + /* */ + /* The module class descriptor. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Module */ + /* */ + /* */ + /* Adds a new module to a given library instance. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* clazz :: A pointer to class descriptor for the module. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Add_Module( FT_Library library, + const FT_Module_Class* clazz ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module */ + /* */ + /* */ + /* Finds a module by its name. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module handle. 0 if none was found. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for :-) */ + /* */ + FT_EXPORT_DEF( FT_Module ) FT_Get_Module( FT_Library library, + const char* module_name ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Remove_Module */ + /* */ + /* */ + /* Removes a given module from a library instance. */ + /* */ + /* */ + /* library :: A handle to a library object. */ + /* */ + /* module :: A handle to a module object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The module object is destroyed by the function in case of success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Remove_Module( FT_Library library, + FT_Module module ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Library */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* memory :: A handle to the original memory object. */ + /* */ + /* */ + /* alibrary :: A pointer to handle of a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_New_Library( FT_Memory memory, + FT_Library* library ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Library */ + /* */ + /* */ + /* Discards a given library object. This closes all drivers and */ + /* discards all resource objects. */ + /* */ + /* */ + /* library :: A handle to the target library. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Done_Library( FT_Library library ); + + + + typedef void (*FT_DebugHook_Func)( void* arg ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Debug_Hook */ + /* */ + /* */ + /* Sets a debug hook function for debugging the interpreter of a font */ + /* format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* 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. */ + /* */ + /* */ + /* Currently, four debug hook slots are available, but only two (for */ + /* the TrueType and the Type 1 interpreter) are defined. */ + /* */ + FT_EXPORT_DEF( void ) FT_Set_Debug_Hook( FT_Library library, + FT_UInt hook_index, + FT_DebugHook_Func debug_hook ); + + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Default_Modules */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + FT_EXPORT_DEF( void ) FT_Add_Default_Modules( FT_Library library ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTMODULE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/ftnames.h b/reactos/subsys/win32k/freetype/include/freetype/ftnames.h new file mode 100644 index 00000000000..2969214b9b6 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/ftnames.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ftnames.h */ +/* */ +/* Simple interface to access SFNT name tables (which are used */ +/* to hold font names, copyright info, notices, etc.). */ +/* */ +/* This is _not_ used to retrieve glyph names! */ +/* */ +/* Copyright 1996-2000 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 FTNAMES_H +#define FTNAMES_H + + +#include + + + typedef struct FT_SfntName_ + { + FT_UShort platform_id; + FT_UShort encoding_id; + FT_UShort language_id; + FT_UShort name_id; + + FT_Byte* string; + FT_UInt string_len; /* in bytes */ + + } FT_SfntName; + + + FT_EXPORT_DEF( FT_UInt ) FT_Get_Sfnt_Name_Count( FT_Face face ); + + FT_EXPORT_DEF( FT_Error ) FT_Get_Sfnt_Name( FT_Face face, + FT_UInt index, + FT_SfntName* aname ); + + +#endif /* FTNAMES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/ftoutln.h b/reactos/subsys/win32k/freetype/include/freetype/ftoutln.h new file mode 100644 index 00000000000..1e448bd0ecc --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/ftoutln.h @@ -0,0 +1,344 @@ +/***************************************************************************/ +/* */ +/* ftoutln.h */ +/* */ +/* Support for the FT_Outline type used to store glyph shapes of */ +/* most scalable font formats (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Decompose */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means sucess. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Decompose( + FT_Outline* outline, + FT_Outline_Funcs* interface, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_New */ + /* */ + /* */ + /* Creates a new outline of a given size. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* outline :: A handle to the new outline. NULL in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* The reason why this function takes a `library' parameter is simply */ + /* to use the library's memory allocator. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_New( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ); + + + FT_EXPORT_DEF( FT_Error ) FT_Outline_New_Internal( + FT_Memory memory, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Done */ + /* */ + /* */ + /* Destroys an outline created with FT_Outline_New(). */ + /* */ + /* */ + /* library :: A handle of the library object used to allocate the */ + /* outline. */ + /* */ + /* outline :: A pointer to the outline object to be discarded. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* If the outline's `owner' field is not set, only the outline */ + /* descriptor will be released. */ + /* */ + /* The reason why this function takes an `outline' parameter is */ + /* simply to use FT_Free(). */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Done( FT_Library library, + FT_Outline* outline ); + + + FT_EXPORT_DEF( FT_Error ) FT_Outline_Done_Internal( FT_Memory memory, + FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_CBox */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* */ + /* cbox :: The outline's control box. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Get_CBox( FT_Outline* outline, + FT_BBox* cbox ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Translate */ + /* */ + /* */ + /* Applies a simple translation to the points of an outline. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* xOffset :: The horizontal offset. */ + /* */ + /* yOffset :: The vertical offset. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Translate( FT_Outline* outline, + FT_Pos xOffset, + FT_Pos yOffset ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Copy */ + /* */ + /* */ + /* Copies an outline into another one. Both objects must have the */ + /* same sizes (number of points & number of contours) when this */ + /* function is called. */ + /* */ + /* */ + /* source :: A handle to the source outline. */ + /* */ + /* */ + /* target :: A handle to the target outline. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Copy( FT_Outline* source, + FT_Outline* target ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector_Transform */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* vector :: The target vector to transform. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Transform( FT_Outline* outline, + FT_Matrix* matrix ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Reverse */ + /* */ + /* */ + /* Reverses the drawing direction of an outline. This is used to */ + /* ensure consistent fill conventions for mirrored glyphs. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* */ + /* 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_DEF( void ) FT_Outline_Reverse( FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_Bitmap */ + /* */ + /* */ + /* Renders an outline within a bitmap. The outline's image is simply */ + /* OR-ed to the target bitmap. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* map :: A pointer to the target bitmap descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap* bitmap ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Render */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* params :: A pointer to a FT_Raster_Params structure used to */ + /* describe the rendering operation. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* 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_DEF( FT_Error ) FT_Outline_Render( FT_Library library, + FT_Outline* outline, + FT_Raster_Params* params ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTOUTLN_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/ftrender.h b/reactos/subsys/win32k/freetype/include/freetype/ftrender.h new file mode 100644 index 00000000000..fe5acd2ce6d --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/ftrender.h @@ -0,0 +1,191 @@ +/***************************************************************************/ +/* */ +/* ftrender.h */ +/* */ +/* FreeType renderer modules public interface (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Renderer_Class */ + /* */ + /* */ + /* The renderer module class descriptor. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Renderer */ + /* */ + /* */ + /* Retrieves the current renderer for a given glyph format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* format :: The glyph format. */ + /* */ + /* */ + /* A renderer handle. 0 if none found. */ + /* */ + /* */ + /* 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_DEF( FT_Renderer ) FT_Get_Renderer( FT_Library library, + FT_Glyph_Format format ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Renderer */ + /* */ + /* */ + /* Sets the current renderer to use, and set additional mode. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* renderer :: A handle to the renderer object. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* parameters :: Additional parameters. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_DEF(FT_Error) FT_Set_Renderer( FT_Library library, + FT_Renderer renderer, + FT_UInt num_params, + FT_Parameter* parameters ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTRENDER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/ftsystem.h b/reactos/subsys/win32k/freetype/include/freetype/ftsystem.h new file mode 100644 index 00000000000..bc74bced225 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/ftsystem.h @@ -0,0 +1,101 @@ +/***************************************************************************/ +/* */ +/* ftsystem.h */ +/* */ +/* FreeType low-level system interface definition (specification). */ +/* */ +/* Copyright 1996-2000 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 + + + /*************************************************************************/ + /* */ + /* M E M O R Y M A N A G E M E N T */ + /* */ + /*************************************************************************/ + + + typedef struct FT_MemoryRec_* FT_Memory; + + + typedef void* (*FT_Alloc_Func)( FT_Memory memory, + long size ); + + typedef void (*FT_Free_Func)( FT_Memory memory, + void* block ); + + typedef void* (*FT_Realloc_Func)( FT_Memory memory, + long cur_size, + long new_size, + void* block ); + + + 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 */ + /* */ + /*************************************************************************/ + + + typedef union FT_StreamDesc_ + { + long value; + void* pointer; + + } FT_StreamDesc; + + + typedef struct FT_StreamRec_* FT_Stream; + + + typedef unsigned long (*FT_Stream_IO)( FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count ); + + typedef void (*FT_Stream_Close)( FT_Stream stream ); + + + struct FT_StreamRec_ + { + unsigned char* base; + unsigned long size; + unsigned long pos; + + FT_StreamDesc descriptor; + FT_StreamDesc pathname; /* ignored by FreeType -- */ + /* useful for debugging */ + FT_Stream_IO read; + FT_Stream_Close close; + + FT_Memory memory; + unsigned char* cursor; + unsigned char* limit; + }; + + +#endif /* FTSYSTEM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/fttypes.h b/reactos/subsys/win32k/freetype/include/freetype/fttypes.h new file mode 100644 index 00000000000..ec909061de9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/fttypes.h @@ -0,0 +1,400 @@ +/***************************************************************************/ +/* */ +/* fttypes.h */ +/* */ +/* FreeType simple types definitions (specification only). */ +/* */ +/* Copyright 1996-2000 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 +#include + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Bool */ + /* */ + /* */ + /* A typedef of unsigned char, used for simple booleans. */ + /* */ + typedef unsigned char FT_Bool; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FWord */ + /* */ + /* */ + /* A signed 16-bit integer used to store a distance in original font */ + /* units. */ + /* */ + typedef signed short FT_FWord; /* distance in FUnits */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UFWord */ + /* */ + /* */ + /* An unsigned 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + typedef unsigned short FT_UFWord; /* unsigned distance */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Char */ + /* */ + /* */ + /* A simple typedef for the _signed_ char type. */ + /* */ + typedef signed char FT_Char; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Byte */ + /* */ + /* */ + /* A simple typedef for the _unsigned_ char type. */ + /* */ + typedef unsigned char FT_Byte; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_String */ + /* */ + /* */ + /* A simple typedef for the char type, usually used for strings. */ + /* */ + typedef char FT_String; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Short */ + /* */ + /* */ + /* A typedef for signed short. */ + /* */ + typedef signed short FT_Short; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UShort */ + /* */ + /* */ + /* A typedef for unsigned short. */ + /* */ + typedef unsigned short FT_UShort; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Int */ + /* */ + /* */ + /* A typedef for the int type. */ + /* */ + typedef int FT_Int; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UInt */ + /* */ + /* */ + /* A typedef for the unsigned int type. */ + /* */ + typedef unsigned int FT_UInt; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Long */ + /* */ + /* */ + /* A typedef for signed long. */ + /* */ + typedef signed long FT_Long; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ULong */ + /* */ + /* */ + /* A typedef for unsigned long. */ + /* */ + typedef unsigned long FT_ULong; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_F2Dot14 */ + /* */ + /* */ + /* A signed 2.14 fixed float type used for unit vectors. */ + /* */ + typedef signed short FT_F2Dot14; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_F26Dot6 */ + /* */ + /* */ + /* A signed 26.6 fixed float type used for vectorial pixel */ + /* coordinates. */ + /* */ + typedef signed long FT_F26Dot6; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Fixed */ + /* */ + /* */ + /* This type is used to store 16.16 fixed float values, like scales */ + /* or matrix coefficients. */ + /* */ + typedef signed long FT_Fixed; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Error */ + /* */ + /* */ + /* The FreeType error code type. A value of 0 is always interpreted */ + /* as a successful operation. */ + /* */ + typedef int FT_Error; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Pointer */ + /* */ + /* */ + /* A simple typedef for a typeless pointer. */ + /* */ + typedef void* FT_Pointer; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UnitVector */ + /* */ + /* */ + /* A simple structure used to store a 2D vector unit vector. Uses */ + /* FT_F2Dot14 types. */ + /* */ + /* */ + /* x :: Horizontal coordinate. */ + /* */ + /* y :: Vertical coordinate. */ + /* */ + typedef struct FT_UnitVector_ + { + FT_F2Dot14 x; + FT_F2Dot14 y; + + } FT_UnitVector; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix */ + /* */ + /* */ + /* 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 */ + /* } */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_BBox */ + /* */ + /* */ + /* A structure used to hold an outline's bounding box, i.e., the */ + /* coordinates of its extrema in the horizontal and vertical */ + /* directions. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MAKE_TAG */ + /* */ + /* */ + /* 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 */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ListNode */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List */ + /* */ + /* */ + /* A handle to a list record (see FT_ListRec). */ + /* */ + typedef struct FT_ListRec_* FT_List; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ListNodeRec */ + /* */ + /* */ + /* A structure used to hold a single list element. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ListRec */ + /* */ + /* */ + /* A structure used to hold a simple doubly-linked list. These are */ + /* used in many parts of FreeType. */ + /* */ + /* */ + /* 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 ) + + +#endif /* FTTYPES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/autohint.h b/reactos/subsys/win32k/freetype/include/freetype/internal/autohint.h new file mode 100644 index 00000000000..5d35a5dcd46 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/autohint.h @@ -0,0 +1,195 @@ +/***************************************************************************/ +/* */ +/* autohint.h */ +/* */ +/* High-level `autohint' module-specific interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + + typedef struct FT_AutoHinterRec_ *FT_AutoHinter; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Get_Global_Func */ + /* */ + /* */ + /* 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(). */ + /* */ + /* */ + /* hinter :: A handle to the source auto-hinter. */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Done_Global_Func */ + /* */ + /* */ + /* Discards the global hints retrieved through */ + /* FT_AutoHinter_Get_Global_Func(). This is the only way these hints */ + /* are freed from memory. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Reset_Func */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Load_Func */ + /* */ + /* */ + /* This function is used to load, scale, and automatically hint a */ + /* glyph from a given face. */ + /* */ + /* */ + /* face :: A handle to the face. */ + /* glyph_index :: The glyph index. */ + /* load_flags :: The load flags. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Interface */ + /* */ + /* */ + /* 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; + + +#endif /* AUTOHINT_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/ftcalc.h b/reactos/subsys/win32k/freetype/include/freetype/internal/ftcalc.h new file mode 100644 index 00000000000..99b6cfaf641 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/ftcalc.h @@ -0,0 +1,123 @@ +/***************************************************************************/ +/* */ +/* ftcalc.h */ +/* */ +/* Arithmetic computations (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include /* for LONG64 */ + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef LONG64 + + + typedef 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) ) + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_64( z ) FT_Sqrt64( z ) + + FT_EXPORT_DEF( FT_Int32 ) FT_Sqrt64( FT_Int64 l ); + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + +#else /* 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 ) + + + FT_EXPORT_DEF( void ) FT_Add64( FT_Int64* x, + FT_Int64* y, + FT_Int64* z ); + + FT_EXPORT_DEF( void ) FT_MulTo64( FT_Int32 x, + FT_Int32 y, + FT_Int64* z ); + + FT_EXPORT_DEF( FT_Int32 ) FT_Div64by32( FT_Int64* x, + FT_Int32 y ); + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_64( z ) FT_Sqrt64( &z ) + + FT_EXPORT_DEF( FT_Int32 ) FT_Sqrt64( FT_Int64* x ); + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + +#endif /* LONG64 */ + + +#ifndef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_32( x ) FT_Sqrt32( x ) + + BASE_DEF( 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 ) ) ) + + +#ifdef __cplusplus + } +#endif + +#endif /* FTCALC_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/ftdebug.h b/reactos/subsys/win32k/freetype/include/freetype/internal/ftdebug.h new file mode 100644 index 00000000000..8b1e4dd5a57 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/ftdebug.h @@ -0,0 +1,225 @@ +/***************************************************************************/ +/* */ +/* ftdebug.h */ +/* */ +/* Debugging and logging component (specification). */ +/* */ +/* Copyright 1996-2000 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 /* for FT_DEBUG_LEVEL_TRACE, */ + /* FT_DEBUG_LEVEL_ERROR */ + +#ifdef __cplusplus + extern "C" { +#endif + + + /* A very stupid pre-processor trick. See K&R version 2 */ + /* section A12.3 for details... */ + /* */ + /* It is also described in the section `Separate */ + /* Expansion of Macro Arguments' in the info file */ + /* `cpp.info', describing GNU cpp. */ + /* */ +#define FT_CAT( x, y ) x ## y +#define FT_XCAT( x, y ) FT_CAT( x, y ) + + +#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) */ + + /* 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, + + /* experimental Type 1 driver components */ + trace_z1driver, + trace_z1gload, + trace_z1hint, + trace_z1load, + trace_z1objs, + trace_z1parse, + + /* Type 2 driver components */ + trace_t2driver, + trace_t2gload, + trace_t2load, + trace_t2objs, + trace_t2parse, + + /* CID driver components */ + trace_cidafm, + trace_ciddriver, + trace_cidgload, + trace_cidload, + trace_cidobjs, + trace_cidparse, + + /* Windows fonts component */ + trace_winfnt, + + /* 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_XCAT( FT_Message, varformat ); \ + } while ( 0 ) + + + FT_EXPORT_DEF( 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_DEF( void ) FT_Message( const char* fmt, ... ); + + /* print a message and exit */ + FT_EXPORT_DEF( void ) FT_Panic( const char* fmt, ... ); + +#define FT_ERROR( varformat ) FT_XCAT( 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 ) + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTDEBUG_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/ftdriver.h b/reactos/subsys/win32k/freetype/include/freetype/internal/ftdriver.h new file mode 100644 index 00000000000..592de498c1f --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/ftdriver.h @@ -0,0 +1,182 @@ +/***************************************************************************/ +/* */ +/* ftdriver.h */ +/* */ +/* FreeType font driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include + + + 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Driver_Class */ + /* */ + /* */ + /* The font driver class. This structure mostly contains pointers to */ + /* driver methods. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + +#endif /* FTDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/ftextend.h b/reactos/subsys/win32k/freetype/include/freetype/internal/ftextend.h new file mode 100644 index 00000000000..fdd2c6ef245 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/ftextend.h @@ -0,0 +1,178 @@ +/***************************************************************************/ +/* */ +/* ftextend.h */ +/* */ +/* FreeType extensions implementation (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* The extensions don't need to be integrated at compile time into the */ + /* engine, only at link time. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Extension_Initializer */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* ext :: A typeless pointer to the extension data. */ + /* */ + /* face :: A handle to the source face object the extension is */ + /* associated with. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Extension_Finalizer */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Extension_Class */ + /* */ + /* */ + /* 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(). */ + /* */ + /* */ + /* 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; + + + FT_EXPORT_DEF( FT_Error ) FT_Register_Extension( + FT_Driver driver, + FT_Extension_Class* clazz ); + + +#ifdef FT_CONFIG_OPTION_EXTEND_ENGINE + + + /* Initialize the extension component */ + LOCAL_DEF + FT_Error FT_Init_Extensions( FT_Library library ); + + /* Finalize the extension component */ + LOCAL_DEF + FT_Error FT_Done_Extensions( FT_Library library ); + + /* Create an extension within a face object. Called by the */ + /* face object constructor. */ + LOCAL_DEF + FT_Error FT_Create_Extensions( FT_Face face ); + + /* Destroy all extensions within a face object. Called by the */ + /* face object destructor. */ + LOCAL_DEF + FT_Error FT_Destroy_Extensions( FT_Face face ); + + +#endif + + + /* return an extension's data & interface according to its ID */ + FT_EXPORT_DEF( void* ) FT_Get_Extension( + FT_Face face, + const char* extension_id, + void** extension_interface ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTEXTEND_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/ftlist.h b/reactos/subsys/win32k/freetype/include/freetype/internal/ftlist.h new file mode 100644 index 00000000000..7c6d8ed3b3d --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/ftlist.h @@ -0,0 +1,113 @@ +/***************************************************************************/ +/* */ +/* ftlist.c */ +/* */ +/* Generic list support for FreeType (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef __cplusplus + extern "C" { +#endif + + + FT_EXPORT_DEF( FT_ListNode ) FT_List_Find( FT_List list, + void* data ); + + FT_EXPORT_DEF( void ) FT_List_Add( FT_List list, + FT_ListNode node ); + + FT_EXPORT_DEF( void ) FT_List_Insert( FT_List list, + FT_ListNode node ); + + FT_EXPORT_DEF( void ) FT_List_Remove( FT_List list, + FT_ListNode node ); + + FT_EXPORT_DEF( void ) FT_List_Up( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Iterator */ + /* */ + /* */ + /* An FT_List iterator function which is called during a list parse */ + /* by FT_List_Iterate(). */ + /* */ + /* */ + /* 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 ); + + + FT_EXPORT_DEF( FT_Error ) FT_List_Iterate( FT_List list, + FT_List_Iterator iterator, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Destructor */ + /* */ + /* */ + /* An FT_List iterator function which is called during a list */ + /* finalization by FT_List_Finalize() to destroy all elements in a */ + /* given list. */ + /* */ + /* */ + /* 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 ); + + + FT_EXPORT_DEF( void ) FT_List_Finalize( FT_List list, + FT_List_Destructor destroy, + FT_Memory memory, + void* user ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTLIST_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/ftmemory.h b/reactos/subsys/win32k/freetype/include/freetype/internal/ftmemory.h new file mode 100644 index 00000000000..da8d3a41260 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/ftmemory.h @@ -0,0 +1,127 @@ +/***************************************************************************/ +/* */ +/* ftmemory.h */ +/* */ +/* The FreeType memory management macros (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include + + + /*************************************************************************/ + /* */ + /* */ + /* FT_SET_ERROR */ + /* */ + /* */ + /* 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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + BASE_DEF( FT_Error ) FT_Alloc( FT_Memory memory, + FT_Long size, + void** P ); + + BASE_DEF( FT_Error ) FT_Realloc( FT_Memory memory, + FT_Long current, + FT_Long size, + void** P ); + + BASE_DEF( 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 + +#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_) ) + + +#endif /* FTMEMORY_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/ftobjs.h b/reactos/subsys/win32k/freetype/include/freetype/internal/ftobjs.h new file mode 100644 index 00000000000..0d0f5d80ac8 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/ftobjs.h @@ -0,0 +1,532 @@ +/***************************************************************************/ +/* */ +/* ftobjs.h */ +/* */ +/* The FreeType private base classes (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M O D U L E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ModuleRec */ + /* */ + /* */ + /* A module object instance. */ + /* */ + /* */ + /* 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 ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module_Interface */ + /* */ + /* */ + /* Finds a module and returns its specific interface as a typeless */ + /* pointer. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module-specific interface if available, 0 otherwise. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for, and what its interface is :-) */ + /* */ + BASE_DEF( 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 + + + /* this must be kept exported -- tt will be used later in our own */ + /* high-level caching font manager called SemTex (way after the */ + /* 2.0 release though */ + FT_EXPORT_DEF( FT_Error ) FT_New_Size( FT_Face face, + FT_Size* size ); + + FT_EXPORT_DEF( FT_Error ) FT_Done_Size( FT_Size size ); + + + FT_EXPORT_DEF( FT_Error ) FT_New_GlyphSlot( FT_Face face, + FT_GlyphSlot* aslot ); + + FT_EXPORT_DEF( 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? */ + + }; + + + BASE_DEF( FT_Error ) FT_GlyphLoader_New( FT_Memory memory, + FT_GlyphLoader** aloader ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Create_Extra( + FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Done( FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Reset( FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Check_Points( + FT_GlyphLoader* loader, + FT_UInt n_points, + FT_UInt n_contours ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Check_Subglyphs( + FT_GlyphLoader* loader, + FT_UInt n_subs ); + + BASE_DEF( void ) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Add( FT_GlyphLoader* loader ); + + BASE_DEF( 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; + const 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DriverRec */ + /* */ + /* */ + /* The root font driver class. A font driver is responsible for */ + /* managing and loading font files of a given format. */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LibraryRec */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + BASE_DEF( FT_Renderer ) FT_Lookup_Renderer( FT_Library library, + FT_Glyph_Format format, + FT_ListNode* node ); + + BASE_DEF( FT_Error ) FT_Render_Glyph_Internal( FT_Library library, + FT_GlyphSlot slot, + FT_UInt render_mode ); + + typedef FT_Error (*FT_Glyph_Name_Requester)( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + +#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + + FT_EXPORT_DEF( FT_Error ) FT_New_Stream( const char* filepathname, + FT_Stream astream ); + + FT_EXPORT_DEF( void ) FT_Done_Stream( FT_Stream stream ); + + FT_EXPORT_DEF( FT_Memory ) FT_New_Memory( void ); + + +#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 + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTOBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/ftstream.h b/reactos/subsys/win32k/freetype/include/freetype/internal/ftstream.h new file mode 100644 index 00000000000..365f479a8af --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/ftstream.h @@ -0,0 +1,361 @@ +/***************************************************************************/ +/* */ +/* ftstream.h */ +/* */ +/* Stream handling(specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* 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_ulong_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 1 ), + ft_frame_long_be = 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_uoff3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 1 ), + ft_frame_off3_be = 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_Frame_Op value; + char size; + FT_UShort offset; + + } FT_Frame_Field; + + + /* make-up a FT_Frame_Field out of a structure type and a field name */ +#define FT_FIELD_REF( s, f ) (((s*)0)->f) + +#define FT_FRAME_FIELD( frame_op, struct_type, field ) \ + { \ + frame_op, \ + sizeof ( FT_FIELD_REF( struct_type,field ) ), \ + (FT_UShort)(char*)&FT_FIELD_REF( struct_type, field ) \ + } + +#define FT_MAKE_EMPTY_FIELD( frame_op ) { frame_op, 0, 0 } + +#define FT_FRAME_START( s ) { ft_frame_start, 0, s } +#define FT_FRAME_END { ft_frame_end, 0, 0 } + +#define FT_FRAME_LONG( s, f ) FT_FRAME_FIELD( ft_frame_long_be, s, f ) +#define FT_FRAME_ULONG( s, f ) FT_FRAME_FIELD( ft_frame_ulong_be, s, f ) +#define FT_FRAME_SHORT( s, f ) FT_FRAME_FIELD( ft_frame_short_be, s, f ) +#define FT_FRAME_USHORT( s, f ) FT_FRAME_FIELD( ft_frame_ushort_be, s, f ) +#define FT_FRAME_BYTE( s, f ) FT_FRAME_FIELD( ft_frame_byte, s, f ) +#define FT_FRAME_CHAR( s, f ) FT_FRAME_FIELD( ft_frame_schar, s, f ) + +#define FT_FRAME_LONG_LE( s, f ) FT_FRAME_FIELD( ft_frame_long_le, s, f ) +#define FT_FRAME_ULONG_LE( s, f ) FT_FRAME_FIELD( ft_frame_ulong_le, s, f ) +#define FT_FRAME_SHORT_LE( s, f ) FT_FRAME_FIELD( ft_frame_short_le, s, f ) +#define FT_FRAME_USHORT_LE( s, f ) FT_FRAME_FIELD( ft_frame_ushort_le, s, 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( struct_type, field, count ) \ + { \ + ft_frame_bytes, \ + count, \ + (FT_UShort)(char*)&FT_FIELD_REF( struct_type, 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 NEXT_Char( buffer ) \ + ( (signed char)*buffer++ ) +#define NEXT_Byte( buffer ) \ + ( (unsigned char)*buffer++ ) + +#define NEXT_Short( buffer ) \ + ( buffer += 2, \ + ( (short)( (signed char)buffer[-2] << 8 ) | \ + (unsigned char)buffer[-1] ) ) + +#define NEXT_UShort( buffer ) \ + ( (unsigned short)NEXT_Short( buffer ) ) + +#define NEXT_Offset( buffer ) \ + ( buffer += 3, \ + ( ( (long)(signed char)buffer[-3] << 16 ) | \ + ( (long)(unsigned char)buffer[-2] << 8 ) | \ + (long)(unsigned char)buffer[-1] ) ) + +#define NEXT_UOffset( buffer ) \ + ( (unsigned long)NEXT_Offset( buffer ) ) + +#define NEXT_Long( buffer ) \ + ( buffer += 4, \ + ( ( (long)(signed char)buffer[-4] << 24 ) | \ + ( (long)(unsigned char)buffer[-3] << 16 ) | \ + ( (long)(unsigned char)buffer[-2] << 8 ) | \ + (long)(unsigned char)buffer[-1] ) ) + +#define NEXT_ULong( buffer ) \ + ( (unsigned long)NEXT_Long( buffer ) ) + + +#define NEXT_ShortLE( buffer ) \ + ( buffer += 2, \ + ( (short)( (signed char)buffer[-1] << 8 ) | \ + (unsigned char)buffer[-2] ) ) + +#define NEXT_UShortLE( buffer ) \ + ( (unsigned short)NEXT_ShortLE( buffer ) ) + +#define NEXT_OffsetLE( buffer ) \ + ( buffer += 3, \ + ( ( (long)(signed char)buffer[-1] << 16 ) | \ + ( (long)(unsigned char)buffer[-2] << 8 ) | \ + (long)(unsigned char)buffer[-3] ) ) + +#define NEXT_UOffsetLE( buffer ) \ + ( (unsigned long)NEXT_OffsetLE( buffer ) ) + + +#define NEXT_LongLE( buffer ) \ + ( buffer += 4, \ + ( ( (long)(signed char)buffer[-1] << 24 ) | \ + ( (long)(unsigned char)buffer[-2] << 16 ) | \ + ( (long)(unsigned char)buffer[-3] << 8 ) | \ + (long)(unsigned char)buffer[-4] ) ) + +#define NEXT_ULongLE( buffer ) \ + ( (unsigned long)NEXT_LongLE( buffer ) ) + + + /*************************************************************************/ + /* */ + /* 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 ) + + + BASE_DEF( void ) FT_New_Memory_Stream( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Stream stream ); + + BASE_DEF( FT_Error ) FT_Seek_Stream( FT_Stream stream, + FT_ULong pos ); + + BASE_DEF( FT_Error ) FT_Skip_Stream( FT_Stream stream, + FT_Long distance ); + + BASE_DEF( FT_Long ) FT_Stream_Pos( FT_Stream stream ); + + + BASE_DEF( FT_Error ) FT_Read_Stream( FT_Stream stream, + FT_Byte* buffer, + FT_ULong count ); + + BASE_DEF( FT_Error ) FT_Read_Stream_At( FT_Stream stream, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ); + + BASE_DEF( FT_Error ) FT_Access_Frame( FT_Stream stream, + FT_ULong count ); + + BASE_DEF( void ) FT_Forget_Frame( FT_Stream stream ); + + BASE_DEF( FT_Error ) FT_Extract_Frame( FT_Stream stream, + FT_ULong count, + FT_Byte** pbytes ); + + BASE_DEF( void ) FT_Release_Frame( FT_Stream stream, + FT_Byte** pbytes ); + + BASE_DEF( FT_Char ) FT_Get_Char( FT_Stream stream ); + + BASE_DEF( FT_Short ) FT_Get_Short( FT_Stream stream ); + + BASE_DEF( FT_Long ) FT_Get_Offset( FT_Stream stream ); + + BASE_DEF( FT_Long ) FT_Get_Long( FT_Stream stream ); + + BASE_DEF( FT_Short ) FT_Get_ShortLE( FT_Stream stream ); + + BASE_DEF( FT_Long ) FT_Get_LongLE( FT_Stream stream ); + + + BASE_DEF( FT_Char ) FT_Read_Char( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Short ) FT_Read_Short( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Long ) FT_Read_Offset( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Long ) FT_Read_Long( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Short ) FT_Read_ShortLE( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Long ) FT_Read_LongLE( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( 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 ) + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTSTREAM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/psnames.h b/reactos/subsys/win32k/freetype/include/freetype/internal/psnames.h new file mode 100644 index 00000000000..ed862359e2f --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/psnames.h @@ -0,0 +1,220 @@ +/***************************************************************************/ +/* */ +/* psnames.h */ +/* */ +/* High-level interface for the `PSNames' module (in charge of */ +/* various functions related to Postscript glyph names conversion). */ +/* */ +/* Copyright 1996-2000 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 + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Unicode_Value_Func */ + /* */ + /* */ + /* A function used to return the Unicode index corresponding to a */ + /* given glyph name. */ + /* */ + /* */ + /* glyph_name :: The glyph name. */ + /* */ + /* */ + /* The Unicode character index resp. the non-Unicode value 0xFFFF if */ + /* the glyph name has no known Unicode meaning. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Unicode_Index_Func */ + /* */ + /* */ + /* A function used to return the glyph index corresponding to a given */ + /* Unicode value. */ + /* */ + /* */ + /* num_glyphs :: The number of glyphs in the face. */ + /* */ + /* glyph_names :: An array of glyph name pointers. */ + /* */ + /* unicode :: The Unicode value. */ + /* */ + /* */ + /* The glyph index resp. 0xFFFF if no glyph corresponds to this */ + /* Unicode value. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Macintosh_Name_Func */ + /* */ + /* */ + /* A function used to return the glyph name corresponding to an Apple */ + /* glyph name index. */ + /* */ + /* */ + /* name_index :: The index of the Mac name. */ + /* */ + /* */ + /* The glyph name, or 0 if the index is invalid. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Unicodes */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* PSNames_Interface */ + /* */ + /* */ + /* This structure defines the PSNames interface. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* `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; + + +#endif /* PSNAMES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/sfnt.h b/reactos/subsys/win32k/freetype/include/freetype/internal/sfnt.h new file mode 100644 index 00000000000..380ee93deca --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/sfnt.h @@ -0,0 +1,492 @@ +/***************************************************************************/ +/* */ +/* sfnt.h */ +/* */ +/* High-level `sfnt' driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Face_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Face_Func */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Face_Func */ + /* */ + /* */ + /* A callback used to delete the common SFNT data from a face. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SFNT_Header_Func */ + /* */ + /* */ + /* Loads the header of a SFNT font file. Supports collections. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* sfnt :: The SFNT header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Directory_Func */ + /* */ + /* */ + /* Loads the table directory into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* sfnt :: The SFNT header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Any_Func */ + /* */ + /* */ + /* Loads any font table into client memory. */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* buffer :: The address of target buffer. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Image_Func */ + /* */ + /* */ + /* Loads a given glyph sbit image from the font resource. This also */ + /* returns its metrics. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* map :: The target pixmap. */ + /* */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* */ + /* FreeType error code. 0 means success. Returns an error if no */ + /* glyph sbit exists for the index. */ + /* */ + /* */ + /* The `map.buffer' field is always freed before the glyph is loaded. */ + /* */ + typedef + FT_Error (*TT_Load_SBit_Image_Func)( TT_Face face, + FT_Int x_ppem, + FT_Int y_ppem, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_PS_Name_Func */ + /* */ + /* */ + /* Gets the PostScript glyph name of a glyph. */ + /* */ + /* */ + /* 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! */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Get_PS_Name_Func)( TT_Face face, + FT_UInt index, + FT_String** PSname ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Metrics_Func */ + /* */ + /* */ + /* Loads the horizontal or vertical header in a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Load_Metrics_Func)( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Load_Func */ + /* */ + /* */ + /* Loads a given TrueType character map into memory. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* stream :: A handle to the current stream object. */ + /* */ + /* */ + /* cmap :: A pointer to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Free_Func */ + /* */ + /* */ + /* Destroys a character mapping table. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* cmap :: A handle to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_CharMap_Free_Func)( TT_Face face, + TT_CMapTable* cmap ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Table_Func */ + /* */ + /* */ + /* Loads a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Table_Func */ + /* */ + /* */ + /* Frees a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + typedef + void (*TT_Free_Table_Func)( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* SFNT_Interface */ + /* */ + /* */ + /* This structure holds pointers to the functions used to load and */ + /* free the basic tables that are required in a `sfnt' font file. */ + /* */ + /* */ + /* 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 `ttsbit.h' */ + 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; + + +#endif /* SFNT_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/t1errors.h b/reactos/subsys/win32k/freetype/include/freetype/internal/t1errors.h new file mode 100644 index 00000000000..58566d8ee54 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/t1errors.h @@ -0,0 +1,67 @@ +/***************************************************************************/ +/* */ +/* t1errors.h */ +/* */ +/* Type 1 error ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 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 T1ERRORS_H +#define T1ERRORS_H + + + /************************ error codes declaration **************/ + + /* The error codes are grouped into `classes' used to indicate the */ + /* `level' at which the error happened. */ + /* */ + /* The class is given by an error code's high byte. */ + + + /* ------------- Success is always 0 -------- */ + +#define T1_Err_Ok FT_Err_Ok + + /* ----------- high level API errors -------- */ + +#define T1_Err_Invalid_File_Format FT_Err_Invalid_File_Format +#define T1_Err_Invalid_Argument FT_Err_Invalid_Argument +#define T1_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle +#define T1_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle +#define T1_Err_Invalid_Size_Handle FT_Err_Invalid_Size_Handle +#define T1_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle +#define T1_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle +#define T1_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index + +#define T1_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature + +#define T1_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle + + /* ------------- internal errors ------------ */ + +#define T1_Err_Out_Of_Memory FT_Err_Out_Of_Memory +#define T1_Err_Unlisted_Object FT_Err_Unlisted_Object + + /* ------------ general glyph outline errors ------ */ + +#define T1_Err_Invalid_Composite FT_Err_Invalid_Composite + +#define T1_Err_Syntax_Error FT_Err_Invalid_File_Format +#define T1_Err_Stack_Underflow FT_Err_Invalid_File_Format +#define T1_Err_Stack_Overflow FT_Err_Invalid_File_Format + + +#endif /* T1ERRORS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/t1types.h b/reactos/subsys/win32k/freetype/include/freetype/internal/t1types.h new file mode 100644 index 00000000000..4d41a6b5914 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/t1types.h @@ -0,0 +1,188 @@ +/***************************************************************************/ +/* */ +/* t1types.h */ +/* */ +/* Basic Type1/Type2 type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 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 +#include + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Encoding */ + /* */ + /* */ + /* A structure modeling a custom encoding */ + /* */ + /* */ + /* 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_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* 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; + CID_Info cid; + void* afm_data; + CID_Subrs* subrs; + + } CID_FaceRec; + + +#endif /* T1TYPES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/t2errors.h b/reactos/subsys/win32k/freetype/include/freetype/internal/t2errors.h new file mode 100644 index 00000000000..d685220013f --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/t2errors.h @@ -0,0 +1,121 @@ +/***************************************************************************/ +/* */ +/* t2errors.h */ +/* */ +/* OpenType error ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 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 T2ERRORS_H +#define T2ERRORS_H + + + /*************************************************************************/ + /* */ + /* Error codes declaration */ + /* */ + /* The error codes are grouped in `classes' used to indicate the `level' */ + /* at which the error happened. The class is given by an error code's */ + /* high byte. */ + /* */ + /*************************************************************************/ + + + /* Success is always 0. */ + +#define T2_Err_Ok FT_Err_Ok + + /* High level API errors. */ + +#define T2_Err_Invalid_File_Format FT_Err_Invalid_File_Format +#define T2_Err_Invalid_Argument FT_Err_Invalid_Argument +#define T2_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle +#define T2_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle +#define T2_Err_Invalid_Instance_Handle FT_Err_Invalid_Size_Handle +#define T2_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle +#define T2_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle +#define T2_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index + +#define T2_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature + +#define T2_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle + + /* Internal errors. */ + +#define T2_Err_Out_Of_Memory FT_Err_Out_Of_Memory +#define T2_Err_Unlisted_Object FT_Err_Unlisted_Object + + /* General glyph outline errors. */ + +#define T2_Err_Invalid_Composite FT_Err_Invalid_Composite + + /* Bytecode interpreter error codes. */ + + /* These error codes are produced by the TrueType */ + /* bytecode interpreter. They usually indicate a */ + /* broken font file, a broken glyph within a font */ + /* file, or a bug in the interpreter! */ + +#define T2_Err_Invalid_Opcode 0x500 +#define T2_Err_Too_Few_Arguments 0x501 +#define T2_Err_Stack_Overflow 0x502 +#define T2_Err_Code_Overflow 0x503 +#define T2_Err_Bad_Argument 0x504 +#define T2_Err_Divide_By_Zero 0x505 +#define T2_Err_Storage_Overflow 0x506 +#define T2_Err_Cvt_Overflow 0x507 +#define T2_Err_Invalid_Reference 0x508 +#define T2_Err_Invalid_Distance 0x509 +#define T2_Err_Interpolate_Twilight 0x50A +#define T2_Err_Debug_OpCode 0x50B +#define T2_Err_ENDF_In_Exec_Stream 0x50C +#define T2_Err_Out_Of_CodeRanges 0x50D +#define T2_Err_Nested_DEFS 0x50E +#define T2_Err_Invalid_CodeRange 0x50F +#define T2_Err_Invalid_Displacement 0x510 +#define T2_Err_Execution_Too_Long 0x511 + +#define T2_Err_Too_Many_Instruction_Defs 0x512 +#define T2_Err_Too_Many_Function_Defs 0x513 + + /* Other TrueType specific error codes. */ + +#define T2_Err_Table_Missing 0x520 +#define T2_Err_Too_Many_Extensions 0x521 +#define T2_Err_Extensions_Unsupported 0x522 +#define T2_Err_Invalid_Extension_Id 0x523 + +#define T2_Err_No_Vertical_Data 0x524 + +#define T2_Err_Max_Profile_Missing 0x530 +#define T2_Err_Header_Table_Missing 0x531 +#define T2_Err_Horiz_Header_Missing 0x532 +#define T2_Err_Locations_Missing 0x533 +#define T2_Err_Name_Table_Missing 0x534 +#define T2_Err_CMap_Table_Missing 0x535 +#define T2_Err_Hmtx_Table_Missing 0x536 +#define T2_Err_OS2_Table_Missing 0x537 +#define T2_Err_Post_Table_Missing 0x538 + +#define T2_Err_Invalid_Horiz_Metrics 0x540 +#define T2_Err_Invalid_CharMap_Format 0x541 +#define T2_Err_Invalid_PPem 0x542 +#define T2_Err_Invalid_Vert_Metrics 0x543 + +#define T2_Err_Could_Not_Find_Context 0x550 + + +#endif /* T2ERRORS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/t2types.h b/reactos/subsys/win32k/freetype/include/freetype/internal/t2types.h new file mode 100644 index 00000000000..033f315e955 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/t2types.h @@ -0,0 +1,218 @@ +/***************************************************************************/ +/* */ +/* t2types.h */ +/* */ +/* Basic OpenType/CFF type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 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 T2TYPES_H +#define T2TYPES_H + + +#include + + + /*************************************************************************/ + /* */ + /* */ + /* CFF_Index */ + /* */ + /* */ + /* A structure used to model a CFF Index table. */ + /* */ + /* */ + /* stream :: XXX */ + /* */ + /* 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 :: XXX */ + /* */ + /* 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_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_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; + + /* we don't load the Encoding and CharSet tables */ + + 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; + + +#endif /* T2TYPES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/tterrors.h b/reactos/subsys/win32k/freetype/include/freetype/internal/tterrors.h new file mode 100644 index 00000000000..b53e9f3da49 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/tterrors.h @@ -0,0 +1,121 @@ +/***************************************************************************/ +/* */ +/* tterrors.h */ +/* */ +/* TrueType error ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 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 TTERRORS_H +#define TTERRORS_H + + + /*************************************************************************/ + /* */ + /* Error codes declaration */ + /* */ + /* The error codes are grouped in `classes' used to indicate the `level' */ + /* at which the error happened. The class is given by an error code's */ + /* high byte. */ + /* */ + /*************************************************************************/ + + + /* Success is always 0. */ + +#define TT_Err_Ok FT_Err_Ok + + /* High level API errors. */ + +#define TT_Err_Invalid_File_Format FT_Err_Invalid_File_Format +#define TT_Err_Invalid_Argument FT_Err_Invalid_Argument +#define TT_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle +#define TT_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle +#define TT_Err_Invalid_Instance_Handle FT_Err_Invalid_Size_Handle +#define TT_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle +#define TT_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle +#define TT_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index + +#define TT_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature + +#define TT_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle + + /* Internal errors. */ + +#define TT_Err_Out_Of_Memory FT_Err_Out_Of_Memory +#define TT_Err_Unlisted_Object FT_Err_Unlisted_Object + + /* General glyph outline errors. */ + +#define TT_Err_Too_Many_Ins FT_Err_Too_Many_Hints +#define TT_Err_Invalid_Composite FT_Err_Invalid_Composite + + /* Bytecode interpreter error codes. */ + + /* These error codes are produced by the TrueType */ + /* bytecode interpreter. They usually indicate a */ + /* broken font file, a broken glyph within a font */ + /* file, or a bug in the interpreter! */ + +#define TT_Err_Invalid_Opcode 0x400 +#define TT_Err_Too_Few_Arguments 0x401 +#define TT_Err_Stack_Overflow 0x402 +#define TT_Err_Code_Overflow 0x403 +#define TT_Err_Bad_Argument 0x404 +#define TT_Err_Divide_By_Zero 0x405 +#define TT_Err_Storage_Overflow 0x406 +#define TT_Err_Cvt_Overflow 0x407 +#define TT_Err_Invalid_Reference 0x408 +#define TT_Err_Invalid_Distance 0x409 +#define TT_Err_Interpolate_Twilight 0x40A +#define TT_Err_Debug_OpCode 0x40B +#define TT_Err_ENDF_In_Exec_Stream 0x40C +#define TT_Err_Out_Of_CodeRanges 0x40D +#define TT_Err_Nested_DEFS 0x40E +#define TT_Err_Invalid_CodeRange 0x40F +#define TT_Err_Invalid_Displacement 0x410 +#define TT_Err_Execution_Too_Long 0x411 +#define TT_Err_Too_Many_Function_Defs 0x412 +#define TT_Err_Too_Many_Instruction_Defs 0x413 + + /* Other TrueType specific error codes. */ + +#define TT_Err_Table_Missing 0x420 +#define TT_Err_Too_Many_Extensions 0x421 +#define TT_Err_Extensions_Unsupported 0x422 +#define TT_Err_Invalid_Extension_Id 0x423 + +#define TT_Err_No_Vertical_Data 0x424 + +#define TT_Err_Max_Profile_Missing 0x430 +#define TT_Err_Header_Table_Missing 0x431 +#define TT_Err_Horiz_Header_Missing 0x432 +#define TT_Err_Locations_Missing 0x433 +#define TT_Err_Name_Table_Missing 0x434 +#define TT_Err_CMap_Table_Missing 0x435 +#define TT_Err_Hmtx_Table_Missing 0x436 +#define TT_Err_OS2_Table_Missing 0x437 +#define TT_Err_Post_Table_Missing 0x438 + +#define TT_Err_Invalid_Horiz_Metrics 0x440 +#define TT_Err_Invalid_CharMap_Format 0x441 +#define TT_Err_Invalid_PPem 0x442 +#define TT_Err_Invalid_Vert_Metrics 0x443 + +#define TT_Err_Could_Not_Find_Context 0x450 + + +#endif /* TTERRORS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/internal/tttypes.h b/reactos/subsys/win32k/freetype/include/freetype/internal/tttypes.h new file mode 100644 index 00000000000..1fd43ceb506 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/internal/tttypes.h @@ -0,0 +1,1582 @@ +/***************************************************************************/ +/* */ +/* tttypes.h */ +/* */ +/* Basic SFNT/TrueType type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 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 + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** REQUIRED TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TTC_Header */ + /* */ + /* */ + /* TrueType collection header. This table contains the offsets of */ + /* the font headers of each distinct TrueType face in the file. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* SFNT_Header */ + /* */ + /* */ + /* SFNT file format header. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_TableDir */ + /* */ + /* */ + /* This structure models a TrueType table directory. It is used to */ + /* access the various tables of the font face. */ + /* */ + /* */ + /* version :: The version number; starts with 0x00010000. */ + /* */ + /* numTables :: The number of tables. */ + /* */ + /* searchRange :: Unused. */ + /* */ + /* entrySelector :: Unused. */ + /* */ + /* rangeShift :: Unused. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Table */ + /* */ + /* */ + /* This structure describes a given table of a TrueType font. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CMapDir */ + /* */ + /* */ + /* This structure describes the directory of the `cmap' table, */ + /* containing the font's character mappings table. */ + /* */ + /* */ + /* tableVersionNumber :: The version number. */ + /* */ + /* numCMaps :: The number of charmaps in the font. */ + /* */ + /* */ + /* This structure is only used during font loading. */ + /* */ + typedef struct TT_CMapDir_ + { + FT_UShort tableVersionNumber; + FT_UShort numCMaps; + + } TT_CMapDir; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CMapDirEntry */ + /* */ + /* */ + /* This structure describes a charmap in a TrueType font. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* This structure is only used during font loading. */ + /* */ + typedef struct TT_CMapDirEntry_ + { + FT_UShort platformID; + FT_UShort platformEncodingID; + FT_Long offset; + + } TT_CMapDirEntry; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_LongMetrics */ + /* */ + /* */ + /* A structure modeling the long metrics of the `hmtx' and `vmtx' */ + /* TrueType tables. The values are expressed in font units. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* TT_ShortMetrics */ + /* */ + /* */ + /* A simple type to model the short metrics of the `hmtx' and `vmtx' */ + /* tables. */ + /* */ + typedef FT_Short TT_ShortMetrics; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_NameRec */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_NameTable */ + /* */ + /* */ + /* A structure modeling the TrueType name table. */ + /* */ + /* */ + /* 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 ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GaspRange */ + /* */ + /* */ + /* A tiny structure used to model a gasp range according to the */ + /* TrueType specification. */ + /* */ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Gasp */ + /* */ + /* */ + /* A structure modeling the TrueType `gasp' table used to specify */ + /* grid-fitting and anti-aliasing behaviour. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_HdmxRec */ + /* */ + /* */ + /* A small structure used to model the pre-computed widths of a given */ + /* size. They are found in the `hdmx' table. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Hdmx */ + /* */ + /* */ + /* A structure used to model the `hdmx' table, which contains */ + /* pre-computed widths for a set of given sizes/dimensions. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Kern_0_Pair */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Metrics */ + /* */ + /* */ + /* 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 `bdat' (Apple) table. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Small_Metrics */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Line_Metrics */ + /* */ + /* */ + /* A structure used to describe the text line metrics of a given */ + /* bitmap strike, for either a horizontal or vertical layout. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Range */ + /* */ + /* */ + /* A TrueType/OpenType subIndexTable as defined in the `EBLC' */ + /* (Microsoft) or `bloc' (Apple) tables. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Strike */ + /* */ + /* */ + /* A structure used describe a given bitmap strike in the `EBLC' */ + /* (Microsoft) or `bloc' (Apple) tables. */ + /* */ + /* */ + /* num_index_ranges :: The number of index ranges. */ + /* */ + /* index_ranges :: An array of glyph index ranges. */ + /* */ + /* color_ref :: Unused. A color reference? */ + /* */ + /* 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? */ + /* */ + 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Component */ + /* */ + /* */ + /* A simple structure to describe a compound sbit element. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Scale */ + /* */ + /* */ + /* A structure used describe a given bitmap scaling table, as defined */ + /* in the `EBSC' table. */ + /* */ + /* */ + /* 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 ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Post_20 */ + /* */ + /* */ + /* Postscript names sub-table, format 2.0. Stores the PS name of */ + /* each glyph in the font face. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Post_25 */ + /* */ + /* */ + /* Postscript names sub-table, format 2.5. Stores the PS name of */ + /* each glyph in the font face. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Post_Names */ + /* */ + /* */ + /* Postscript names table, either format 2.0 or 2.5. */ + /* */ + /* */ + /* 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_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_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_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_UShort firstCode; /* first character code of subrange */ + FT_UShort entryCount; /* number of character codes in subrange */ + + FT_UShort* glyphIdArray; + + } TT_CMap6; + + + 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_UShort length; + FT_UShort version; + + FT_Bool loaded; + FT_ULong offset; + + union + { + TT_CMap0 cmap0; + TT_CMap2 cmap2; + TT_CMap4 cmap4; + TT_CMap6 cmap6; + } c; + + TT_CharMap_Func get_index; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMapRec */ + /* */ + /* */ + /* The TrueType character map object type. */ + /* */ + /* */ + /* 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'. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Face */ + /* */ + /* */ + /* A handle to a TrueType face/font object. A TT_Face encapsulates */ + /* the resolution and scaling independent parts of a TrueType font */ + /* resource. */ + /* */ + /* */ + /* The TT_Face structure is also used as a `parent class' for the */ + /* OpenType-CFF class (T2_Face). */ + /* */ + typedef struct TT_FaceRec_* TT_Face; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Goto_Table_Func */ + /* */ + /* */ + /* Seeks a stream to the start of a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* tag :: A 4-byte tag used to name the table. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* length :: The length of the table in bytes. Set to 0 if not */ + /* needed. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Access_Glyph_Frame_Func */ + /* */ + /* */ + /* Seeks a stream to the start of a given glyph element, and opens a */ + /* frame for it. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Glyph_Element_Func */ + /* */ + /* */ + /* Reads one glyph element (its header, a simple glyph, or a */ + /* composite) from the loader's current stream frame. */ + /* */ + /* */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Load_Glyph_Element_Func)( TT_Loader* loader ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Forget_Glyph_Frame_Func */ + /* */ + /* */ + /* Closes the current loader stream frame for the glyph. */ + /* */ + /* */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + typedef + void (*TT_Forget_Glyph_Frame_Func)( TT_Loader* loader ); + + + + /*************************************************************************/ + /* */ + /* TrueType Face Type */ + /* */ + /* */ + /* TT_Face */ + /* */ + /* */ + /* The TrueType face class. These objects model the resolution and */ + /* point-size independent data found in a TrueType font file. */ + /* */ + /* */ + /* 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_Int 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GlyphZone */ + /* */ + /* */ + /* A glyph zone is used to load, scale and hint glyph outline */ + /* coordinates. */ + /* */ + /* */ + /* 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_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; + + }; + + +#endif /* TTTYPES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/t1tables.h b/reactos/subsys/win32k/freetype/include/freetype/t1tables.h new file mode 100644 index 00000000000..323e0130c15 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/t1tables.h @@ -0,0 +1,235 @@ +/***************************************************************************/ +/* */ +/* t1tables.h */ +/* */ +/* Basic Type 1/Type 2 tables definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 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 + + + /* Note that we separate font data in T1_FontInfo and T1_Private */ + /* structures in order to support Multiple Master fonts. */ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_FontInfo */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Private */ + /* */ + /* */ + /* 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]; /* reserve one place for the std */ + FT_Short snap_heights[13]; /* reserve one place for the std */ + + FT_Long language_group; + FT_Long password; + + FT_Short min_feature[2]; + + } T1_Private; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Blend_Flags */ + /* */ + /* */ + /* 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_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; + + +#endif /* T1TABLES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/ttnameid.h b/reactos/subsys/win32k/freetype/include/freetype/ttnameid.h new file mode 100644 index 00000000000..48902424152 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/ttnameid.h @@ -0,0 +1,698 @@ +/***************************************************************************/ +/* */ +/* ttmakeid.h */ +/* */ +/* TrueType name ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 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 + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* 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 +#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 + + + /*************************************************************************/ + /* */ + /* 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 +#define TT_MS_LANGID_CHINESE_MACAU 0x1404 +#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 +#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0428 +#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 +#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c +#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c +#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 + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */ + /* */ + /* Updated 02-Jul-2000. */ + /* */ + + /* General Scripts Area */ + + /* Bit 0 C0 Controls and 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+00A0-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 */ +#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 + Extended Bopomofo */ +#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 CJK Miscellaneous */ +#define TT_UCR_CJK_MISC (1L << 21) /* U+3190-U+319F */ + /* 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 Surrogates */ +#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DFFF */ + /* Bit 58 is reserved for Unicode SubRanges */ + + /* CJK Ideographs Area */ + + /* Bit 59 CJK Unified Ideographs + */ + /* CJK Radical Supplement + */ + /* Kangxi Radicals + */ + /* Ideographic Description + */ + /* 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+34E0-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+0FCF */ + /* 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+12BF */ + /* Bit 76 Cherokee */ +#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */ + /* Bit 77 Canadian Aboriginal Syllabics */ +#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+14DF */ + /* 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 */ +#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */ + /* Bit 83 Yi + Yi Radicals */ +#define TT_UCR_YI (1L << 19) /* U+A000-U+A48C */ + /* 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 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 */ + + +#endif /* TTNAMEID_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/tttables.h b/reactos/subsys/win32k/freetype/include/freetype/tttables.h new file mode 100644 index 00000000000..27c46f3c99a --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/tttables.h @@ -0,0 +1,583 @@ +/***************************************************************************/ +/* */ +/* tttables.h */ +/* */ +/* Basic SFNT/TrueType tables definitions and interface */ +/* (specification only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Header */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_HoriHeader */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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're used to connect the metrics header to the relevant */ + /* `HMTX' table. */ + + void* long_metrics; + void* short_metrics; + + } TT_HoriHeader; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_VertHeader */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* Reserved :: 10 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_OS2 */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Postscript */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_PCLT */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_MaxProfile */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Sfnt_Table */ + /* */ + /* */ + /* Returns a pointer to a given SFNT table within a face. */ + /* */ + /* */ + /* face :: A handle to the source. */ + /* */ + /* tag :: The index of the SFNT table. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* You can load any table using the (internal) SFNT_Interface */ + /* structure -- this is available via FT_Get_Module_Interface(). */ + /* */ + FT_EXPORT_DEF( void* ) FT_Get_Sfnt_Table( FT_Face face, + FT_Sfnt_Tag tag ); + +#ifdef __cplusplus + } +#endif + + +#endif /* TTTABLES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/include/freetype/tttags.h b/reactos/subsys/win32k/freetype/include/freetype/tttags.h new file mode 100644 index 00000000000..9de9810e992 --- /dev/null +++ b/reactos/subsys/win32k/freetype/include/freetype/tttags.h @@ -0,0 +1,66 @@ +/***************************************************************************/ +/* */ +/* tttags.h */ +/* */ +/* Tags for TrueType tables (specification only). */ +/* */ +/* Copyright 1996-2000 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 /* for MAKE_TT_TAG() */ + + +#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_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' ) + +#endif /* TTAGS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/license.txt b/reactos/subsys/win32k/freetype/license.txt new file mode 100644 index 00000000000..f14087b9117 --- /dev/null +++ b/reactos/subsys/win32k/freetype/license.txt @@ -0,0 +1,164 @@ + The FreeType Project LICENSE + ---------------------------- + + 2000-Feb-08 + + Copyright 1996-2000 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we are be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`LICENSE.TXT') unaltered; any additions, deletions or changes + to the original files must be clearly indicated in + accompanying documentation. The copyright notices of the + unaltered, original files must be preserved in all copies of + source files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@freetype.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o devel@freetype.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + o http://www.freetype.org + + Holds the current FreeType web page, which will allow you to + download our latest development version and read online + documentation. + + You can also contact us individually at: + + David Turner + Robert Wilhelm + Werner Lemberg + + +--- end of LICENSE.TXT --- diff --git a/reactos/subsys/win32k/freetype/obj/README b/reactos/subsys/win32k/freetype/obj/README new file mode 100644 index 00000000000..91fdcbdc120 --- /dev/null +++ b/reactos/subsys/win32k/freetype/obj/README @@ -0,0 +1 @@ +This directory contains all the object files created when building the library diff --git a/reactos/subsys/win32k/freetype/psmodule.c b/reactos/subsys/win32k/freetype/psmodule.c new file mode 100644 index 00000000000..4817b173955 --- /dev/null +++ b/reactos/subsys/win32k/freetype/psmodule.c @@ -0,0 +1,322 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* psmodule.c */ +/* */ +/* PSNames module implementation (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "psmodule.h" +#include "pstables.h" + +#else + +#include +#include + +#endif + + +#include /* for qsort() */ +#include /* 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 + 4; + + + for ( count = 4; count > 0; count--, p++ ) + { + char c = *p; + unsigned char 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 = 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 = t1_standard_glyphs[n]; + + + if ( first == name[0] && strcmp( glyph_name, name ) == 0 ) + return 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 */ + static + 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 && uni_char != 0xFFFF ) + { + map->unicode = uni_char; + map->glyph_index = n; + map++; + } + } + } + + /* now, compress the table a bit */ + count = 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 = FT_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 standard_glyph_names[mac_standard_names[name_index]]; + } + + + static + const char* PS_Standard_Strings( FT_UInt sid ) + { + return ( sid < NUM_STD_GLYPHS ? t1_standard_glyphs[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 */ + + + 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/reactos/subsys/win32k/freetype/psmodule.h b/reactos/subsys/win32k/freetype/psmodule.h new file mode 100644 index 00000000000..ff7ef065037 --- /dev/null +++ b/reactos/subsys/win32k/freetype/psmodule.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* psmodule.h */ +/* */ +/* High-level PSNames module interface (specification). */ +/* */ +/* Copyright 1996-2000 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 PSDRIVER_H +#define PSDRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Module_Class ) psnames_module_class; + +#endif /* PSDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/psnames.c b/reactos/subsys/win32k/freetype/psnames.c new file mode 100644 index 00000000000..57ca5885642 --- /dev/null +++ b/reactos/subsys/win32k/freetype/psnames.c @@ -0,0 +1,24 @@ +/***************************************************************************/ +/* */ +/* psnames.c */ +/* */ +/* FreeType PSNames module component (body only). */ +/* */ +/* Copyright 1996-2000 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 "psmodule.c" + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/pstables.h b/reactos/subsys/win32k/freetype/pstables.h new file mode 100644 index 00000000000..094bc27c335 --- /dev/null +++ b/reactos/subsys/win32k/freetype/pstables.h @@ -0,0 +1,2942 @@ +/***************************************************************************/ +/* */ +/* pstables.h */ +/* */ +/* PostScript glyph names (specification only). */ +/* */ +/* Copyright 2000 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* standard_glyph_names[] = + { + ".null", + "CR", + "notequal", + "infinity", + "lessequal", + "greaterequal", + "partialdiff", + "summation", + "product", + "pi", + "integral", + "Omega", + "radical", + "approxequal", + "Delta", + "nbspace", + "lozenge", + "periodcentered", + "apple", + "lslash", + "franc", + "Gbreve", + "gbreve", + "Idot", + "Scedilla", + "scedilla", + "Cacute", + "cacute", + "Ccaron", + "ccaron", + "dmacron", + ".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", + "periodcenter", + "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", + "Islash", + "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", + "Uacautesmall", + "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", + "Caron", + "Ccircumflex", + "Cdotaccent", + "Chi", + "Dcaron", + "Dcroat", + "Dieresis", + "DieresisAcute", + "DieresisGrave", + "Ebreve", + "Ecaron", + "Edotaccent", + "Emacron", + "Eng", + "Eogonek", + "Epsilon", + "Epsilontonos", + "Eta", + "Etatonos", + "Euro", + "Gamma", + "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", + "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", + "Scircumflex", + "Scommaaccent", + "Sigma", + "Tau", + "Tbar", + "Tcaron", + "Tcommaaccent", + "Tcommaaccent", + "Theta", + "Uacutesmall", + "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", + "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", + "carriagereturn", + "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", + "gamma", + "gcaron", + "gcircumflex", + "gcommaaccent", + "gdotaccent", + "gradient", + "gravecomb", + "hbar", + "hcircumflex", + "heart", + "hookabovecomb", + "house", + "ibreve", + "ij", + "imacron", + "integralbt", + "integralex", + "integraltp", + "intersection", + "invbullet", + "invcircle", + "invsmileface", + "iogonek", + "iota", + "iotadieresis", + "iotadieresistonos", + "iotatonos", + "itilde", + "jcircumflex", + "kappa", + "kcommaaccent", + "kgreenlandic", + "lacute", + "lambda", + "lcaron", + "lcommaaccent", + "ldot", + "lfblock", + "lira", + "ll", + "logicaland", + "logicalor", + "longs", + "ltshade", + "male", + "minute", + "musicalnote", + "musicalnotedbl", + "nacute", + "napostrophe", + "ncaron", + "ncommaaccent", + "notelement", + "notsubset", + "nu", + "obreve", + "ohorn", + "ohungarumlaut", + "omacron", + "omega", + "omega1", + "omegatonos", + "omicron", + "omicrontonos", + "openbullet", + "orthogonal", + "oslashacute", + "parenleftbt", + "parenleftex", + "parenlefttp", + "parenrightbt", + "parenrightex", + "parenrighttp", + "perpendicular", + "peseta", + "phi", + "phi1", + "prescription", + "propersubset", + "propersuperset", + "proportional", + "psi", + "quotereversed", + "racute", + "radicalex", + "rcaron", + "rcommaaccent", + "reflexsubset", + "reflexsuperset", + "registersans", + "registerserif", + "revlogicalnot", + "rho", + "rtblock", + "sacute", + "scircumflex", + "scommaaccent", + "second", + "shade", + "sigma", + "sigma1", + "similar", + "smileface", + "spade", + "suchthat", + "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 */ + + 0 + }; + + + static const char** t1_standard_glyphs = standard_glyph_names + 31; + + +#define NUM_STD_GLYPHS 391 + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST +#define NUM_ADOBE_GLYPHS 1032 +#else +#define NUM_ADOBE_GLYPHS 391 +#endif + + + static const unsigned short mac_standard_names[259] = + { + 0, + 0, + 1, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 104, + 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, + 124, + 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, + 173, + 175, + 177, + 178, + 186, + 189, + 195, + 200, + 203, + 201, + 202, + 205, + 204, + 206, + 207, + 210, + 208, + 209, + 211, + 214, + 212, + 213, + 215, + 216, + 219, + 217, + 218, + 220, + 222, + 225, + 223, + 224, + 112, + 161, + 97, + 98, + 102, + 116, + 115, + 149, + 165, + 170, + 153, + 125, + 131, + 2, + 138, + 141, + 3, + 156, + 4, + 5, + 100, + 152, + 6, + 7, + 8, + 9, + 10, + 139, + 143, + 11, + 144, + 147, + 123, + 96, + 151, + 12, + 101, + 13, + 14, + 106, + 120, + 121, + 15, + 174, + 176, + 191, + 142, + 148, + 111, + 137, + 105, + 119, + 65, + 8, + 159, + 16, + 227, + 198, + 99, + 103, + 107, + 108, + 109, + 110, + 113, + 17, + 117, + 118, + 122, + 172, + 179, + 171, + 180, + 181, + 182, + 183, + 184, + 185, + 187, + 188, + 18, + 190, + 193, + 194, + 196, + 145, + 126, + 127, + 128, + 129, + 130, + 132, + 133, + 134, + 135, + 136, + 140, + 19, + 192, + 221, + 199, + 228, + 160, + 154, + 167, + 197, + 226, + 157, + 162, + 166, + 168, + 150, + 164, + 169, + 155, + 158, + 163, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 0 + }; + + + + static const unsigned short names_to_unicode[1033] = + { + 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, + 0, + 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, + 0, + 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, + 0, + 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, + 0xF6CA, + 0x0108, + 0x010A, + 0x03A7, + 0x010E, + 0x0110, + 0xF6CB, + 0xF6CC, + 0xF6CD, + 0x0114, + 0x011A, + 0x0116, + 0x0112, + 0x014A, + 0x0118, + 0x0395, + 0x0388, + 0x0397, + 0x0389, + 0x20AC, + 0x0393, + 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, + 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, + 0x015C, + 0x0218, + 0x03A3, + 0x03A4, + 0x0166, + 0x0164, + 0x0162, + 0x0162, + 0x0398, + 0xF7FA, + 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, + 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, + 0x21B5, + 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, + 0x03B3, + 0x01E7, + 0x011D, + 0x0123, + 0x0121, + 0x2207, + 0x0300, + 0x0127, + 0x0125, + 0x2665, + 0x0309, + 0x2302, + 0x012D, + 0x0133, + 0x012B, + 0x2321, + 0xF8F5, + 0x2320, + 0x2229, + 0x25D8, + 0x25D9, + 0x263B, + 0x012F, + 0x03B9, + 0x03CA, + 0x0390, + 0x03AF, + 0x0129, + 0x0135, + 0x03BA, + 0x0137, + 0x0138, + 0x013A, + 0x03BB, + 0x013E, + 0x013C, + 0x0140, + 0x258C, + 0x20A4, + 0xF6C0, + 0x2227, + 0x2228, + 0x017F, + 0x2591, + 0x2642, + 0x2032, + 0x266A, + 0x266B, + 0x0144, + 0x0149, + 0x0148, + 0x0146, + 0x2209, + 0x2284, + 0x03BD, + 0x014F, + 0x01A1, + 0x0151, + 0x014D, + 0x03C9, + 0x03D6, + 0x03CE, + 0x03BF, + 0x03CC, + 0x25E6, + 0x221F, + 0x01FF, + 0xF8ED, + 0xF8EC, + 0xF8EB, + 0xF8F8, + 0xF8F7, + 0xF8F6, + 0x22A5, + 0x20A7, + 0x03C6, + 0x03D5, + 0x211E, + 0x2282, + 0x2283, + 0x221D, + 0x03C8, + 0x201B, + 0x0155, + 0xF8E5, + 0x0159, + 0x0157, + 0x2286, + 0x2287, + 0xF8E8, + 0xF6DA, + 0x2310, + 0x03C1, + 0x2590, + 0x015B, + 0x015D, + 0x0219, + 0x2033, + 0x2592, + 0x03C3, + 0x03C2, + 0x223C, + 0x263A, + 0x2660, + 0x220B, + 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, + 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, + 0 + }; + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/raster1.c b/reactos/subsys/win32k/freetype/raster1.c new file mode 100644 index 00000000000..48123e50629 --- /dev/null +++ b/reactos/subsys/win32k/freetype/raster1.c @@ -0,0 +1,37 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* raster1.c */ +/* */ +/* FreeType monochrome rasterer module component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ftraster.c" +#include "ftrend1.c" + +#else + +#include +#include + +#endif + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/sfdriver.c b/reactos/subsys/win32k/freetype/sfdriver.c new file mode 100644 index 00000000000..96a738b43cc --- /dev/null +++ b/reactos/subsys/win32k/freetype/sfdriver.c @@ -0,0 +1,225 @@ +/***************************************************************************/ +/* */ +/* sfdriver.c */ +/* */ +/* High-level SFNT driver interface (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "sfdriver.h" +#include "ttload.h" +#include "ttsbit.h" +#include "ttpost.h" +#include "ttcmap.h" +#include "sfobjs.h" + +#else + +#include +#include +#include +#include +#include +#include + +#endif + + +#include /* 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 = strlen( gname ); + + + if ( len >= buffer_max ) + len = buffer_max - 1; + + MEM_Copy( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return error; + } + + +#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + + static + 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 + 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 `ttsbit.h' */ + TT_Load_SBit_Strikes, + TT_Load_SBit_Image, + TT_Free_SBit_Strikes, + +#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + 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, + }; + + + 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/reactos/subsys/win32k/freetype/sfdriver.h b/reactos/subsys/win32k/freetype/sfdriver.h new file mode 100644 index 00000000000..92c9c8129d1 --- /dev/null +++ b/reactos/subsys/win32k/freetype/sfdriver.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* sfdriver.h */ +/* */ +/* High-level SFNT driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + FT_EXPORT_VAR( const FT_Module_Class ) sfnt_module_class; + +#endif /* SFDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/sfnt.c b/reactos/subsys/win32k/freetype/sfnt.c new file mode 100644 index 00000000000..5ebd49b7e48 --- /dev/null +++ b/reactos/subsys/win32k/freetype/sfnt.c @@ -0,0 +1,59 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* sfnt.c */ +/* */ +/* Single object library component. */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.c" +#include "ttcmap.c" +#include "sfobjs.c" + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS +#include "ttsbit.c" +#endif + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include "ttpost.c" +#endif + +#include "sfdriver.c" + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS +#include +#endif + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include +#endif + +#include + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/sfobjs.c b/reactos/subsys/win32k/freetype/sfobjs.c new file mode 100644 index 00000000000..4ae85022e8e --- /dev/null +++ b/reactos/subsys/win32k/freetype/sfobjs.c @@ -0,0 +1,561 @@ +/***************************************************************************/ +/* */ +/* sfobjs.c */ +/* */ +/* SFNT object management (base). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "sfobjs.h" + +#else + +#include + +#endif + + +#include +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Name */ + /* */ + /* */ + /* Returns a given ENGLISH name record in ASCII. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* nameid :: The name id of the name record to 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_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; + } + + + LOCAL_FUNC + 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 = FT_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 ) ) \ + != TT_Err_Ok ) + + + LOCAL_FUNC + 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; + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + FT_UNUSED( face_index ); + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + /* Load tables */ + if ( LOAD_( header ) || + LOAD_( max_profile ) || + + /* load the `hhea' & `hmtx' tables at once */ + ( error = sfnt->load_metrics( face, stream, 0 ) ) != TT_Err_Ok || + + /* try to load the `vhea' & `vmtx' at once if present */ + ( error = sfnt->load_metrics( face, stream, 1 ) ) != TT_Err_Ok || + + LOAD_( charmaps ) || + LOAD_( names ) || + LOAD_( os2 ) || + LOAD_( psnames ) ) + goto Exit; + + /* the optional tables */ + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + /* embedded bitmap support. */ + if ( sfnt->load_sbits && LOAD_( sbits ) ) + 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 ) ) != TT_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; + TT_CharMap charmap; + FT_Int n; + FT_Memory memory; + + + memory = root->memory; + + /*********************************************************************/ + /* */ + /* Compute face flags. */ + /* */ + flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ + 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 ( 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 = platform; + charmap->root.encoding_id = 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->num_fixed_sizes = face->num_sbit_strikes; + if ( ALLOC_ARRAY( root->available_sizes, + face->num_sbit_strikes, + FT_Bitmap_Size ) ) + return error; + + 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 + +#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + { + root->num_fixed_sizes = 0; + root->available_sizes = 0; + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /*********************************************************************/ + /* */ + /* Set up metrics. */ + /* */ + 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; + + /* The ascender/descender/height are computed from the OS/2 table */ + /* when found. Otherwise, they're taken from the horizontal header. */ + if ( face->os2.version != 0xFFFF ) + { + root->ascender = face->os2.sTypoAscender; + root->descender = -face->os2.sTypoDescender; + root->height = root->ascender + root->descender + + face->os2.sTypoLineGap; + } + else + { + root->ascender = face->horizontal.Ascender; + root->descender = face->horizontal.Descender; + root->height = root->ascender + root->descender + + face->horizontal.Line_Gap; + } + + root->max_advance_width = face->horizontal.advance_Width_Max; + + root->max_advance_height = 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_ + + + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/sfobjs.h b/reactos/subsys/win32k/freetype/sfobjs.h new file mode 100644 index 00000000000..35d92f9d198 --- /dev/null +++ b/reactos/subsys/win32k/freetype/sfobjs.h @@ -0,0 +1,57 @@ +/***************************************************************************/ +/* */ +/* sfobjs.h */ +/* */ +/* SFNT object management (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error SFNT_Init_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + FT_Error SFNT_Load_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void SFNT_Done_Face( TT_Face face ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* SFDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/smooth.c b/reactos/subsys/win32k/freetype/smooth.c new file mode 100644 index 00000000000..cbe86f61d7e --- /dev/null +++ b/reactos/subsys/win32k/freetype/smooth.c @@ -0,0 +1,37 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* smooth.c */ +/* */ +/* FreeType anti-aliasing rasterer module component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ftgrays.c" +#include "ftsmooth.c" + +#else + +#include +#include + +#endif + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/CatharonLicense.txt b/reactos/subsys/win32k/freetype/src/autohint/CatharonLicense.txt new file mode 100644 index 00000000000..e68bc230505 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/CatharonLicense.txt @@ -0,0 +1,123 @@ + The Catharon Open Source LICENSE + ---------------------------- + + 2000-Jul-04 + + Copyright (C) 2000 by Catharon Productions, Inc. + + + +Introduction +============ + + This license applies to source files distributed by Catharon + Productions, Inc. in several archive packages. This license + applies to all files found in such packages which do not fall + under their own explicit license. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we are + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + Catharon Code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering the packages distributed by + Catharon Productions, Inc. and assume no liability related to + their use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `Catharon Package', `package', + and `Catharon Code' refer to the set of files originally + distributed by Catharon Productions, Inc. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using one of the + Catharon Packages'. + + This license applies to all files distributed in the original + Catharon Package(s), including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The Catharon Packages are copyright (C) 2000 by Catharon + Productions, Inc. All rights reserved except as specified below. + +1. No Warranty +-------------- + + THE CATHARON PACKAGES ARE PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OF OR THE INABILITY TO + USE THE CATHARON PACKAGE. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the Catharon Packages (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`license.txt') unaltered; any additions, deletions or changes + to the original files must be clearly indicated in + accompanying documentation. The copyright notices of the + unaltered, original files must be preserved in all copies of + source files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part on the work of + Catharon Productions, Inc. in the distribution documentation. + + These conditions apply to any software derived from or based on + the Catharon Packages, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither Catharon Productions, Inc. and contributors nor you shall + use the name of the other for commercial, advertising, or + promotional purposes without specific prior written permission. + + We suggest, but do not require, that you use the following phrase + to refer to this software in your documentation: 'this software is + based in part on the Catharon Typography Project'. + + As you have not signed this license, you are not required to + accept it. However, as the Catharon Packages are copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the Catharon + Packages, you indicate that you understand and accept all the + terms of this license. + +--- end of license.txt --- diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahangles.c b/reactos/subsys/win32k/freetype/src/autohint/ahangles.c new file mode 100644 index 00000000000..2f759edd5c9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahangles.c @@ -0,0 +1,137 @@ +/***************************************************************************/ +/* */ +/* ahangles.h */ +/* */ +/* A routine used to compute vector angles with limited accuracy */ +/* and very high speed (body). */ +/* */ +/* Copyright 2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahangles.h" + +#else + +#include + +#endif + + + /* 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 + }; + + + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/src/autohint/ahangles.h b/reactos/subsys/win32k/freetype/src/autohint/ahangles.h new file mode 100644 index 00000000000..4eb36bf4d21 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahangles.h @@ -0,0 +1,63 @@ +/***************************************************************************/ +/* */ +/* ahangles.h */ +/* */ +/* A routine used to compute vector angles with limited accuracy */ +/* and very high speed (specification). */ +/* */ +/* Copyright 2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + +#include + + + /* 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]; + + + LOCAL_DEF + AH_Angle ah_angle( FT_Vector* v ); + + +#endif /* AHANGLES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahglobal.c b/reactos/subsys/win32k/freetype/src/autohint/ahglobal.c new file mode 100644 index 00000000000..892ca861748 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahglobal.c @@ -0,0 +1,402 @@ +/***************************************************************************/ +/* */ +/* ahglobal.c */ +/* */ +/* Routines used to compute global metrics automatically (body). */ +/* */ +/* Copyright 2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahglobal.h" +#include "ahglyph.h" + +#else + +#include +#include + +#endif + + +#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 > 1; 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 = 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_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 = ( 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; + } + + + LOCAL_FUNC + FT_Error ah_hinter_compute_globals( AH_Hinter* hinter ) + { + return ah_hinter_compute_widths( hinter ) || + ah_hinter_compute_blues ( hinter ); + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahglobal.h b/reactos/subsys/win32k/freetype/src/autohint/ahglobal.h new file mode 100644 index 00000000000..79e73586f98 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahglobal.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ahglobal.h */ +/* */ +/* Routines used to compute global metrics automatically */ +/* (specification). */ +/* */ +/* Copyright 2000 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 + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + +#include /* for LOCAL_DEF/LOCAL_FUNC */ + + +#define AH_IS_TOP_BLUE( b ) ( (b) == ah_blue_capital_top || \ + (b) == ah_blue_small_top ) + + + /* compute global metrics automatically */ + LOCAL_DEF + FT_Error ah_hinter_compute_globals( AH_Hinter* hinter ); + + +#endif /* AHGLOBAL_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahglyph.c b/reactos/subsys/win32k/freetype/src/autohint/ahglyph.c new file mode 100644 index 00000000000..348ee8e32d5 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahglyph.c @@ -0,0 +1,1299 @@ +/***************************************************************************/ +/* */ +/* ahglyph.c */ +/* */ +/* Routines used to load and analyze a given glyph before hinting */ +/* (body). */ +/* */ +/* Copyright 2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahglyph.h" +#include "ahangles.h" +#include "ahglobal.h" + +#else + +#include +#include +#include + +#endif + + +#include + + +#define xxxAH_DEBUG_GLYPH + + + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_new */ + /* */ + /* */ + /* Creates a new and empty AH_Outline object. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_done */ + /* */ + /* */ + /* Destroys a given AH_Outline object. */ + /* */ + LOCAL_FUNC + 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_save */ + /* */ + /* */ + /* Saves the content of a given AH_Outline object into a face's glyph */ + /* slot. */ + /* */ + LOCAL_FUNC + void ah_outline_save( AH_Outline* outline, + AH_Loader* gloader ) + { + AH_Point* point = outline->points; + AH_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 < 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_load */ + /* */ + /* */ + /* Loads an unscaled outline from a glyph slot into an AH_Outline */ + /* object. */ + /* */ + LOCAL_FUNC + FT_Error ah_outline_load( AH_Outline* outline, + FT_Face face ) + { + FT_Memory memory = outline->memory; + FT_Error error = FT_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 FT_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, realloc the points, segments & edges arrays if needed */ + if ( num_points > outline->max_points ) + { + FT_Int news = ( num_points + 7 ) & -8; + FT_Int max = outline->max_points; + + + if ( REALLOC_ARRAY( outline->points, max, news, AH_Point ) || + REALLOC_ARRAY( outline->horz_edges, max, news, AH_Edge ) || + REALLOC_ARRAY( outline->horz_segments, max, news, AH_Segment ) ) + goto Exit; + + /* readjust some pointers */ + outline->vert_edges = outline->horz_edges + ( news >> 1 ); + outline->vert_segments = outline->horz_segments + ( news >> 1 ); + 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; + + /* Compute the vertical and horizontal major directions; this is */ + /* currently done by inspecting the `ft_outline_reverse_fill' flag. */ + /* However, some fonts have improper glyphs, and it'd be a good idea */ + /* to be able to re-compute these values on the fly. */ + outline->vert_major_dir = ah_dir_up; + outline->horz_major_dir = ah_dir_left; + + if ( source->flags & ft_outline_reverse_fill ) + { + 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; + + { + /* do one thing at a time -- it is easier to understand, and */ + /* the code is clearer */ + AH_Point* point = points; + AH_Point* limit = point + 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 < 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 < 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 < limit; point++ ) + { + point->prev = prev; + if ( point < end ) + { + point->next = point + 1; + prev = point; + } + else + { + point->next = first; + contour_index++; + if ( point + 1 < limit ) + { + end = points + source->contours[contour_index]; + first = point + 1; + prev = end; + } + } + } + } + + /* set-up the contours array */ + { + AH_Point** contour = outline->contours; + AH_Point** limit = contour + outline->num_contours; + short* end = source->contours; + short index = 0; + + + for ( ; contour < limit; contour++, end++ ) + { + contour[0] = points + index; + index = end[0] + 1; + } + } + + /* compute directions of in & out vectors */ + { + for ( point = points; 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; + } + + + LOCAL_FUNC + void ah_setup_uv( AH_Outline* outline, + AH_UV source ) + { + AH_Point* point = outline->points; + AH_Point* limit = point + outline->num_points; + + + for ( ; 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; + } + } + + + LOCAL_FUNC + 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; + + if ( point == max_point ) + max_point = 0; + + if ( point == min_point ) + min_point = 0; + } + + 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* limit = point + outline->num_points; + + AH_Point* min_point = 0; + AH_Point* max_point = 0; + FT_Pos min_pos = 32000; + FT_Pos max_pos = -32000; + + + /* compute minimum and maximum points */ + for ( ; 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 ); + } + } + + + LOCAL_FUNC + void ah_outline_link_segments( AH_Outline* outline ) + { + AH_Segment* segments; + AH_Segment* limit; + int dimension; + + + ah_setup_uv( outline, ah_uv_fyx ); + + segments = outline->horz_segments; + 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 < 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 < 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 = ( seg1->dir == outline->horz_major_dir || + seg1->dir == outline->vert_major_dir ); + is_pos = 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 < 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; + limit = segments + outline->num_vsegments; + } + } + + +#ifdef AH_DEBUG_GLYPH + + /* A function used to dump the array of linked segments */ + void ah_dump_segments( AH_Outline* outline ) + { + AH_Segment* segments; + AH_Segment* limit; + AH_Point* points; + FT_Int dimension; + + + points = outline->points; + segments = outline->horz_segments; + 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 < 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; + limit = segments + outline->num_vsegments; + } + } + +#endif /* AH_DEBUG_GLYPH */ + + + 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 = 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 = 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_straight == 0 && is_round ) + 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_detect_features */ + /* */ + /* */ + /* Performs feature detection on a given AH_Outline object. */ + /* */ + LOCAL_FUNC + void ah_outline_detect_features( AH_Outline* outline ) + { + ah_outline_compute_segments( outline ); + ah_outline_link_segments ( outline ); + ah_outline_compute_edges ( outline ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_compute_blue_edges */ + /* */ + /* */ + /* Computes the `blue edges' in a given outline (i.e. those that must */ + /* be snapped to a blue zone edge (top or bottom). */ + /* */ + LOCAL_FUNC + void ah_outline_compute_blue_edges( AH_Outline* outline, + AH_Face_Globals* face_globals ) + { + AH_Edge* edge = outline->horz_edges; + AH_Edge* limit = edge + outline->num_hedges; + AH_Globals* globals = &face_globals->design; + FT_Fixed y_scale = outline->y_scale; + + + /* compute for each horizontal edge, which blue zone is closer */ + for ( ; 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 = AH_IS_TOP_BLUE( blue ); + FT_Bool is_major_dir = edge->dir == outline->horz_major_dir; + + + /* 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 = 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_scale_blue_edges */ + /* */ + /* */ + /* 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'). */ + /* */ + LOCAL_FUNC + void ah_outline_scale_blue_edges( AH_Outline* outline, + AH_Face_Globals* globals ) + { + AH_Edge* edge = outline->horz_edges; + AH_Edge* limit = edge + outline->num_hedges; + FT_Int delta; + + + delta = globals->scaled.blue_refs - globals->design.blue_refs; + + for ( ; edge < limit; edge++ ) + { + if ( edge->blue_edge ) + edge->blue_edge += delta; + } + } + + +#ifdef AH_DEBUG_GLYPH + + void ah_dump_edges( AH_Outline* outline ) + { + AH_Edge* edges; + AH_Edge* limit; + AH_Segment* segments; + FT_Int dimension; + + + edges = outline->horz_edges; + 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 < 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; + limit = edges + outline->num_vedges; + segments = outline->vert_segments; + } + } + +#endif /* AH_DEBUG_GLYPH */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahglyph.h b/reactos/subsys/win32k/freetype/src/autohint/ahglyph.h new file mode 100644 index 00000000000..66fd5e31551 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahglyph.h @@ -0,0 +1,93 @@ +/***************************************************************************/ +/* */ +/* ahglyph.h */ +/* */ +/* Routines used to load and analyze a given glyph before hinting */ +/* (specification). */ +/* */ +/* Copyright 2000 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 + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + + 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; + + + LOCAL_DEF + void ah_setup_uv( AH_Outline* outline, + AH_UV source ); + + + /* AH_Outline functions - they should be typically called in this order */ + + LOCAL_DEF + FT_Error ah_outline_new( FT_Memory memory, + AH_Outline** aoutline ); + + LOCAL_DEF + FT_Error ah_outline_load( AH_Outline* outline, + FT_Face face ); + + LOCAL_DEF + void ah_outline_compute_segments( AH_Outline* outline ); + + LOCAL_DEF + void ah_outline_link_segments( AH_Outline* outline ); + + LOCAL_DEF + void ah_outline_detect_features( AH_Outline* outline ); + + LOCAL_DEF + void ah_outline_compute_blue_edges( AH_Outline* outline, + AH_Face_Globals* globals ); + + LOCAL_DEF + void ah_outline_scale_blue_edges( AH_Outline* outline, + AH_Face_Globals* globals ); + + LOCAL_DEF + void ah_outline_save( AH_Outline* outline, AH_Loader* loader ); + + LOCAL_DEF + void ah_outline_done( AH_Outline* outline ); + + +#endif /* AHGLYPH_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahhint.c b/reactos/subsys/win32k/freetype/src/autohint/ahhint.c new file mode 100644 index 00000000000..f50f8839de4 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahhint.c @@ -0,0 +1,1398 @@ +/***************************************************************************/ +/* */ +/* ahhint.c */ +/* */ +/* Glyph hinter (body). */ +/* */ +/* Copyright 2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahhint.h" +#include "ahglyph.h" +#include "ahangles.h" + +#else + +#include +#include +#include + +#endif + +#include + + +#define FACE_GLOBALS( face ) ((AH_Face_Globals*)(face)->autohint.data) + +#define AH_USE_IUP + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** Hinting routines ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + static int disable_horz_edges = 0; + static int disable_vert_edges = 0; + + + /* 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* before = 0; + AH_Edge* after = 0; + AH_Edge* anchor = 0; + int has_serifs = 0; + + + if ( disable_vert_edges && !dimension ) + goto Next_Dimension; + + if ( 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.. */ + before = 0; + after = 0; + 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; + } + } + + + LOCAL_FUNC + void ah_hinter_hint_edges( AH_Hinter* hinter, + int no_horz_edges, + int no_vert_edges ) + { + disable_horz_edges = no_horz_edges; + 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; + AH_Edge* before; + AH_Edge* after; + + + before = 0; + after = 0; + + 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; + AH_Edge* before; + AH_Edge* after; + + + before = 0; + after = 0; + + 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++ ) + { + FT_Pos 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_Edge* edges; + AH_Edge* edge_limit; + 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 */ + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + 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 */ + + + LOCAL_FUNC + 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 */ + 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_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_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 */ + 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_Fixed x_scale = face->size->metrics.x_scale; + FT_Fixed y_scale = face->size->metrics.y_scale; + FT_Glyph_Metrics metrics; /* temporary metrics */ + FT_Error error; + AH_Outline* outline = hinter->glyph; + AH_Loader* gloader = hinter->loader; + FT_Bool no_horz_hints = + ( load_flags & AH_HINT_NO_HORZ_EDGES ) != 0; + FT_Bool no_vert_hints = + ( load_flags & AH_HINT_NO_VERT_EDGES ) != 0; + + + /* load the glyph */ + error = FT_Load_Glyph( face, glyph_index, load_flags ); + if ( error ) + goto Exit; + + /* save current glyph metrics */ + metrics = slot->metrics; + + switch ( slot->format ) + { + case ft_glyph_format_outline: + /* first of all, 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_width, new_width; + FT_Pos old_advance, new_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_width = edge2->opos - edge1->opos; + new_width = edge2->pos - edge1->pos; + + old_advance = hinter->pp2.x; + old_lsb = edge1->opos; + new_lsb = edge1->pos; + + new_advance = old_advance + + ( new_width + new_lsb - old_width - old_lsb ); + + 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, start_contour; + FT_SubGlyph* subglyph; + + + start_point = gloader->base.outline.n_points; + start_contour = gloader->base.outline.n_contours; + + /* 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 = FT_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 = num_new_points; + + FT_Outline_Translate( &dummy, x, y ); + } + } + } + break; + + default: + /* we don't support other formats (yet?) */ + error = FT_Err_Unimplemented_Feature; + } + + Hint_Metrics: + if ( depth == 0 ) + { + FT_BBox bbox; + + + /* 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->loader ); + error = ah_loader_copy_points( slot->loader, gloader ); + if ( error ) + goto Exit; + + slot->outline = slot->loader->base.outline; + slot->format = ft_glyph_format_outline; + } + + Exit: + return error; + } + + + /* load and hint a given glyph */ + 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 ); + + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE; + + ah_loader_rewind( hinter->loader ); + + error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); + + Exit: + return error; + } + + + /* retrieve a face's autohint globals for client applications */ + 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; + } + + + void ah_hinter_done_global_hints( AH_Hinter* hinter, + void* global_hints ) + { + FT_Memory memory = hinter->memory; + + + FREE( global_hints ); + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahhint.h b/reactos/subsys/win32k/freetype/src/autohint/ahhint.h new file mode 100644 index 00000000000..bb297fb80f1 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahhint.h @@ -0,0 +1,72 @@ +/***************************************************************************/ +/* */ +/* ahhint.h */ +/* */ +/* Glyph hinter (declaration). */ +/* */ +/* Copyright 2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ahglobal.h" + +#else + +#include + +#endif + + +#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_Error ah_hinter_new( FT_Library library, + AH_Hinter** ahinter ); + + /* Load a hinted glyph in the hinter */ + 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 */ + void ah_hinter_done( AH_Hinter* hinter ); + + LOCAL_DEF + void ah_hinter_done_face_globals( AH_Face_Globals* globals ); + + void ah_hinter_get_global_hints( AH_Hinter* hinter, + FT_Face face, + void** global_hints, + long* global_len ); + + void ah_hinter_done_global_hints( AH_Hinter* hinter, + void* global_hints ); + + +#endif /* AHHINT_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahloader.h b/reactos/subsys/win32k/freetype/src/autohint/ahloader.h new file mode 100644 index 00000000000..4a8563c0aab --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahloader.h @@ -0,0 +1,124 @@ +/***************************************************************************/ +/* */ +/* ahloader.h */ +/* */ +/* Glyph loader for the auto-hinting module (declaration only). */ +/* */ +/* Copyright 2000 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 + + +#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 */ + }; + + + LOCAL_DEF + FT_Error AH_GlyphLoader_New( FT_Memory memory, + AH_GlyphLoader** aloader ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Create_Extra( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Done( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Reset( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Rewind( AH_GlyphLoader* loader ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Check_Points( AH_GlyphLoader* loader, + FT_UInt n_points, + FT_UInt n_contours ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Check_Subglyphs( AH_GlyphLoader* loader, + FT_UInt n_subs ); + + LOCAL_DEF + void AH_GlyphLoader_Prepare( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Add( AH_GlyphLoader* loader ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Copy_Points( AH_GlyphLoader* target, + FT_GlyphLoader* source ); + +#else /* _STANDALONE */ + +#include + + #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_ */ + +#endif /* AHLOADER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahmodule.c b/reactos/subsys/win32k/freetype/src/autohint/ahmodule.c new file mode 100644 index 00000000000..85755681ee7 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahmodule.c @@ -0,0 +1,127 @@ +/***************************************************************************/ +/* */ +/* ahmodule.c */ +/* */ +/* Auto-hinting module implementation (declaration). */ +/* */ +/* Copyright 2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ahhint.h" + +#else + +#include + +#endif + + + typedef struct FT_AutoHinterRec_ + { + FT_ModuleRec root; + AH_Hinter* hinter; + + } FT_AutoHinterRec; + + + static + FT_Error ft_autohinter_init( FT_AutoHinter module ) + { + return ah_hinter_new( module->root.library, &module->hinter ); + } + + + static + void ft_autohinter_done( FT_AutoHinter module ) + { + ah_hinter_done( module->hinter ); + } + + + static + 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 ); + } + + + static + 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) ); + } + + + static + 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 ); + } + + + static + void ft_autohinter_done_globals( FT_AutoHinter module, + void* global_hints ) + { + ah_hinter_done_global_hints( module->hinter, global_hints ); + } + + + static + const FT_AutoHinter_Interface autohinter_interface = + { + ft_autohinter_reset, + ft_autohinter_load, + ft_autohinter_get_globals, + ft_autohinter_done_globals + }; + + + 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/reactos/subsys/win32k/freetype/src/autohint/ahmodule.h b/reactos/subsys/win32k/freetype/src/autohint/ahmodule.h new file mode 100644 index 00000000000..28b07538bcf --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahmodule.h @@ -0,0 +1,32 @@ +/***************************************************************************/ +/* */ +/* ahmodule.h */ +/* */ +/* Auto-hinting module (declaration). */ +/* */ +/* Copyright 2000 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 + + FT_EXPORT_VAR( const FT_Module_Class ) autohint_module_class; + +#endif /* AHMODULE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahoptim.c b/reactos/subsys/win32k/freetype/src/autohint/ahoptim.c new file mode 100644 index 00000000000..d1d684132b9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahoptim.c @@ -0,0 +1,889 @@ +/***************************************************************************/ +/* */ +/* ahoptim.c */ +/* */ +/* FreeType auto hinting outline optimization (body). */ +/* */ +/* Copyright 2000 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 /* for ALLOC_ARRAY() and FREE() */ + + +#ifdef FT_FLAT_COMPILE + +#include "ahoptim.h" + +#else + +#include + +#endif + + + /* 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 +#include +#include + +#define FLOAT( x ) ( (float)( (x) / 64.0 ) ) + + static + void optim_log( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); +/* vprintf( fmt, ap ); FIXME */ + 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/reactos/subsys/win32k/freetype/src/autohint/ahoptim.h b/reactos/subsys/win32k/freetype/src/autohint/ahoptim.h new file mode 100644 index 00000000000..a1f52bf68ff --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahoptim.h @@ -0,0 +1,136 @@ +/***************************************************************************/ +/* */ +/* ahoptim.h */ +/* */ +/* FreeType auto hinting outline optimization (declaration). */ +/* */ +/* Copyright 2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + + /* 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 ); + + +#endif /* AHOPTIM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/ahtypes.h b/reactos/subsys/win32k/freetype/src/autohint/ahtypes.h new file mode 100644 index 00000000000..3372ea9af6a --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/ahtypes.h @@ -0,0 +1,492 @@ +/***************************************************************************/ +/* */ +/* ahtypes.h */ +/* */ +/* General types and definitions for the auto-hint module */ +/* (specification only). */ +/* */ +/* Copyright 2000 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 /* for freetype.h + LOCAL_DEF etc. */ + + +#ifdef FT_FLAT_COMPILE + +#include "ahloader.h" + +#else + +#include + +#endif + + +#define xxAH_DEBUG + + +#ifdef AH_DEBUG + +#include + +#define AH_LOG( x ) printf##x + +#else + +#define AH_LOG( x ) do ; while ( 0 ) /* nothing */ + +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** 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; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Point */ + /* */ + /* */ + /* A structure used to model an outline point to the AH_Outline type. */ + /* */ + /* */ + /* 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 */ + }; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Segment */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Edge */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Globals */ + /* */ + /* */ + /* Holds the global metrics for a given font face (be it in design */ + /* units or scaled pixel values). */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Face_Globals */ + /* */ + /* */ + /* Holds the complete global metrics for a given font face (i.e., the */ + /* design units version + a scaled version + the current scales */ + /* used). */ + /* */ + /* */ + /* 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; + + } AH_Hinter; + + +#endif /* AHTYPES_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/autohint.c b/reactos/subsys/win32k/freetype/src/autohint/autohint.c new file mode 100644 index 00000000000..5916b633026 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/autohint.c @@ -0,0 +1,43 @@ +/***************************************************************************/ +/* */ +/* autohint.c */ +/* */ +/* Automatic Hinting wrapper (body only). */ +/* */ +/* Copyright 2000 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 + +#ifdef FT_FLAT_COMPILE + +#include "ahangles.c" +#include "ahglyph.c" +#include "ahglobal.c" +#include "ahhint.c" +#include "ahmodule.c" + +#else + +#include +#include +#include +#include +#include + +#endif + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/autohint/mather.py b/reactos/subsys/win32k/freetype/src/autohint/mather.py new file mode 100644 index 00000000000..b416fdfcb69 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/mather.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# + +# +# autohint math table builder +# + + +# Copyright 1996-2000 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. + + +import math + +ag_pi = 256 + +def print_arctan( atan_bits ): + atan_base = 1 << atan_bits + + print " static AH_Angle ag_arctan[1L << AG_ATAN_BITS] =" + print " {" + + count = 0 + line = " " + + for n in range( atan_base ): + comma = "," + if ( n == atan_base - 1 ): + comma = "" + + angle = math.atan( n * 1.0 / atan_base ) / math.pi * ag_pi + line = line + " " + repr( int( angle + 0.5 ) ) + comma + count = count + 1; + if ( count == 8 ): + count = 0 + print line + line = " " + + if ( count > 0 ): + print line + print " };" + + +# This routine is not used currently. +# +def print_sines(): + print " static FT_Fixed ah_sines[AG_HALF_PI + 1] =" + print " {" + + count = 0 + line = " " + + for n in range( ag_pi / 2 ): + sinus = math.sin( n * math.pi / ag_pi ) + line = line + " " + repr( int( 65536.0 * sinus ) ) + "," + count = count + 1 + if ( count == 8 ): + count = 0 + print line + line = " " + + if ( count > 0 ): + print line + print " 65536" + print " };" + + +print_arctan( 8 ) +print + + +# END diff --git a/reactos/subsys/win32k/freetype/src/autohint/module.mk b/reactos/subsys/win32k/freetype/src/autohint/module.mk new file mode 100644 index 00000000000..71e5ee3524a --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_autohint_module + +add_autohint_module: + $(OPEN_DRIVER)autohint_module_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)autohint $(ECHO_DRIVER_DESC)automatic hinting module$(ECHO_DRIVER_DONE) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/autohint/rules.mk b/reactos/subsys/win32k/freetype/src/autohint/rules.mk new file mode 100644 index 00000000000..87f7849adcd --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/autohint/rules.mk @@ -0,0 +1,77 @@ +# +# FreeType 2 auto-hinter module configuration rules +# + + +# Copyright 2000 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. + + +# AUTO driver directory +# +AUTO_DIR := $(SRC_)autohint +AUTO_DIR_ := $(AUTO_DIR)$(SEP) + + +# compilation flags for the driver +# +AUTO_COMPILE := $(FT_COMPILE) + + +# AUTO driver sources (i.e., C files) +# +AUTO_DRV_SRC := $(AUTO_DIR_)ahangles.c \ + $(AUTO_DIR_)ahglobal.c \ + $(AUTO_DIR_)ahglyph.c \ + $(AUTO_DIR_)ahhint.c \ + $(AUTO_DIR_)ahmodule.c + +# AUTO driver headers +# +AUTO_DRV_H := $(AUTO_DRV_SRC:%c=%h) \ + $(AUTO_DIR_)ahloader.h \ + $(AUTO_DIR_)ahtypes.h + + +# AUTO driver object(s) +# +# AUTO_DRV_OBJ_M is used during `multi' builds. +# AUTO_DRV_OBJ_S is used during `single' builds. +# +AUTO_DRV_OBJ_M := $(AUTO_DRV_SRC:$(AUTO_DIR_)%.c=$(OBJ_)%.$O) +AUTO_DRV_OBJ_S := $(OBJ_)autohint.$O + +# AUTO driver source file for single build +# +AUTO_DRV_SRC_S := $(AUTO_DIR_)autohint.c + + +# AUTO driver - single object +# +$(AUTO_DRV_OBJ_S): $(AUTO_DRV_SRC_S) $(AUTO_DRV_SRC) \ + $(FREETYPE_H) $(AUTO_DRV_H) + $(AUTO_COMPILE) $T$@ $(AUTO_DRV_SRC_S) + + +# AUTO driver - multiple objects +# +$(OBJ_)%.$O: $(AUTO_DIR_)%.c $(FREETYPE_H) $(AUTO_DRV_H) + $(AUTO_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(AUTO_DRV_OBJ_S) +DRV_OBJS_M += $(AUTO_DRV_OBJ_M) + + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/base/ftbase.c b/reactos/subsys/win32k/freetype/src/base/ftbase.c new file mode 100644 index 00000000000..a110af42b44 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftbase.c @@ -0,0 +1,42 @@ +/***************************************************************************/ +/* */ +/* ftbase.c */ +/* */ +/* Single object library component (body only). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ftcalc.c" +#include "ftobjs.c" +#include "ftstream.c" +#include "ftlist.c" +#include "ftoutln.c" +#include "ftextend.c" +#include "ftnames.c" + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include +#include +#include +#include +#include + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/base/ftcalc.c b/reactos/subsys/win32k/freetype/src/base/ftcalc.c new file mode 100644 index 00000000000..d27de265246 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftcalc.c @@ -0,0 +1,773 @@ +/***************************************************************************/ +/* */ +/* ftcalc.c */ +/* */ +/* Arithmetic computations (body). */ +/* */ +/* Copyright 1996-2000 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(), and FT_DivFix() are declared in freetype.h. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include /* for ABS() */ + + + /*************************************************************************/ + /* */ + /* 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 + + +#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 + + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt32 */ + /* */ + /* */ + /* Computes the square root of an Int32 integer (which will be */ + /* handled as an unsigned long value). */ + /* */ + /* */ + /* x :: The value to compute the root for. */ + /* */ + /* */ + /* The result of `sqrt(x)'. */ + /* */ + FT_EXPORT_FUNC( 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 + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* */ + /* 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_FUNC( FT_Long ) FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ) + { + FT_Int s; + + + s = 1; + if ( a < 0 ) { a = -a; s = -s; } + if ( b < 0 ) { b = -b; s = -s; } + if ( c < 0 ) { c = -c; s = -s; } + + return s * ( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c + : 0x7FFFFFFFL ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* */ + /* 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_FUNC( FT_Long ) FT_MulFix( FT_Long a, + FT_Long b ) + { + FT_Int s; + + + s = 1; + if ( a < 0 ) { a = -a; s = -s; } + if ( b < 0 ) { b = -b; s = -s; } + + return s * (FT_Long)( ( (FT_Int64)a * b + 0x8000 ) >> 16 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DivFix */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* */ + /* 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_FUNC( 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 + /* compute result directly */ + q = ( (FT_Int64)a << 16 ) / b; + + return (FT_Int32)( s < 0 ? -q : 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt64 */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* l :: A 64-bit integer. */ + /* */ + /* */ + /* The 32-bit square-root. */ + /* */ + FT_EXPORT_FUNC( 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 r; + } + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + +#else /* FT_LONG64 */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* */ + /* 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'. */ + /* */ + /* */ + /* The FT_MulDiv() function has been optimized thanks to ideas from */ + /* Graham Asher. The trick is to optimize computation if everything */ + /* fits within 32 bits (a rather common case). */ + /* */ + /* We compute `a*b+c/2', then divide it by `c' (positive values). */ + /* */ + /* 46340 is FLOOR(SQRT(2^31-1)). */ + /* */ + /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */ + /* */ + /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */ + /* */ + /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */ + /* */ + /* and 2*0x157F0 = 176096. */ + /* */ + FT_EXPORT_FUNC( 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 <= 46340 && b <= 46340 && 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 = (FT_Int32)( c >> 31 ); + temp2.lo = (FT_UInt32)( c / 2 ); + FT_Add64( &temp, &temp2, &temp ); + a = FT_Div64by32( &temp, c ); + } + else + a = 0x7FFFFFFFL; + + return ( s < 0 ? -a : a ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* */ + /* The optimization for FT_MulFix() is different. We could simply be */ + /* happy by applying the same principles as with FT_MulDiv(), because */ + /* */ + /* c = 0x10000 < 176096 */ + /* */ + /* However, in most cases, we have a `b' with a value around 0x10000 */ + /* which is greater than 46340. */ + /* */ + /* According to some testing, most cases have `a' < 2048, so a good */ + /* idea is to use bounds like 2048 and 1048576 (=floor((2^31-1)/2048) */ + /* for `a' and `b', respectively. */ + /* */ + FT_EXPORT_FUNC( 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 ) >> 16 ); + } + + return ( s < 0 ? -(FT_Long)ua : ua ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DivFix */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* */ + /* The optimization for FT_DivFix() is simple: If (a << 16) fits into */ + /* 32 bits, then the division is computed directly. Otherwise, we */ + /* use a specialized version of the old FT_MulDiv64(). */ + /* */ + FT_EXPORT_FUNC( 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 ) / (FT_UInt32)b; + } + else + { + /* we need more bits; we have to do it by hand */ + FT_UInt32 c; + + + q = ( a / b ) << 16; + c = a % b; + + /* we must compute C*0x10000/B: we simply shift C and B so */ + /* C becomes smaller than 16 bits */ + while ( c >> 16 ) + { + c >>= 1; + b <<= 1; + } + + q += ( c << 16 ) / b; + } + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add64 */ + /* */ + /* */ + /* Add two Int64 values. */ + /* */ + /* */ + /* x :: A pointer to the first value to be added. */ + /* y :: A pointer to the second value to be added. */ + /* */ + /* */ + /* z :: A pointer to the result of `x + y'. */ + /* */ + /* */ + /* Will be wrapped by the ADD_64() macro. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Add64( FT_Int64* x, + FT_Int64* y, + FT_Int64* z ) + { + register FT_UInt32 lo, hi; + + + lo = x->lo + y->lo; + hi = x->hi + y->hi + ( lo < x->lo ); + + z->lo = lo; + z->hi = hi; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulTo64 */ + /* */ + /* */ + /* Multiplies two Int32 integers. Returns an Int64 integer. */ + /* */ + /* */ + /* x :: The first multiplier. */ + /* y :: The second multiplier. */ + /* */ + /* */ + /* z :: A pointer to the result of `x * y'. */ + /* */ + /* */ + /* Will be wrapped by the MUL_64() macro. */ + /* */ + FT_EXPORT_FUNC( 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_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2; + + + lo1 = x & 0x0000FFFF; hi1 = x >> 16; + lo2 = y & 0x0000FFFF; hi2 = y >> 16; + + lo = lo1 * lo2; + i1 = lo1 * hi2; + i2 = lo2 * hi1; + hi = hi1 * hi2; + + /* Check carry overflow of i1 + i2 */ + i1 += i2; + if ( i1 < i2 ) + hi += 1L << 16; + + hi += i1 >> 16; + i1 = i1 << 16; + + /* Check carry overflow of i1 + lo */ + lo += i1; + hi += ( lo < i1 ); + + z->lo = lo; + z->hi = hi; + } + + if ( s < 0 ) + { + z->lo = (FT_UInt32)-(FT_Int32)z->lo; + z->hi = ~z->hi + !( z->lo ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Div64by32 */ + /* */ + /* */ + /* Divides an Int64 value by an Int32 value. Returns an Int32 */ + /* integer. */ + /* */ + /* */ + /* x :: A pointer to the dividend. */ + /* y :: The divisor. */ + /* */ + /* */ + /* The result of `x / y'. */ + /* */ + /* */ + /* Will be wrapped by the DIV_64() macro. */ + /* */ + FT_EXPORT_FUNC( FT_Int32 ) FT_Div64by32( FT_Int64* x, + FT_Int32 y ) + { + FT_Int32 s; + FT_UInt32 q, r, i, lo; + + + 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; + else + q = 0x7FFFFFFFL; + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + + r = x->hi; + lo = x->lo; + + if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */ + return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL ); + /* Return Max/Min Int32 if division overflow. */ + /* This includes division by zero! */ + q = 0; + for ( i = 0; i < 32; i++ ) + { + r <<= 1; + q <<= 1; + r |= lo >> 31; + + if ( r >= (FT_UInt32)y ) + { + r -= y; + q |= 1; + } + lo <<= 1; + } + + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt64 */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* z :: A pointer to a 64-bit integer. */ + /* */ + /* */ + /* The 32-bit square-root. */ + /* */ + FT_EXPORT_FUNC( 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 */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/base/ftdebug.c b/reactos/subsys/win32k/freetype/src/base/ftdebug.c new file mode 100644 index 00000000000..da8b3b4aa3b --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftdebug.c @@ -0,0 +1,124 @@ +/***************************************************************************/ +/* */ +/* ftdebug.c */ +/* */ +/* Debugging and logging component (body). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef FT_DEBUG_LEVEL_TRACE + char ft_trace_levels[trace_max]; +#endif + + +#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE ) + + +#include +#include +#include + + + FT_EXPORT_FUNC( void ) FT_Message( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); +/* vprintf( fmt, ap ); FIXME */ + va_end( ap ); + } + + + FT_EXPORT_FUNC( void ) FT_Panic( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); +/* vprintf( fmt, ap ); FIXME */ + va_end( ap ); + +/* exit( EXIT_FAILURE ); FIXME */ + } + + +#ifdef FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* */ + /* FT_SetTraceLevel */ + /* */ + /* */ + /* Sets the trace level for debugging. */ + /* */ + /* */ + /* component :: The component which should be traced. See ftdebug.h */ + /* for a complete list. If set to `trace_any', all */ + /* components will be traced. */ + /* level :: The tracing level. */ + /* */ + FT_EXPORT_FUNC( 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 */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/base/ftextend.c b/reactos/subsys/win32k/freetype/src/base/ftextend.c new file mode 100644 index 00000000000..f298b19a8aa --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftextend.c @@ -0,0 +1,332 @@ +/***************************************************************************/ +/* */ +/* ftextend.h */ +/* */ +/* FreeType extensions implementation (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + + /*************************************************************************/ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Init_Extensions */ + /* */ + /* */ + /* Initializes the extension component. */ + /* */ + /* */ + /* driver :: A handle to the driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Extensions */ + /* */ + /* */ + /* Finalizes the extension component. */ + /* */ + /* */ + /* driver :: A handle to the driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error FT_Done_Extensions( FT_Driver driver ) + { + FT_Memory memory = driver->root.memory; + + + FREE( driver->extensions ); + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Register_Extension */ + /* */ + /* */ + /* Registers a new extension. */ + /* */ + /* */ + /* driver :: A handle to the driver object. */ + /* class :: A pointer to a class describing the extension. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Extension */ + /* */ + /* */ + /* Queries an extension block by an extension ID string. */ + /* */ + /* */ + /* face :: A handle to the face object. */ + /* extension_id :: An ID string identifying the extension. */ + /* */ + /* */ + /* extension_interface :: A generic pointer, usually pointing to a */ + /* table of functions implementing the */ + /* extension interface. */ + /* */ + /* */ + /* A generic pointer to the extension block. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Destroy_Extensions */ + /* */ + /* */ + /* Destroys all extensions within a face object. */ + /* */ + /* */ + /* face :: A handle to the face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Called by the face object destructor. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Create_Extensions */ + /* */ + /* */ + /* Creates an extension object within a face object for all */ + /* registered extensions. */ + /* */ + /* */ + /* face :: A handle to the face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Called by the face object constructor. */ + /* */ + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/src/base/ftglyph.c b/reactos/subsys/win32k/freetype/src/base/ftglyph.c new file mode 100644 index 00000000000..4052e6e4f88 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftglyph.c @@ -0,0 +1,1184 @@ +/***************************************************************************/ +/* */ +/* ftglyph.c */ +/* */ +/* FreeType convenience functions to handle glyphs (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + + /*************************************************************************/ + /* */ + /* 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 ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Multiply */ + /* */ + /* */ + /* Performs the matrix operation `b = a*b'. */ + /* */ + /* */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `a' or `b' is zero. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Invert */ + /* */ + /* */ + /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */ + /* */ + /* */ + /* matrix :: A pointer to the target matrix. Remains untouched in */ + /* case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_FUNC( 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( source->buffer, target->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->xMax - ( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Copy */ + /* */ + /* */ + /* A function used to copy a glyph image. */ + /* */ + /* */ + /* source :: A handle to the source glyph object. */ + /* */ + /* */ + /* target :: A handle to the target glyph object. 0 in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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, © ); + if ( error ) + goto Exit; + + if ( clazz->glyph_copy ) + error = clazz->glyph_copy( source, copy ); + + if ( error ) + FT_Done_Glyph( copy ); + else + *target = copy; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph */ + /* */ + /* */ + /* A function used to extract a glyph image from a slot. */ + /* */ + /* */ + /* slot :: A handle to the source glyph slot. */ + /* */ + /* */ + /* aglyph :: A handle to the glyph object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Transform */ + /* */ + /* */ + /* Transforms a glyph image if its format is scalable. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code (the glyph format is not scalable if it is */ + /* not zero). */ + /* */ + /* */ + /* The 2x2 transformation matrix is also applied to the glyph's */ + /* advance vector. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Get_CBox */ + /* */ + /* */ + /* Returns the glyph image's bounding box. */ + /* */ + /* */ + /* glyph :: A handle to the source glyph object. */ + /* */ + /* mode :: A set of bit flags that indicate how to interpret the */ + /* returned bounding box values. */ + /* */ + /* */ + /* box :: The glyph bounding box. Coordinates are expressed in */ + /* 1/64th of pixels if it is grid-fitted. */ + /* */ + /* */ + /* Coordinates are relative to the glyph origin, using the Y-upwards */ + /* convention. */ + /* */ + /* If `ft_glyph_bbox_subpixels' is set in `mode', the bbox */ + /* coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels). */ + /* Otherwise, coordinates are expressed in integer 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 the */ + /* `ft_glyph_bbox_gridfit' flag is set in `mode;, 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); */ + /* */ + /* The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Glyph_Get_CBox( FT_Glyph glyph, + FT_UInt bbox_mode, + FT_BBox* cbox ) + { + const FT_Glyph_Class* clazz; + FT_Error error = FT_Err_Ok; + + + if ( !cbox || !glyph || !glyph->clazz ) + error = FT_Err_Invalid_Argument; + else + { + clazz = glyph->clazz; + if ( !clazz->glyph_bbox ) + error = FT_Err_Invalid_Glyph_Format; + else + { + /* retrieve bbox in 26.6 coordinates */ + clazz->glyph_bbox( glyph, cbox ); + + /* perform grid fitting if needed */ + if ( bbox_mode & ft_glyph_bbox_gridfit ) + { + cbox->xMin &= -64; + cbox->yMin &= -64; + cbox->xMax = ( cbox->xMax + 63 ) & -64; + cbox->yMax = ( cbox->yMax + 63 ) & -64; + } + + /* convert to integer pixels if needed */ + if ( !( bbox_mode & ft_glyph_bbox_subpixels ) ) + { + cbox->xMin >>= 6; + cbox->yMin >>= 6; + cbox->xMax >>= 6; + cbox->yMax >>= 6; + } + } + } + return; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_To_Bitmap */ + /* */ + /* */ + /* Converts a given glyph object to a bitmap glyph object. */ + /* */ + /* */ + /* glyph :: A pointer to a handle to the target glyph. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 ) || + FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); + + if ( !destroy && origin ) + { + FT_Vector v; + + + v.x = -origin->x; + v.y = -origin->y; + FT_Glyph_Transform( glyph, 0, &v ); + } + + /* in case of succes, 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; + } + + if ( destroy ) + FT_Done_Glyph( glyph ); + + *the_glyph = FT_GLYPH( bitmap ); + } + + Exit: + return error; + + Bad: + error = FT_Err_Invalid_Argument; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Glyph */ + /* */ + /* */ + /* Destroys a given glyph. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + FT_EXPORT_FUNC( 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 ); + } + } + + +#if 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 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 */ + return ft_test_extrema( outline, indices.xMin ) || + ft_test_extrema( outline, indices.yMin ) || + ft_test_extrema( outline, indices.xMax ) || + ft_test_extrema( outline, indices.yMax ) || + 1; /* this is an empty glyph? */ + } + + + static + FT_Error ft_embolden( FT_Face original, + FT_Outline* outline, + FT_Pos* advance ) + { + FT_Vector u, v; + FT_Vector* points; + FT_Vector cur, prev, next; + FT_Pos distance; + int c, n, first, orientation; + + FT_UNUSED( advance ); + + + /* compute control distance */ + distance = FT_MulFix( original->em_size / 60, + original->size->metrics.y_scale ); + + orientation = ft_get_orientation( &original->glyph->outline ); + + points = original->glyph->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->flags[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; + } + +#endif /* 0 -- EXPERIMENTAL STUFF! */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/base/ftinit.c b/reactos/subsys/win32k/freetype/src/base/ftinit.c new file mode 100644 index 00000000000..cc754eb856c --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftinit.c @@ -0,0 +1,155 @@ +/***************************************************************************/ +/* */ +/* ftinit.c */ +/* */ +/* FreeType initialization layer (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* 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 +#define FT_USE_MODULE( x ) extern const FT_Module_Class* x; + +#ifdef macintosh + FT_USE_MODULE(fond_driver_class) +#endif +#include + +#undef FT_USE_MODULE +#define FT_USE_MODULE( x ) (const FT_Module_Class*)&x, + +static +const FT_Module_Class* ft_default_modules[] = + { +#ifdef macintosh + FT_USE_MODULE(fond_driver_class) +#endif +#include + 0 + }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Default_Modules */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Add_Default_Modules( FT_Library library ) + { + FT_Error error; + const FT_Module_Class** 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++; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Init_FreeType */ + /* */ + /* */ + /* Initializes a new FreeType library object. The set of drivers */ + /* that are registered by this function is determined at build time. */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Init_FreeType( FT_Library* library ) + { + 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, library ); + if ( !error ) + FT_Add_Default_Modules( *library ); + + return error; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/base/ftlist.c b/reactos/subsys/win32k/freetype/src/base/ftlist.c new file mode 100644 index 00000000000..0158ba4434c --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftlist.c @@ -0,0 +1,301 @@ +/***************************************************************************/ +/* */ +/* ftlist.c */ +/* */ +/* Generic list support for FreeType (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Find */ + /* */ + /* */ + /* Finds the list node for a given listed object. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* data :: The address of the listed object. */ + /* */ + /* */ + /* List node. NULL if it wasn't found. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Add */ + /* */ + /* */ + /* Appends an element to the end of a list. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* node :: The node to append. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Insert */ + /* */ + /* */ + /* Inserts an element at the head of a list. */ + /* */ + /* */ + /* list :: A pointer to parent list. */ + /* node :: The node to insert. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Remove */ + /* */ + /* */ + /* Removes a node from a list. This function doesn't check whether */ + /* the node is in the list! */ + /* */ + /* */ + /* node :: The node to remove. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Up */ + /* */ + /* */ + /* Moves a node to the head/top of a list. Used to maintain LRU */ + /* lists. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* node :: The node to move. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Iterate */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The result (a FreeType error code) of the last iterator call. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Finalize */ + /* */ + /* */ + /* Destroys all elements in the list as well as the list itself. */ + /* */ + /* */ + /* 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. */ + /* */ + BASE_FUNC( 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/reactos/subsys/win32k/freetype/src/base/ftmm.c b/reactos/subsys/win32k/freetype/src/base/ftmm.c new file mode 100644 index 00000000000..0f6fddea28b --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftmm.c @@ -0,0 +1,176 @@ +/***************************************************************************/ +/* */ +/* ftmm.c */ +/* */ +/* Multiple Master font support (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Multi_Master */ + /* */ + /* */ + /* Retrieves the Multiple Master descriptor of a given font. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* */ + /* master :: The Multiple Masters descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master* master ) + { + 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, master ); + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Design_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through design coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Blend_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through normalized blend coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates (each one must be between 0 */ + /* and 1.0). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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/reactos/subsys/win32k/freetype/src/base/ftnames.c b/reactos/subsys/win32k/freetype/src/base/ftnames.c new file mode 100644 index 00000000000..43a0d12d073 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftnames.c @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* ftnames.c */ +/* */ +/* Simple interface to access SFNT name tables (which are used */ +/* to hold font names, copyright info, notices, etc.). */ +/* */ +/* This is _not_ used to retrieve glyph names! */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_CONFIG_OPTION_SFNT_NAMES + + + FT_EXPORT_FUNC( FT_UInt ) FT_Get_Sfnt_Name_Count( FT_Face face ) + { + return face && ( FT_IS_SFNT( face ) ? ((TT_Face)face)->num_names : 0 ); + } + + + FT_EXPORT_FUNC( 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 < 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 /* FT_CONFIG_OPTION_SFNT_NAMES */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/base/ftobjs.c b/reactos/subsys/win32k/freetype/src/base/ftobjs.c new file mode 100644 index 00000000000..de74882554b --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftobjs.c @@ -0,0 +1,3246 @@ +/***************************************************************************/ +/* */ +/* ftobjs.c */ +/* */ +/* The FreeType private base classes (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + +#include + +#include /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Alloc */ + /* */ + /* */ + /* Allocates a new block of memory. The returned area is always */ + /* zero-filled; this is a strong convention in many FreeType parts. */ + /* */ + /* */ + /* memory :: A handle to a given `memory object' which handles */ + /* allocation. */ + /* */ + /* size :: The size in bytes of the block to allocate. */ + /* */ + /* */ + /* P :: A pointer to the fresh new block. It should be set to */ + /* NULL if `size' is 0, or in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Realloc */ + /* */ + /* */ + /* Reallocates a block of memory pointed to by `*P' to `Size' bytes */ + /* from the heap, possibly changing `*P'. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* P :: A pointer to the fresh new block. It should be set to */ + /* NULL if `size' is 0, or in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* All callers of FT_Realloc() _must_ provide the current block size */ + /* as well as the new one. */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Free */ + /* */ + /* */ + /* Releases a given block of memory allocated through FT_Alloc(). */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If P or *P are NULL, this function should return successfully. */ + /* This is a strong convention within all of FreeType and its */ + /* drivers. */ + /* */ + BASE_FUNC( 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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* ft_new_input_stream */ + /* */ + /* */ + /* Creates a new input stream object from an FT_Open_Args structure. */ + /* */ + /* */ + /* 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, + 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 ) + { + *stream = *(args->stream); + stream->memory = memory; + } + else + error = FT_Err_Invalid_Argument; + + if ( error ) + FREE( stream ); + + *astream = stream; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Stream */ + /* */ + /* */ + /* Closes and destroys a stream object. */ + /* */ + /* */ + /* stream :: The stream to be closed and destroyed. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Done_Stream( FT_Stream stream ) + { + if ( stream && stream->close ) + stream->close( stream ); + } + + + static + void ft_done_stream( FT_Stream* astream ) + { + FT_Stream stream = *astream; + FT_Memory memory = stream->memory; + + + if ( stream->close ) + stream->close( stream ); + + 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 */ + BASE_FUNC( 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 */ + BASE_FUNC( 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 */ + BASE_FUNC( 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 */ + BASE_FUNC( 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; + } + + + BASE_FUNC( 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! */ + /* */ + BASE_FUNC( 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; + + + /* check points & tags */ + new_max = base->n_points + current->n_points + n_points; + if ( new_max > loader->max_points ) + { + new_max = ( new_max + 7 ) & -8; + if ( REALLOC_ARRAY( base->points, base->n_points, + new_max, FT_Vector ) || + REALLOC_ARRAY( base->tags, base->n_points, + new_max, FT_Byte ) ) + goto Exit; + + if ( loader->use_extra && + REALLOC_ARRAY( loader->base.extra_points, base->n_points, + new_max, FT_Vector ) ) + goto Exit; + + adjust = 1; + loader->max_points = new_max; + } + + /* check contours */ + new_max = base->n_contours + current->n_contours + + n_contours; + if ( new_max > loader->max_contours ) + { + new_max = ( new_max + 3 ) & -4; + if ( REALLOC_ARRAY( base->contours, base->n_contours, + 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! */ + /* */ + BASE_FUNC( 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; + + FT_GlyphLoad* base = &loader->base; + FT_GlyphLoad* current = &loader->current; + + + new_max = base->num_subglyphs + current->num_subglyphs + n_subs; + if ( new_max > loader->max_subglyphs ) + { + new_max = ( new_max + 1 ) & -2; + if ( REALLOC_ARRAY( base->subglyphs, base->num_subglyphs, + 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 */ + BASE_FUNC( 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 */ + BASE_FUNC( 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 += current->outline.n_points; + 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] += n_base_points; + + /* prepare for another new glyph image */ + FT_GlyphLoader_Prepare( loader ); + } + + + BASE_FUNC( 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 = num_points; + out->n_contours = 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; + + + slot->library = driver->root.library; + + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + error = FT_GlyphLoader_New( memory, &slot->loader ); + + if ( !error && clazz->init_slot ) + error = clazz->init_slot( slot ); + + 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; + + + /* 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->loader ); + slot->loader = 0; + } + + if ( clazz->done_slot ) + clazz->done_slot( slot ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_GlyphSlot */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to a parent face object. */ + /* */ + /* */ + /* aslot :: A handle to a new glyph slot object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_GlyphSlot */ + /* */ + /* */ + /* Destroys a given glyph slot. Remember however that all slots are */ + /* automatically destroyed with its parent. Using this function is */ + /* not always mandatory. */ + /* */ + /* */ + /* slot :: A handle to a target glyph slot. */ + /* */ + FT_EXPORT_FUNC( 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; + } + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Transform */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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_FUNC( void ) FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ) + { + if ( !face ) + return; + + face->transform_flags = 0; + + if ( !matrix ) + { + face->transform_matrix.xx = 0x10000L; + face->transform_matrix.xy = 0; + face->transform_matrix.yx = 0; + face->transform_matrix.yy = 0x10000L; + matrix = &face->transform_matrix; + } + else + face->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 ) + face->transform_flags |= 1; + + if ( !delta ) + { + face->transform_delta.x = 0; + face->transform_delta.y = 0; + delta = &face->transform_delta; + } + else + face->transform_delta = *delta; + + /* set transform_flags bit flag 1 if `delta' isn't the null vector */ + if ( delta->x | delta->y ) + face->transform_flags |= 2; + } + + + static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Glyph */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* */ + /* face :: A handle to the target face object where the glyph */ + /* will be 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). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + /* do we need to load the glyph through the auto-hinter? */ + library = driver->root.library; + hinter = library->auto_hinter; + autohint = hinter && + !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ); + 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; + } + + /* now, transform the glyph image when needed */ + if ( face->transform_flags ) + { + /* get renderer */ + FT_Renderer renderer = ft_lookup_glyph_renderer( slot ); + + + if ( renderer ) + error = renderer->clazz->transform_glyph( renderer, slot, + &face->transform_matrix, + &face->transform_delta ); + /* transform advance */ + FT_Vector_Transform( &slot->advance, &face->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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Char */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size, according to its character code. */ + /* */ + /* */ + /* face :: A handle to a target face object where the glyph */ + /* will be loaded. */ + /* */ + /* 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). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 ); + } + + + /* 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->slot' */ + 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 */ + if ( ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) == 0 ) + ft_done_stream( &face->stream ); + + /* get rid of it */ + 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* open_face */ + /* */ + /* */ + /* 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; + + + clazz = driver->clazz; + memory = driver->root.memory; + + /* allocate the face object and perform basic initialization */ + if ( ALLOC( face, clazz->face_object_size ) ) + goto Fail; + + 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 ); + *aface = 0; + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a pathname to the font file. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* pathname :: A path to the font file. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* 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 */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_FUNC( 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a font file already loaded into memory. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* 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. */ + /* */ + /* face :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* 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 */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Memory_Face( FT_Library library, + FT_Byte* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face* face ) + { + 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, face ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Face */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* 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. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* 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 resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_FUNC( 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; + + + /* test for valid `library' and `args' delayed to */ + /* ft_new_input_stream() */ + + if ( !aface ) + return FT_Err_Invalid_Argument; + + *aface = 0; + + /* 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 ); + 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 ( error != FT_Err_Unknown_File_Format ) + goto Fail; + } + } + + ft_done_stream( &stream ); + + /* no driver is able to handle this format */ + error = FT_Err_Unknown_File_Format; + goto Fail; + } + + Success: + FT_TRACE4(( "FT_New_Face: New face object, adding to list\n" )); + + /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */ + if ( args->flags & ft_open_stream && args->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 transformation for convenience functions */ + face->transform_matrix.xx = 0x10000L; + face->transform_matrix.xy = 0; + face->transform_matrix.yx = 0; + face->transform_matrix.yy = 0x10000L; + + face->transform_delta.x = 0; + face->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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_File */ + /* */ + /* */ + /* `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. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* */ + /* filepathname :: An 8-bit pathname naming the `metrics' file. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_Stream */ + /* */ + /* */ + /* This function is similar to FT_Attach_File() with the exception */ + /* that it reads the attachment from an arbitrary stream. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* parameters :: A pointer to an FT_Open_Args structure used to */ + /* describe the input stream to FreeType. */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 */ + if ( !parameters->stream || ( parameters->flags & ft_open_stream ) ) + ft_done_stream( &stream ); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Face */ + /* */ + /* */ + /* Discards a given face object, as well as all of its child slots */ + /* and sizes. */ + /* */ + /* */ + /* face :: A handle to a target face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Size */ + /* */ + /* */ + /* Creates a new size object from a given face object. */ + /* */ + /* */ + /* face :: A handle to a parent face object. */ + /* */ + /* */ + /* asize :: A handle to a new size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Size */ + /* */ + /* */ + /* Discards a given size object. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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 FT_Err_Ok; + } + + + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Char_Size */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* When dealing with fixed-size faces (i.e., non-scalable formats), */ + /* use the function FT_Set_Pixel_Sizes(). */ + /* */ + FT_EXPORT_FUNC( 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_Memory memory; + 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; + memory = driver->root.memory; + + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Pixel_Sizes */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* pixel_width :: The character width, in integer pixels. */ + /* */ + /* pixel_height :: The character height, in integer pixels. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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_Memory memory; + 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; + memory = driver->root.memory; + + /* 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 = pixel_width; + metrics->y_ppem = 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Kerning */ + /* */ + /* */ + /* Returns the kerning vector between two glyphs of a same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( FT_Error ) FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_UInt kern_mode, + FT_Vector* kerning ) + { + FT_Error error = FT_Err_Ok; + FT_Driver driver; + FT_Memory memory; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + if ( !kerning ) + return FT_Err_Invalid_Argument; + + driver = face->driver; + memory = driver->root.memory; + + kerning->x = 0; + kerning->y = 0; + + if ( driver->clazz->get_kerning ) + { + error = driver->clazz->get_kerning( face, + left_glyph, + right_glyph, + kerning ); + if ( !error ) + { + if ( kern_mode != ft_kerning_unscaled ) + { + kerning->x = FT_MulFix( kerning->x, face->size->metrics.x_scale ); + kerning->y = FT_MulFix( kerning->y, face->size->metrics.y_scale ); + + if ( kern_mode != ft_kerning_unfitted ) + { + kerning->x = ( kerning->x + 32 ) & -64; + kerning->y = ( kerning->y + 32 ) & -64; + } + } + } + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Select_Charmap */ + /* */ + /* */ + /* Selects a given charmap by its encoding tag (as listed in */ + /* `freetype.h'). */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* encoding :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function will return an error if no charmap in the face */ + /* corresponds to the encoding queried here. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Charmap */ + /* */ + /* */ + /* Selects a given charmap for character code to glyph index */ + /* decoding. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* charmap :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Char_Index */ + /* */ + /* */ + /* Returns the glyph index of a given character code. This function */ + /* uses a charmap object to do the translation. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph_Name */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to a source face object. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* buffer :: A pointer to a target buffer where the name will be */ + /* copied to. */ + /* */ + /* buffer_max :: The maximal number of bytes available in the */ + /* buffer. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Sfnt_Table */ + /* */ + /* */ + /* Returns a pointer to a given SFNT table within a face. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* tag :: An index of an SFNT table. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 the FT_Sfnt_Tag */ + /* enumeration in `tttables.h' for a list. */ + /* */ + /* You can load any table with a different function.. XXX */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** R E N D E R E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* lookup a renderer by glyph format in the library's list */ + BASE_FUNC( 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 ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Renderer */ + /* */ + /* */ + /* Retrieves the current renderer for a given glyph format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* format :: The glyph format. */ + /* */ + /* */ + /* A renderer handle. 0 if none found. */ + /* */ + /* */ + /* 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_FUNC( 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Renderer */ + /* */ + /* */ + /* Sets the current renderer to use, and set additional mode. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* renderer :: A handle to the renderer object. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* parameters :: Additional parameters. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_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; + } + + + LOCAL_FUNC + 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 || 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Render_Glyph */ + /* */ + /* */ + /* Converts a given glyph image to a bitmap. It does so by */ + /* inspecting the glyph image format, find the relevant renderer, and */ + /* invoke it. */ + /* */ + /* */ + /* slot :: A handle to the glyph slot containing the image to */ + /* convert. */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Destroy_Module */ + /* */ + /* */ + /* Destroys a given module object. For drivers, this also destroys */ + /* all child faces. */ + /* */ + /* */ + /* module :: A handle to the target driver object. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Module */ + /* */ + /* */ + /* Adds a new module to a given library instance. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* clazz :: A pointer to class descriptor for the module. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module */ + /* */ + /* */ + /* Finds a module by its name. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module handle. 0 if none was found. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for :-) */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module_Interface */ + /* */ + /* */ + /* Finds a module and returns its specific interface as a typeless */ + /* pointer. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module-specific interface if available, 0 otherwise. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for, and what its interface is :-) */ + /* */ + BASE_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Remove_Module */ + /* */ + /* */ + /* Removes a given module from a library instance. */ + /* */ + /* */ + /* library :: A handle to a library object. */ + /* */ + /* module :: A handle to a module object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The module object is destroyed by the function in case of success. */ + /* */ + FT_EXPORT_FUNC( 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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Library */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* memory :: A handle to the original memory object. */ + /* */ + /* */ + /* alibrary :: A pointer to handle of a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Library */ + /* */ + /* */ + /* Discards a given library object. This closes all drivers and */ + /* discards all resource objects. */ + /* */ + /* */ + /* library :: A handle to the target library. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Debug_Hook */ + /* */ + /* */ + /* Sets a debug hook function for debugging the interpreter of a font */ + /* format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* 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. */ + /* */ + /* */ + /* Currently, four debug hook slots are available, but only two (for */ + /* the TrueType and the Type 1 interpreter) are defined. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_FreeType */ + /* */ + /* */ + /* Destroys a given FreeType library object and all of its childs, */ + /* including resources, drivers, faces, sizes, etc. */ + /* */ + /* */ + /* library :: A handle to the target library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Done_FreeType( FT_Library library ) + { + /* test for valid `library' delayed to FT_Done_Library() */ + + /* Discard the library object */ + FT_Done_Library( library ); + + return FT_Err_Ok; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/base/ftoutln.c b/reactos/subsys/win32k/freetype/src/base/ftoutln.c new file mode 100644 index 00000000000..20292d0c3ae --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftoutln.c @@ -0,0 +1,842 @@ +/***************************************************************************/ +/* */ +/* ftoutln.c */ +/* */ +/* FreeType outline management (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + + /*************************************************************************/ + /* */ + /* 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 }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Decompose */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means sucess. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Outline_Decompose( + FT_Outline* outline, + 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 */ + char 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_FUNC( FT_Error ) FT_Outline_New_Internal( + FT_Memory memory, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ) + { + FT_Error error; + + + if ( !outline || !memory ) + return FT_Err_Invalid_Argument; + + *outline = null_outline; + + if ( ALLOC_ARRAY( outline->points, numPoints * 2L, FT_Pos ) || + ALLOC_ARRAY( outline->tags, numPoints, FT_Byte ) || + ALLOC_ARRAY( outline->contours, numContours, FT_UShort ) ) + goto Fail; + + outline->n_points = (FT_UShort)numPoints; + outline->n_contours = (FT_Short)numContours; + outline->flags |= ft_outline_owner; + + return FT_Err_Ok; + + Fail: + outline->flags |= ft_outline_owner; + FT_Outline_Done_Internal( memory, outline ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_New */ + /* */ + /* */ + /* Creates a new outline of a given size. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* outline :: A handle to the new outline. NULL in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* The reason why this function takes a `library' parameter is simply */ + /* to use the library's memory allocator. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Outline_New( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ) + { + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + return FT_Outline_New_Internal( library->memory, numPoints, + numContours, outline ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Copy */ + /* */ + /* */ + /* Copies an outline into another one. Both objects must have the */ + /* same sizes (number of points & number of contours) when this */ + /* function is called. */ + /* */ + /* */ + /* source :: A handle to the source outline. */ + /* */ + /* */ + /* target :: A handle to the target outline. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( 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_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Done */ + /* */ + /* */ + /* Destroys an outline created with FT_Outline_New(). */ + /* */ + /* */ + /* library :: A handle of the library object used to allocate the */ + /* outline. */ + /* */ + /* outline :: A pointer to the outline object to be discarded. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* If the outline's `owner' field is not set, only the outline */ + /* descriptor will be released. */ + /* */ + /* The reason why this function takes an `outline' parameter is */ + /* simply to use FT_Free(). */ + /* */ + FT_EXPORT_FUNC( 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_CBox */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* */ + /* cbox :: The outline's control box. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Outline_Get_CBox( FT_Outline* outline, + FT_BBox* cbox ) + { + FT_Pos xMin, yMin, xMax, yMax; + + + if ( outline && cbox ) + { + 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; + } + } + cbox->xMin = xMin; + cbox->xMax = xMax; + cbox->yMin = yMin; + cbox->yMax = yMax; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Translate */ + /* */ + /* */ + /* Applies a simple translation to the points of an outline. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* xOffset :: The horizontal offset. */ + /* */ + /* yOffset :: The vertical offset. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_FUNC( 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++; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Reverse */ + /* */ + /* */ + /* Reverses the drawing direction of an outline. This is used to */ + /* ensure consistent fill conventions for mirrored glyphs. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* */ + /* This functions toggles the bit flag `ft_outline_reverse_fill' in */ + /* the outline's `flags' field. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Render */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* params :: A pointer to a FT_Raster_Params structure used to */ + /* describe the rendering operation. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* 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_FUNC( 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 || 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_Bitmap */ + /* */ + /* */ + /* Renders an outline within a bitmap. The outline's image is simply */ + /* OR-ed to the target bitmap. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* map :: A pointer to the target bitmap descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* 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_FUNC( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap* bitmap ) + { + FT_Raster_Params params; + + + if ( !bitmap ) + return FT_Err_Invalid_Argument; + + /* other checks are delayed to FT_Outline_Render() */ + + params.target = bitmap; + params.flags = 0; + + if ( bitmap->pixel_mode == ft_pixel_mode_grays ) + params.flags |= ft_raster_flag_aa; + + return FT_Outline_Render( library, outline, ¶ms ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector_Transform */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* vector :: The target vector to transform. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Transform */ + /* */ + /* */ + /* Applies a simple 2x2 matrix to all of an outline's points. Useful */ + /* for applying rotations, slanting, flipping, etc. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* matrix :: A pointer to the transformation matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* You can use FT_Outline_Translate() if you need to translate the */ + /* outline's points. */ + /* */ + FT_EXPORT_FUNC( 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/reactos/subsys/win32k/freetype/src/base/ftstream.c b/reactos/subsys/win32k/freetype/src/base/ftstream.c new file mode 100644 index 00000000000..768586ebbf4 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftstream.c @@ -0,0 +1,818 @@ +/***************************************************************************/ +/* */ +/* ftstream.c */ +/* */ +/* I/O stream support (body). */ +/* */ +/* Copyright 2000 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 +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( FT_Error ) FT_Skip_Stream( FT_Stream stream, + FT_Long distance ) + { + return FT_Seek_Stream( stream, (FT_ULong)( stream->pos + distance ) ); + } + + + BASE_FUNC( FT_Long ) FT_Stream_Pos( FT_Stream stream ) + { + return stream->pos; + } + + + BASE_FUNC( FT_Error ) FT_Read_Stream( FT_Stream stream, + FT_Byte* buffer, + FT_ULong count ) + { + return FT_Read_Stream_At( stream, stream->pos, buffer, count ); + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( void ) FT_Release_Frame( FT_Stream stream, + FT_Byte** pbytes ) + { + if ( stream->read ) + { + FT_Memory memory = stream->memory; + + + FREE( *pbytes ); + } + *pbytes = 0; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( 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; + } + + + BASE_FUNC( FT_Error ) FT_Read_Fields( FT_Stream stream, + const FT_Frame_Field* fields, + void* structure ) + { + FT_Error error; + FT_Bool frame_accessed = 0; + + + 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; + fields++; + continue; /* loop! */ + + case ft_frame_bytes: /* read a byte sequence */ + case ft_frame_skip: /* skip some bytes */ + { + FT_Int len = fields->size; + + + if ( stream->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, stream->cursor, len ); + } + stream->cursor += len; + fields++; + continue; + } + + case ft_frame_byte: + case ft_frame_schar: /* read a single byte */ + value = GET_Byte(); + sign_shift = 24; + break; + + case ft_frame_short_be: + case ft_frame_ushort_be: /* read a 2-byte big-endian short */ + value = GET_UShort(); + sign_shift = 16; + break; + + case ft_frame_short_le: + case ft_frame_ushort_le: /* read a 2-byte little-endian short */ + { + FT_Byte* p; + + + value = 0; + p = stream->cursor; + + if ( p + 1 < stream->limit ) + { + value = ( FT_UShort)p[0] | ((FT_UShort)p[1] << 8 ); + stream->cursor += 2; + } + sign_shift = 16; + break; + } + + case ft_frame_long_be: + case ft_frame_ulong_be: /* read a 4-byte big-endian long */ + value = GET_ULong(); + sign_shift = 0; + break; + + case ft_frame_long_le: + case ft_frame_ulong_le: /* read a 4-byte little-endian long */ + { + FT_Byte* p; + + + value = 0; + p = stream->cursor; + + if ( p + 3 < stream->limit ) + { + value = (FT_ULong)p[0] | + ( (FT_ULong)p[1] << 8 ) | + ( (FT_ULong)p[2] << 16 ) | + ( (FT_ULong)p[3] << 24 ); + stream->cursor += 4; + } + sign_shift = 0; + break; + } + + case ft_frame_off3_be: + case ft_frame_uoff3_be: /* read a 3-byte big-endian long */ + value = GET_UOffset(); + sign_shift = 8; + break; + + case ft_frame_off3_le: + case ft_frame_uoff3_le: /* read a 3-byte little-endian long */ + { + FT_Byte* p; + + + value = 0; + p = stream->cursor; + + if ( p + 2 < stream->limit ) + { + value = (FT_ULong)p[0] | + ( (FT_ULong)p[1] << 8 ) | + ( (FT_ULong)p[2] << 16 ); + stream->cursor += 3; + } + sign_shift = 8; + break; + } + + default: + /* otherwise, exit the loop */ + 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/reactos/subsys/win32k/freetype/src/base/ftsystem.c b/reactos/subsys/win32k/freetype/src/base/ftsystem.c new file mode 100644 index 00000000000..931bb6c35d3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/ftsystem.c @@ -0,0 +1,299 @@ +/***************************************************************************/ +/* */ +/* ftsystem.c */ +/* */ +/* ANSI-specific FreeType low-level system interface (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* 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(). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* ft_alloc */ + /* */ + /* */ + /* The memory allocation function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* size :: The requested size in bytes. */ + /* */ + /* */ + /* block :: The address of newly allocated block. */ + /* */ + static + void* ft_alloc( FT_Memory memory, + long size ) + { + FT_UNUSED( memory ); + +/* return malloc( size ); FIXME */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_realloc */ + /* */ + /* */ + /* The memory reallocation function. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The address of the reallocated memory block. */ + /* */ + static + 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 ); FIXME */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_free */ + /* */ + /* */ + /* The memory release function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* block :: The address of block in memory to be freed. */ + /* */ + static + void ft_free( FT_Memory memory, + void* block ) + { + FT_UNUSED( memory ); + +/* free( block ); FIXME */ + } + + + /*************************************************************************/ + /* */ + /* 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 ) + + + /*************************************************************************/ + /* */ + /* */ + /* ft_close_stream */ + /* */ + /* */ + /* The function to close a stream. */ + /* */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + static + void ft_close_stream( FT_Stream stream ) + { +/* fclose( STREAM_FILE( stream ) ); FIXME */ + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_io_stream */ + /* */ + /* */ + /* The function to open a stream. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The number of bytes actually read. */ + /* */ + static + 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 ); FIXME */ + +/* return (unsigned long)fread( buffer, 1, count, file ); FIXME */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Stream */ + /* */ + /* */ + /* Creates a new stream object. */ + /* */ + /* */ + /* filepathname :: The name of the stream (usually a file) to be */ + /* opened. */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Stream( const char* filepathname, + FT_Stream stream ) + { +/* FILE* file; FIXME */ + + + if ( !stream ) + 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 ); + stream->size = ftell( file ); + fseek( file, 0, SEEK_SET ); + + stream->descriptor.pointer = file; + stream->pathname.pointer = (char*)filepathname; + stream->pos = 0; + + stream->read = ft_io_stream; + stream->close = ft_close_stream; FIXME */ + + FT_TRACE1(( "FT_New_Stream:" )); + FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", + filepathname, stream->size )); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory */ + /* */ + /* */ + /* Creates a new memory object. */ + /* */ + /* */ + /* A pointer to the new memory object. 0 in case of error. */ + /* */ + FT_EXPORT_FUNC( FT_Memory ) FT_New_Memory( void ) + { + FT_Memory memory; + + +/* memory = (FT_Memory)malloc( sizeof ( *memory ) ); FIXME */ + if ( memory ) + { + memory->user = 0; + memory->alloc = ft_alloc; + memory->realloc = ft_realloc; + memory->free = ft_free; + } + + return memory; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/base/rules.mk b/reactos/subsys/win32k/freetype/src/base/rules.mk new file mode 100644 index 00000000000..1763a09817b --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/base/rules.mk @@ -0,0 +1,83 @@ +# +# FreeType 2 base layer configuration rules +# + + +# Copyright 1996-2000 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. + + +# It sets the following variables which are used by the master Makefile +# after the call: +# +# BASE_OBJ_S: The single-object base layer. +# BASE_OBJ_M: A list of all objects for a multiple-objects build. +# BASE_EXT_OBJ: A list of base layer extensions, i.e., components found +# in `freetype/src/base' which are not compiled within the +# base layer proper. +# +# BASE_H is defined in freetype.mk to simplify the dependency rules. + + +BASE_COMPILE := $(FT_COMPILE) $I$(SRC_)base + + +# Base layer sources +# +# ftsystem, ftinit, and ftdebug are handled by freetype.mk +# +BASE_SRC := $(BASE_)ftcalc.c \ + $(BASE_)ftextend.c \ + $(BASE_)ftlist.c \ + $(BASE_)ftobjs.c \ + $(BASE_)ftstream.c \ + $(BASE_)ftoutln.c + +# Base layer `extensions' sources +# +# An extension is added to the library file (.a or .lib) as a separate +# object. It will then be linked to the final executable only if one of its +# symbols is used by the application. +# +BASE_EXT_SRC := $(BASE_)ftglyph.c \ + $(BASE_)ftmm.c + +# Default extensions objects +# +BASE_EXT_OBJ := $(BASE_EXT_SRC:$(BASE_)%.c=$(OBJ_)%.$O) + + +# Base layer object(s) +# +# BASE_OBJ_M is used during `multi' builds (each base source file compiles +# to a single object file). +# +# BASE_OBJ_S is used during `single' builds (the whole base layer is +# compiled as a single object file using ftbase.c). +# +BASE_OBJ_M := $(BASE_SRC:$(BASE_)%.c=$(OBJ_)%.$O) +BASE_OBJ_S := $(OBJ_)ftbase.$O + +# Base layer root source file for single build +# +BASE_SRC_S := $(BASE_)ftbase.c + + +# Base layer - single object build +# +$(BASE_OBJ_S): $(BASE_SRC_S) $(BASE_SRC) $(FREETYPE_H) + $(BASE_COMPILE) $T$@ $(BASE_SRC_S) + + +# Multiple objects build + extensions +# +$(OBJ_)%.$O: $(BASE_)%.c $(FREETYPE_H) + $(BASE_COMPILE) $T$@ $< + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/cff/cff.c b/reactos/subsys/win32k/freetype/src/cff/cff.c new file mode 100644 index 00000000000..5a987f1cdf9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/cff.c @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* cff.c */ +/* */ +/* FreeType OpenType driver component (body only). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef FT_FLAT_COMPILE + +#include "t2driver.c" /* driver interface */ +#include "t2parse.c" /* token parser */ +#include "t2load.c" /* tables loader */ +#include "t2objs.c" /* object management */ +#include "t2gload.c" /* glyph loader */ + +#else + +#include /* driver interface */ +#include /* token parser */ +#include /* tables loader */ +#include /* object management */ +#include /* glyph loader */ + +#endif + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cff/module.mk b/reactos/subsys/win32k/freetype/src/cff/module.mk new file mode 100644 index 00000000000..9bc5c8f722c --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_cff_driver + +add_cff_driver: + $(OPEN_DRIVER)cff_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)cff $(ECHO_DRIVER_DESC)OpenType fonts with extension *.otf$(ECHO_DRIVER_DONE) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/cff/rules.mk b/reactos/subsys/win32k/freetype/src/cff/rules.mk new file mode 100644 index 00000000000..ba87af5f18b --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/rules.mk @@ -0,0 +1,69 @@ +# +# FreeType 2 OpenType/CFF driver configuration rules +# + + +# Copyright 1996-2000 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. + + +# OpenType driver directory +# +T2_DIR := $(SRC_)cff +T2_DIR_ := $(T2_DIR)$(SEP) + + +T2_COMPILE := $(FT_COMPILE) + + +# T2 driver sources (i.e., C files) +# +T2_DRV_SRC := $(T2_DIR_)t2objs.c \ + $(T2_DIR_)t2load.c \ + $(T2_DIR_)t2gload.c \ + $(T2_DIR_)t2parse.c \ + $(T2_DIR_)t2driver.c + +# T2 driver headers +# +T2_DRV_H := $(T2_DRV_SRC:%.c=%.h) \ + $(T2_DIR_)t2tokens.h + + +# T2 driver object(s) +# +# T2_DRV_OBJ_M is used during `multi' builds +# T2_DRV_OBJ_S is used during `single' builds +# +T2_DRV_OBJ_M := $(T2_DRV_SRC:$(T2_DIR_)%.c=$(OBJ_)%.$O) +T2_DRV_OBJ_S := $(OBJ_)cff.$O + +# T2 driver source file for single build +# +T2_DRV_SRC_S := $(T2_DIR_)cff.c + + +# T2 driver - single object +# +$(T2_DRV_OBJ_S): $(T2_DRV_SRC_S) $(T2_DRV_SRC) $(FREETYPE_H) $(T2_DRV_H) + $(T2_COMPILE) $T$@ $(T2_DRV_SRC_S) + + +# T2 driver - multiple objects +# +$(OBJ_)%.$O: $(T2_DIR_)%.c $(FREETYPE_H) $(T2_DRV_H) + $(T2_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(T2_DRV_OBJ_S) +DRV_OBJS_M += $(T2_DRV_OBJ_M) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/cff/t2driver.c b/reactos/subsys/win32k/freetype/src/cff/t2driver.c new file mode 100644 index 00000000000..d1e1b188d23 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2driver.c @@ -0,0 +1,377 @@ +/***************************************************************************/ +/* */ +/* t2driver.c */ +/* */ +/* OpenType font driver implementation (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2driver.h" +#include "t2gload.h" + +#else + +#include +#include + +#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_t2driver + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F A C E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#undef PAIR_TAG +#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ + (FT_ULong)right ) + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 T2_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 T2_Err_Ok; + + Found: + kerning->x = pair->value; + goto Exit; + } + + +#undef PAIR_TAG + + + /*************************************************************************/ + /* */ + /* */ + /* Load_Glyph */ + /* */ + /* */ + /* A driver method used to load a glyph within a given glyph slot. */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Load_Glyph( T2_GlyphSlot slot, + T2_Size size, + FT_UShort glyph_index, + FT_UInt load_flags ) + { + FT_Error error; + + + if ( !slot ) + return T2_Err_Invalid_Glyph_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 T2_Err_Invalid_Face_Handle; + } + + /* now load the glyph outline if necessary */ + error = T2_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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Glyph index. 0 means `undefined character code'. */ + /* */ + static + FT_UInt t2_get_char_index( TT_CharMap charmap, + FT_Long charcode ) + { + FT_Error error; + T2_Face face; + TT_CMapTable* cmap; + + + cmap = &charmap->cmap; + face = (T2_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 ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** D R I V E R I N T E R F A C E ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Module_Interface t2_get_interface( T2_Driver driver, + const char* interface ) + { + FT_Module sfnt; + + + /* 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. */ + + const FT_Driver_Class cff_driver_class = + { + /* begin with the FT_Module_Class fields */ + { + ft_module_font_driver | ft_module_driver_scalable, + sizeof( T2_DriverRec ), + "cff", + 0x10000L, + 0x20000L, + + 0, /* module-specific interface */ + + (FT_Module_Constructor)T2_Init_Driver, + (FT_Module_Destructor) T2_Done_Driver, + (FT_Module_Requester) t2_get_interface, + }, + + /* now the specific driver fields */ + sizeof( TT_FaceRec ), + sizeof( FT_SizeRec ), + sizeof( T2_GlyphSlotRec ), + + (FTDriver_initFace) T2_Init_Face, + (FTDriver_doneFace) T2_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) t2_get_char_index, + + (FTDriver_getKerning) Get_Kerning, + (FTDriver_attachFile) 0, + (FTDriver_getAdvances) 0 + }; + + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverClass */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ + EXPORT_FUNC( FT_Driver_Class* ) getDriverClass( void ) + { + return &cff_driver_class; + } + + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cff/t2driver.h b/reactos/subsys/win32k/freetype/src/cff/t2driver.h new file mode 100644 index 00000000000..e0b0afd3ac3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2driver.h @@ -0,0 +1,30 @@ +/***************************************************************************/ +/* */ +/* t2driver.h */ +/* */ +/* High-level OpenType driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 T2DRIVER_H +#define T2DRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Driver_Class ) cff_driver_class; + + +#endif /* T2DRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cff/t2gload.c b/reactos/subsys/win32k/freetype/src/cff/t2gload.c new file mode 100644 index 00000000000..1023e3cf481 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2gload.c @@ -0,0 +1,2045 @@ +/***************************************************************************/ +/* */ +/* t2gload.c */ +/* */ +/* OpenType Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2load.h" +#include "t2gload.h" + +#else + +#include +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* 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_t2gload + + + typedef enum T2_Operator_ + { + t2_op_unknown = 0, + + t2_op_rmoveto, + t2_op_hmoveto, + t2_op_vmoveto, + + t2_op_rlineto, + t2_op_hlineto, + t2_op_vlineto, + + t2_op_rrcurveto, + t2_op_hhcurveto, + t2_op_hvcurveto, + t2_op_rcurveline, + t2_op_rlinecurve, + t2_op_vhcurveto, + t2_op_vvcurveto, + + t2_op_flex, + t2_op_hflex, + t2_op_hflex1, + t2_op_flex1, + + t2_op_endchar, + + t2_op_hstem, + t2_op_vstem, + t2_op_hstemhm, + t2_op_vstemhm, + + t2_op_hintmask, + t2_op_cntrmask, + + t2_op_abs, + t2_op_add, + t2_op_sub, + t2_op_div, + t2_op_neg, + t2_op_random, + t2_op_mul, + t2_op_sqrt, + + t2_op_blend, + + t2_op_drop, + t2_op_exch, + t2_op_index, + t2_op_roll, + t2_op_dup, + + t2_op_put, + t2_op_get, + t2_op_store, + t2_op_load, + + t2_op_and, + t2_op_or, + t2_op_not, + t2_op_eq, + t2_op_ifelse, + + t2_op_callsubr, + t2_op_callgsubr, + t2_op_return, + + /* do not remove */ + t2_op_max + + } T2_Operator; + + +#define T2_COUNT_CHECK_WIDTH 0x80 +#define T2_COUNT_EXACT 0x40 +#define T2_COUNT_CLEAR_STACK 0x20 + + + static const FT_Byte t2_argument_counts[] = + { + 0, /* unknown */ + + 2 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, /* rmoveto */ + 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, + 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, + + 0 | T2_COUNT_CLEAR_STACK, /* rlineto */ + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + + 0 | T2_COUNT_CLEAR_STACK, /* rrcurveto */ + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + + 13, /* flex */ + 7, + 9, + 11, + + 0, /* endchar */ + + 2 | T2_COUNT_CHECK_WIDTH, /* hstem */ + 2 | T2_COUNT_CHECK_WIDTH, + 2 | T2_COUNT_CHECK_WIDTH, + 2 | T2_COUNT_CHECK_WIDTH, + + 0, /* hintmask */ + 0, /* cntrmask */ + + 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 *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + static + void T2_Init_Builder( T2_Builder* builder, + TT_Face face, + T2_Size size, + T2_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.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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Done_Builder */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + static + void T2_Done_Builder( T2_Builder* builder ) + { + T2_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t2_compute_bias */ + /* */ + /* */ + /* Computes the bias value in dependence of the number of glyph */ + /* subroutines. */ + /* */ + /* */ + /* num_subrs :: The number of glyph subroutines. */ + /* */ + /* */ + /* The bias value. */ + static + FT_Int t2_compute_bias( FT_UInt num_subrs ) + { + FT_Int result; + + + if ( num_subrs < 1240 ) + result = 107; + else if ( num_subrs < 33900 ) + result = 1131; + else + result = 32768; + + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* slot :: The current glyph object. */ + /* */ + LOCAL_FUNC + void T2_Init_Decoder( T2_Decoder* decoder, + TT_Face face, + T2_Size size, + T2_GlyphSlot slot ) + { + CFF_Font* cff = (CFF_Font*)face->extra.data; + + + /* clear everything */ + MEM_Set( decoder, 0, sizeof ( *decoder ) ); + + /* initialize builder */ + T2_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 = t2_compute_bias( decoder->num_globals ); + } + + + /* this function is used to select the locals subrs array */ + LOCAL_DEF + void T2_Prepare_Decoder( T2_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 = t2_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( T2_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( T2_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 = 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( T2_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( T2_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return T2_Err_Ok; + } + + error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = 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( T2_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( T2_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; + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + } + + +#define USE_ARGS( n ) do \ + { \ + top -= n; \ + if ( top < decoder->stack ) \ + goto Stack_Underflow; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given Type 2 charstrings program. */ + /* */ + /* */ + /* decoder :: The current Type 1 decoder. */ + /* */ + /* */ + /* charstring_base :: The base of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T2_Parse_CharStrings( T2_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ) + { + FT_Error error; + T2_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + T2_Builder* builder = &decoder->builder; + FT_Outline* outline; + 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 = T2_Err_Ok; + outline = builder->current; + + x = builder->pos_x; + y = builder->pos_y; + + /* now, execute loop */ + while ( ip < limit ) + { + T2_Operator op; + FT_Byte v; + FT_Byte count; + + + /********************************************************************/ + /* */ + /* 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 >= T2_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 = t2_op_unknown; + + switch ( v ) + { + case 1: + op = t2_op_hstem; + break; + case 3: + op = t2_op_vstem; + break; + case 4: + op = t2_op_vmoveto; + break; + case 5: + op = t2_op_rlineto; + break; + case 6: + op = t2_op_hlineto; + break; + case 7: + op = t2_op_vlineto; + break; + case 8: + op = t2_op_rrcurveto; + break; + case 10: + op = t2_op_callsubr; + break; + case 11: + op = t2_op_return; + break; + case 12: + { + if ( ip >= limit ) + goto Syntax_Error; + v = *ip++; + + switch ( v ) + { + case 3: + op = t2_op_and; + break; + case 4: + op = t2_op_or; + break; + case 5: + op = t2_op_not; + break; + case 8: + op = t2_op_store; + break; + case 9: + op = t2_op_abs; + break; + case 10: + op = t2_op_add; + break; + case 11: + op = t2_op_sub; + break; + case 12: + op = t2_op_div; + break; + case 13: + op = t2_op_load; + break; + case 14: + op = t2_op_neg; + break; + case 15: + op = t2_op_eq; + break; + case 18: + op = t2_op_drop; + break; + case 20: + op = t2_op_put; + break; + case 21: + op = t2_op_get; + break; + case 22: + op = t2_op_ifelse; + break; + case 23: + op = t2_op_random; + break; + case 24: + op = t2_op_mul; + break; + case 26: + op = t2_op_sqrt; + break; + case 27: + op = t2_op_dup; + break; + case 28: + op = t2_op_exch; + break; + case 29: + op = t2_op_index; + break; + case 30: + op = t2_op_roll; + break; + case 34: + op = t2_op_hflex; + break; + case 35: + op = t2_op_flex; + break; + case 36: + op = t2_op_hflex1; + break; + case 37: + op = t2_op_flex1; + break; + default: + /* decrement ip for syntax error message */ + ip--; + } + } + break; + case 14: + op = t2_op_endchar; + break; + case 16: + op = t2_op_blend; + break; + case 18: + op = t2_op_hstemhm; + break; + case 19: + op = t2_op_hintmask; + break; + case 20: + op = t2_op_cntrmask; + break; + case 21: + op = t2_op_rmoveto; + break; + case 22: + op = t2_op_hmoveto; + break; + case 23: + op = t2_op_vstemhm; + break; + case 24: + op = t2_op_rcurveline; + break; + case 25: + op = t2_op_rlinecurve; + break; + case 26: + op = t2_op_vvcurveto; + break; + case 27: + op = t2_op_hhcurveto; + break; + case 29: + op = t2_op_callgsubr; + break; + case 30: + op = t2_op_vhcurveto; + break; + case 31: + op = t2_op_hvcurveto; + break; + default: + ; + } + if ( op == t2_op_unknown ) + goto Syntax_Error; + + /* check arguments */ + req_args = count = t2_argument_counts[op]; + if ( req_args & T2_COUNT_CHECK_WIDTH ) + { + args = stack; + if ( num_args & 1 && decoder->read_width ) + { + decoder->glyph_width = decoder->nominal_width + + ( stack[0] >> 16 ); + 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 t2_op_hstem: + case t2_op_vstem: + case t2_op_hstemhm: + case t2_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 == t2_op_hstem ? " hstem" : + op == t2_op_vstem ? " vstem" : + op == t2_op_hstemhm ? " hstemhm" : + " vstemhm" )); + decoder->num_hints += num_args / 2; + args = stack; + break; + + case t2_op_hintmask: + case t2_op_cntrmask: + FT_TRACE4(( op == t2_op_hintmask ? " hintmask" + : " cntrmask" )); + + decoder->num_hints += num_args / 2; + ip += ( decoder->num_hints + 7 ) >> 3; + if ( ip >= limit ) + goto Syntax_Error; + args = stack; + break; + + case t2_op_rmoveto: + FT_TRACE4(( " rmoveto" )); + + close_contour( builder ); + builder->path_begun = 0; + x += args[0]; + y += args[1]; + args = stack; + break; + + case t2_op_vmoveto: + FT_TRACE4(( " vmoveto" )); + + close_contour( builder ); + builder->path_begun = 0; + y += args[0]; + args = stack; + break; + + case t2_op_hmoveto: + FT_TRACE4(( " hmoveto" )); + + close_contour( builder ); + builder->path_begun = 0; + x += args[0]; + args = stack; + break; + + case t2_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 t2_op_hlineto: + case t2_op_vlineto: + { + FT_Int phase = ( op == t2_op_hlineto ); + + + FT_TRACE4(( op == t2_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 t2_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 t2_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 t2_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 t2_op_vhcurveto: + case t2_op_hvcurveto: + { + FT_Int phase; + + + FT_TRACE4(( op == t2_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 == t2_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 t2_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 t2_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 t2_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 t2_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 t2_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 t2_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 t2_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 T2_Err_Ok; + + case t2_op_abs: + FT_TRACE4(( " abs" )); + + if ( args[0] < 0 ) + args[0] = -args[0]; + args++; + break; + + case t2_op_add: + FT_TRACE4(( " add" )); + + args[0] += args[1]; + args++; + break; + + case t2_op_sub: + FT_TRACE4(( " sub" )); + + args[0] -= args[1]; + args++; + break; + + case t2_op_div: + FT_TRACE4(( " div" )); + + args[0] = FT_DivFix( args[0], args[1] ); + args++; + break; + + case t2_op_neg: + FT_TRACE4(( " neg" )); + + args[0] = -args[0]; + args++; + break; + + case t2_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 t2_op_mul: + FT_TRACE4(( " mul" )); + + args[0] = FT_MulFix( args[0], args[1] ); + args++; + break; + + case t2_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 t2_op_drop: + /* nothing */ + FT_TRACE4(( " drop" )); + + break; + + case t2_op_exch: + { + FT_Fixed tmp; + + + FT_TRACE4(( " exch" )); + + tmp = args[0]; + args[0] = args[1]; + args[1] = tmp; + args += 2; + } + break; + + case t2_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 t2_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 t2_op_dup: + FT_TRACE4(( " dup" )); + + args[1] = args[0]; + args++; + break; + + case t2_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 t2_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 t2_op_store: + FT_TRACE4(( " store ")); + + goto Unimplemented; + + case t2_op_load: + FT_TRACE4(( " load" )); + + goto Unimplemented; + + case t2_op_and: + { + FT_Fixed cond = args[0] && args[1]; + + + FT_TRACE4(( " and" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case t2_op_or: + { + FT_Fixed cond = args[0] || args[1]; + + + FT_TRACE4(( " or" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case t2_op_eq: + { + FT_Fixed cond = !args[0]; + + + FT_TRACE4(( " eq" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case t2_op_ifelse: + { + FT_Fixed cond = (args[2] <= args[3]); + + + FT_TRACE4(( " ifelse" )); + + if ( !cond ) + args[0] = args[1]; + args++; + } + break; + + case t2_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(( "T2_Parse_CharStrings:" )); + FT_ERROR(( " invalid local subr index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "T2_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(( "T2_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case t2_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(( "T2_Parse_CharStrings:" )); + FT_ERROR(( " invalid global subr index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "T2_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(( "T2_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case t2_op_return: + FT_TRACE4(( " return" )); + + if ( decoder->zone <= decoder->zones ) + { + FT_ERROR(( "T2_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 T2_Err_Unimplemented_Feature; + } + + decoder->top = args; + + } /* general operator processing */ + + } /* while ip < limit */ + + FT_TRACE4(( "..end..\n\n" )); + + return error; + + Syntax_Error: + FT_TRACE4(( "T2_Parse_CharStrings: syntax error!" )); + return T2_Err_Invalid_File_Format; + + Stack_Underflow: + FT_TRACE4(( "T2_Parse_CharStrings: stack underflow!" )); + return T2_Err_Too_Few_Arguments; + + Stack_Overflow: + FT_TRACE4(( "T2_Parse_CharStrings: stack overflow!" )); + return T2_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 */ + + + LOCAL_FUNC + FT_Error T2_Compute_Max_Advance( TT_Face face, + FT_Int* max_advance ) + { + FT_Error error = 0; + T2_Decoder decoder; + FT_Int glyph_index; + CFF_Font* cff = (CFF_Font*)face->other; + + + *max_advance = 0; + + /* Initialize load decoder */ + T2_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 = T2_Access_Element( &cff->charstrings_index, glyph_index, + &charstring, &charstring_len ); + if ( !error ) + { + T2_Prepare_Decoder( &decoder, glyph_index ); + error = T2_Parse_CharStrings( &decoder, charstring, charstring_len ); + + T2_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 T2_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. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error T2_Load_Glyph( T2_GlyphSlot glyph, + T2_Size size, + FT_Int glyph_index, + FT_Int load_flags ) + { + FT_Error error; + T2_Decoder decoder; + TT_Face face = (TT_Face)glyph->root.face; + FT_Bool hinting; + CFF_Font* cff = (CFF_Font*)face->extra.data; + + + 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 = ( 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; + + + T2_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 = T2_Access_Element( &cff->charstrings_index, glyph_index, + &charstring, &charstring_len ); + if ( !error ) + { + T2_Prepare_Decoder( &decoder, glyph_index ); + error = T2_Parse_CharStrings( &decoder, charstring, charstring_len ); + + T2_Forget_Element( &cff->charstrings_index, &charstring ); + } + + /* save new glyph tables */ + T2_Done_Builder( &decoder.builder ); + } + + /* 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 ( glyph->root.format == ft_glyph_format_composite ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.glyph_width; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.glyph_width; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 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; + + 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 ); + } + +#if 0 + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, cff->font_matrix ); +#endif + + /* 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/reactos/subsys/win32k/freetype/src/cff/t2gload.h b/reactos/subsys/win32k/freetype/src/cff/t2gload.h new file mode 100644 index 00000000000..2654d4b5636 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2gload.h @@ -0,0 +1,213 @@ +/***************************************************************************/ +/* */ +/* t2gload.h */ +/* */ +/* OpenType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 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 T2GLOAD_H +#define T2GLOAD_H + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + +#define T2_MAX_OPERANDS 48 +#define T2_MAX_SUBRS_CALLS 32 + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* 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 T2_Builder_ + { + FT_Memory memory; + TT_Face face; + T2_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; + + } T2_Builder; + + + /* execution context charstring zone */ + + typedef struct T2_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } T2_Decoder_Zone; + + + typedef struct T2_Decoder_ + { + T2_Builder builder; + CFF_Font* cff; + + FT_Fixed stack[T2_MAX_OPERANDS + 1]; + FT_Fixed* top; + + T2_Decoder_Zone zones[T2_MAX_SUBRS_CALLS + 1]; + T2_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; + + } T2_Decoder; + + + LOCAL_DEF + void T2_Init_Decoder( T2_Decoder* decoder, + TT_Face face, + T2_Size size, + T2_GlyphSlot slot ); + + LOCAL_DEF + void T2_Prepare_Decoder( T2_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 */ + LOCAL_DEF + FT_Error T2_Compute_Max_Advance( TT_Face face, + FT_Int* max_advance ); + +#endif /* 0 */ + + LOCAL_DEF + FT_Error T2_Parse_CharStrings( T2_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ); + + LOCAL_DEF + FT_Error T2_Load_Glyph( T2_GlyphSlot glyph, + T2_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2GLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cff/t2load.c b/reactos/subsys/win32k/freetype/src/cff/t2load.c new file mode 100644 index 00000000000..4a776933181 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2load.c @@ -0,0 +1,757 @@ +/***************************************************************************/ +/* */ +/* t2load.c */ +/* */ +/* TrueType glyph data/program tables loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2load.h" +#include "t2parse.h" + +#else + +#include +#include + +#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_t2load + + + /* read a CFF offset from memory */ + static + FT_ULong t2_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 t2_new_cff_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] = t2_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 */ + (void)FILE_Skip( data_size ); + } + } + + Exit: + if ( error ) + FREE( index->offsets ); + + return error; + } + + + static + void t2_done_cff_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 t2_explicit_cff_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; + } + + + LOCAL_FUNC + FT_Error T2_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; + + + 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 = T2_Err_Invalid_Argument; + + Exit: + return error; + } + + + LOCAL_FUNC + void T2_Forget_Element( CFF_Index* index, + FT_Byte** pbytes ) + { + if ( index->bytes == 0 ) + { + FT_Stream stream = index->stream; + + + RELEASE_Frame( *pbytes ); + } + } + + + LOCAL_FUNC + FT_String* T2_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 = T2_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; + } + T2_Forget_Element( index, &bytes ); + + Exit: + return name; + } + + + LOCAL_FUNC + FT_String* T2_Get_String( CFF_Index* index, + FT_UInt sid, + PSNames_Interface* interface ) + { + /* if it is not a standard string, return it */ + if ( sid > 390 ) + return T2_Get_Name( index, sid - 390 ); + + /* 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 = T2_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + LOCAL_FUNC + 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 + 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; + T2_Parser parser; + FT_Byte* dict; + FT_ULong dict_len; + CFF_Font_Dict* top = &font->font_dict; + CFF_Private* priv = &font->private_dict; + + + T2_Parser_Init( &parser, T2CODE_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 = T2_Access_Element( index, font_index, &dict, &dict_len ) || + T2_Parser_Run( &parser, dict, dict + dict_len ); + + T2_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; + + T2_Parser_Init( &parser, T2CODE_PRIVATE, priv ); + + if ( FILE_Seek( base_offset + font->font_dict.private_offset ) || + ACCESS_Frame( font->font_dict.private_size ) ) + goto Exit; + + error = T2_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 = t2_new_cff_index( &font->local_subrs_index, stream, 1 ); + if ( error ) + goto Exit; + + font->num_local_subrs = font->local_subrs_index.count; + error = t2_explicit_cff_index( &font->local_subrs_index, + &font->local_subrs ); + } + + Exit: + return error; + } + + + static + void CFF_Done_SubFont( FT_Memory memory, + CFF_SubFont* subfont ) + { + if ( subfont ) + { + t2_done_cff_index( &subfont->local_subrs_index ); + FREE( subfont->local_subrs ); + } + } + + + LOCAL_FUNC + FT_Error T2_Load_CFF_Font( FT_Stream stream, + FT_Int face_index, + CFF_Font* font ) + { + static const FT_Frame_Field cff_header_fields[] = + { + FT_FRAME_START( 4 ), + FT_FRAME_BYTE( CFF_Font, version_major ), + FT_FRAME_BYTE( CFF_Font, version_minor ), + FT_FRAME_BYTE( CFF_Font, header_size ), + FT_FRAME_BYTE( CFF_Font, 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 = FT_Err_Unknown_File_Format; + goto Exit; + } + + /* skip the rest of the header */ + (void)FILE_Skip( font->header_size - 4 ); + + /* read the name, top dict, string and global subrs index */ + error = t2_new_cff_index( &font->name_index, stream, 0 ) || + t2_new_cff_index( &font->font_dict_index, stream, 0 ) || + t2_new_cff_index( &font->string_index, stream, 0 ) || + t2_new_cff_index( &font->global_subrs_index, stream, 1 ); + if ( error ) + 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(( "T2_Load_CFF_Font: incorrect face index = %d\n", + face_index )); + error = T2_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 = t2_new_cff_index( &fd_index, stream, 0 ); + if ( error ) + goto Exit; + + if ( fd_index.count > CFF_MAX_CID_FONTS ) + { + FT_ERROR(( "T2_Load_CFF_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: + t2_done_cff_index( &fd_index ); + + if ( error ) + goto Exit; + } + else + font->num_subfonts = 0; + + /* read the charstrings index now */ + if ( dict->charstrings_offset == 0 ) + { + FT_ERROR(( "T2_Load_CFF_Font: no charstrings offset!\n" )); + error = FT_Err_Unknown_File_Format; + goto Exit; + } + + if ( FILE_Seek( base_offset + dict->charstrings_offset ) ) + goto Exit; + + error = t2_new_cff_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 = t2_explicit_cff_index( &font->global_subrs_index, + &font->global_subrs ) ; + + if ( error ) + goto Exit; + + /* get the font name */ + font->font_name = T2_Get_Name( &font->name_index, face_index ); + + Exit: + return error; + } + + + LOCAL_FUNC + void T2_Done_CFF_Font( CFF_Font* font ) + { + FT_Memory memory = font->memory; + FT_UInt index; + + + t2_done_cff_index( &font->global_subrs_index ); + t2_done_cff_index( &font->string_index ); + t2_done_cff_index( &font->font_dict_index ); + t2_done_cff_index( &font->name_index ); + t2_done_cff_index( &font->charstrings_index ); + + /* release font dictionaries */ + for ( index = 0; index < font->num_subfonts; index++ ) + CFF_Done_SubFont( memory, font->subfonts[index] ); + + 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/reactos/subsys/win32k/freetype/src/cff/t2load.h b/reactos/subsys/win32k/freetype/src/cff/t2load.h new file mode 100644 index 00000000000..7ebc76d27d3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2load.h @@ -0,0 +1,69 @@ +/***************************************************************************/ +/* */ +/* t2load.h */ +/* */ +/* OpenType glyph data/program tables loader (specification). */ +/* */ +/* Copyright 1996-2000 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 T2LOAD_H +#define T2LOAD_H + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + LOCAL_DEF + FT_String* T2_Get_Name( CFF_Index* index, + FT_UInt element ); + + LOCAL_DEF + FT_String* T2_Get_String( CFF_Index* index, + FT_UInt sid, + PSNames_Interface* interface ); + + LOCAL_DEF + FT_Error T2_Access_Element( CFF_Index* index, + FT_UInt element, + FT_Byte** pbytes, + FT_ULong* pbyte_len ); + + LOCAL_DEF + void T2_Forget_Element( CFF_Index* index, + FT_Byte** pbytes ); + + LOCAL_DEF + FT_Error T2_Load_CFF_Font( FT_Stream stream, + FT_Int face_index, + CFF_Font* font ); + + LOCAL_DEF + void T2_Done_CFF_Font( CFF_Font* font ); + + LOCAL_DEF + FT_Byte CFF_Get_FD( CFF_FD_Select* select, + FT_UInt glyph_index ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2LOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cff/t2objs.c b/reactos/subsys/win32k/freetype/src/cff/t2objs.c new file mode 100644 index 00000000000..1d59a585f7e --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2objs.c @@ -0,0 +1,600 @@ +/***************************************************************************/ +/* */ +/* t2objs.c */ +/* */ +/* OpenType objects manager (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2objs.h" +#include "t2load.h" + +#else + +#include +#include + +#endif + + +#include + +#include /* 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_t2objs + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + static + FT_String* T2_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( T2_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 = T2_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] = T2_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] = T2_Get_String( &font->string_index, + first, + psnames ); + gname++; + first++; + } + } + break; + } + + default: /* unknown charset format! */ + FT_ERROR(( "CFF: unknown charset format!\n" )); + error = T2_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Face */ + /* */ + /* */ + /* Initializes a given OpenType face object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_DEF + FT_Error T2_Init_Face( FT_Stream stream, + T2_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 T2_Err_Ok; + + sfnt_format = 1; + + /* now, the font can be either an OpenType/CFF font, or a 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: for now, we don't load the GPOS table, as OpenType Layout */ + /* support will be added later to FreeType 2 as a separate module */ + } + + /* 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 */ + (void)FILE_Seek( 0 ); + error = FT_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; + FT_ULong base_offset; + + + if ( ALLOC( cff, sizeof ( *cff ) ) ) + goto Exit; + + base_offset = FILE_Pos(); + + face->extra.data = cff; + error = T2_Load_CFF_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(( "T2_Init_Face:" )); + FT_ERROR(( " cannot open CFF & CEF fonts\n" )); + FT_ERROR(( " " )); + FT_ERROR(( " without the `PSNames' module\n" )); + goto Bad_Format; + } + + /* 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->units_per_EM = (FT_UInt)FT_DivFix( 1000L << 16, + dict->font_matrix.yy ) >> 16; + root->bbox = dict->font_bbox; + root->ascender = (FT_Short)root->bbox.yMax; + root->descender = (FT_Short)root->bbox.yMin; + + /* retrieve font family & style name */ + root->family_name = T2_Get_Name( &cff->name_index, face_index ); + if ( dict->cid_registry ) + { + root->style_name = T2_StrCopy( memory, "Regular" ); /* XXXX */ + } + else + { + root->style_name = T2_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; + +/* XXXX: 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 + + 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 = platform; + charmap->root.encoding_id = 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 = FT_Err_Unknown_File_Format; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Done_Face */ + /* */ + /* */ + /* Finalizes a given face object. */ + /* */ + /* */ + /* face :: A pointer to the face object to destroy. */ + /* */ + LOCAL_DEF + void T2_Done_Face( T2_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 ) + { + T2_Done_CFF_Font( cff ); + FREE( face->extra.data ); + } + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Driver */ + /* */ + /* */ + /* Initializes a given OpenType driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T2_Init_Driver( T2_Driver driver ) + { + /* init extension registry if needed */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + + return TT_Init_Extensions( driver ); + +#else + + FT_UNUSED( driver ); + + return T2_Err_Ok; + +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Done_Driver */ + /* */ + /* */ + /* Finalizes a given OpenType driver. */ + /* */ + /* */ + /* driver :: A handle to the target OpenType driver. */ + /* */ + LOCAL_FUNC + void T2_Done_Driver( T2_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/reactos/subsys/win32k/freetype/src/cff/t2objs.h b/reactos/subsys/win32k/freetype/src/cff/t2objs.h new file mode 100644 index 00000000000..2602862751f --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2objs.h @@ -0,0 +1,148 @@ +/***************************************************************************/ +/* */ +/* t2objs.h */ +/* */ +/* OpenType objects manager (specification). */ +/* */ +/* Copyright 1996-2000 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 T2OBJS_H +#define T2OBJS_H + + +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Driver */ + /* */ + /* */ + /* A handle to an OpenType driver object. */ + /* */ + typedef struct T2_DriverRec_* T2_Driver; + + typedef TT_Face T2_Face; + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Size */ + /* */ + /* */ + /* A handle to an OpenType size object. */ + /* */ + typedef FT_Size T2_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* T2_GlyphSlot */ + /* */ + /* */ + /* A handle to an OpenType glyph slot object. */ + /* */ + typedef struct T2_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + + FT_Bool hint; + FT_Bool scaled; + + FT_Fixed x_scale; + FT_Fixed y_scale; + + } T2_GlyphSlotRec, *T2_GlyphSlot; + + + + /*************************************************************************/ + /* */ + /* Subglyph transformation record. */ + /* */ + typedef struct T2_Transform_ + { + FT_Fixed xx, xy; /* transformation matrix coefficients */ + FT_Fixed yx, yy; + FT_F26Dot6 ox, oy; /* offsets */ + + } T2_Transform; + + + /* this is only used in the case of a pure CFF font with no charmap */ + typedef struct T2_CharMapRec_ + { + TT_CharMapRec root; + PS_Unicodes unicodes; + + } T2_CharMapRec, *T2_CharMap; + + + /***********************************************************************/ + /* */ + /* TrueType driver class. */ + /* */ + typedef struct T2_DriverRec_ + { + FT_DriverRec root; + + void* extension_component; + + } T2_DriverRec; + + + /*************************************************************************/ + /* */ + /* Face functions */ + /* */ + LOCAL_DEF + FT_Error T2_Init_Face( FT_Stream stream, + T2_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void T2_Done_Face( T2_Face face ); + + + /*************************************************************************/ + /* */ + /* Driver functions */ + /* */ + LOCAL_DEF + FT_Error T2_Init_Driver( T2_Driver driver ); + + LOCAL_DEF + void T2_Done_Driver( T2_Driver driver ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2OBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cff/t2parse.c b/reactos/subsys/win32k/freetype/src/cff/t2parse.c new file mode 100644 index 00000000000..7d62fef5b67 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2parse.c @@ -0,0 +1,641 @@ +/***************************************************************************/ +/* */ +/* t2parse.c */ +/* */ +/* OpenType parser (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t2parse.h" + +#else + +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* 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_t2parse + + +#define T2_Err_Stack_Underflow FT_Err_Invalid_Argument +#define T2_Err_Syntax_Error FT_Err_Invalid_Argument + + + enum + { + t2_kind_none = 0, + t2_kind_num, + t2_kind_fixed, + t2_kind_string, + t2_kind_bool, + t2_kind_delta, + t2_kind_callback, + + t2_kind_max /* do not remove */ + }; + + + /* now generate handlers for the most simple fields */ + typedef FT_Error (*T2_Field_Reader)( T2_Parser* parser ); + + typedef struct T2_Field_Handler_ + { + int kind; + int code; + FT_UInt offset; + FT_Byte size; + T2_Field_Reader reader; + FT_UInt array_max; + FT_UInt count_offset; + + } T2_Field_Handler; + + + LOCAL_FUNC + void T2_Parser_Init( T2_Parser* parser, + FT_UInt code, + void* object ) + { + MEM_Set( parser, 0, sizeof ( *parser ) ); + + parser->top = parser->stack; + parser->object_code = code; + parser->object = object; + } + + + /* reads an integer */ + static + FT_Long parse_t2_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 parse_t2_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_Byte nib; + FT_Byte phase; + + + result = 0; + num = 0; + divider = 1; + + /* first of all, read the integer part */ + phase = 4; + p--; + + for (;;) + { + /* read one nibble at a time */ + if ( phase && ++p >= limit ) + goto Bad; + + 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 (;;) + { + /* read one nibble at a time */ + if ( !phase && ++p >= limit ) + goto Bad; + + phase = 4 - phase; + nib = ( p[0] >> phase ) & 0xF; + + 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 (;;) + { + /* read one nibble at a time */ + if ( !phase && ++p >= limit ) + goto Bad; + + phase = 4 - phase; + nib = ( p[0] >> phase ) & 0xF; + + 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++; + } + + 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 t2_parse_num( FT_Byte** d ) + { + return ( **d == 30 ? ( parse_t2_real( d[0], d[1], 0 ) >> 16 ) + : parse_t2_integer( d[0], d[1] ) ); + } + + + /* reads a floating point number, either integer or real */ + static + FT_Fixed t2_parse_fixed( FT_Byte** d ) + { + return ( **d == 30 ? parse_t2_real( d[0], d[1], 0 ) + : parse_t2_integer( d[0], d[1] ) << 16 ); + } + + + static + FT_Error parse_font_matrix( T2_Parser* parser ) + { + CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; + FT_Matrix* matrix = &dict->font_matrix; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 4 ) + { + matrix->xx = t2_parse_fixed( data++ ); + matrix->yx = t2_parse_fixed( data++ ); + matrix->xy = t2_parse_fixed( data++ ); + matrix->yy = t2_parse_fixed( data ); + error = T2_Err_Ok; + } + + return error; + } + + + static + FT_Error parse_font_bbox( T2_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 = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 4 ) + { + bbox->xMin = t2_parse_num( data++ ); + bbox->yMin = t2_parse_num( data++ ); + bbox->xMax = t2_parse_num( data++ ); + bbox->yMax = t2_parse_num( data ); + error = T2_Err_Ok; + } + + return error; + } + + + static + FT_Error parse_private_dict( T2_Parser* parser ) + { + CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 2 ) + { + dict->private_size = t2_parse_num( data++ ); + dict->private_offset = t2_parse_num( data ); + error = T2_Err_Ok; + } + + return error; + } + + + static + FT_Error parse_cid_ros( T2_Parser* parser ) + { + CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 3 ) + { + dict->cid_registry = (FT_UInt)t2_parse_num( data++ ); + dict->cid_ordering = (FT_UInt)t2_parse_num( data++ ); + dict->cid_supplement = (FT_ULong)t2_parse_num( data ); + error = T2_Err_Ok; + } + + return error; + } + + +#define T2_FIELD_NUM( code, name ) \ + T2_FIELD( code, name, t2_kind_num ) +#define T2_FIELD_FIXED( code, name ) \ + T2_FIELD( code, name, t2_kind_fixed ) +#define T2_FIELD_STRING( code, name ) \ + T2_FIELD( code, name, t2_kind_string ) +#define T2_FIELD_BOOL( code, name ) \ + T2_FIELD( code, name, t2_kind_bool ) +#define T2_FIELD_DELTA( code, name,max ) \ + T2_FIELD( code, name, t2_kind_delta ) + +#define T2_REF( s, f ) ( ((s*)0)->f ) + +#define T2_FIELD_CALLBACK( code, name ) \ + { \ + t2_kind_callback, \ + code | T2CODE, \ + 0, 0, \ + parse_ ## name, \ + 0, 0 \ + }, + +#undef T2_FIELD +#define T2_FIELD( code, name, kind ) \ + { \ + kind, \ + code | T2CODE, \ + (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \ + sizeof( T2_REF( T2TYPE, name ) ), \ + 0, 0, 0 \ + }, + +#undef T2_FIELD_DELTA +#define T2_FIELD_DELTA( code, name, max ) \ + { \ + t2_kind_delta, \ + code | T2CODE, \ + (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \ + sizeof( T2_REF( T2TYPE, name )[0] ), \ + 0, \ + max, \ + (FT_UInt)(char*)&T2_REF( T2TYPE, num_ ## name ) \ + }, + +#define T2CODE_TOPDICT 0x1000 +#define T2CODE_PRIVATE 0x2000 + + static const T2_Field_Handler t2_field_handlers[] = + { + +#ifdef FT_FLAT_COMPILE + +#include "t2tokens.h" + +#else + +#include + +#endif + + { 0, 0, 0, 0, 0, 0, 0 } + }; + + + LOCAL_FUNC + FT_Error T2_Parser_Run( T2_Parser* parser, + FT_Byte* start, + FT_Byte* limit ) + { + FT_Byte* p = start; + FT_Error error = T2_Err_Ok; + + + parser->top = parser->stack; + parser->start = start; + parser->limit = limit; + parser->cursor = start; + + while ( p < limit ) + { + FT_Byte v = *p; + + + if ( v >= 27 && v != 31 ) + { + /* it's a number; we will push its position on the stack */ + if ( parser->top - parser->stack >= T2_MAX_STACK_DEPTH ) + goto Stack_Overflow; + + *parser->top ++ = p; + + /* now, skip it */ + if ( v == 30 ) + { + /* skip real number */ + for (;;) + { + if ( p >= limit ) + goto Syntax_Error; + v = p[0] >> 4; + if ( v == 15 ) + break; + v = p[0] & 0xF; + if ( v == 15 ) + break; + p++; + } + 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 T2_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 = t2_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 t2_kind_bool: + case t2_kind_string: + case t2_kind_num: + val = t2_parse_num( parser->stack ); + goto Store_Number; + + case t2_kind_fixed: + val = t2_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 t2_kind_delta: + { + FT_Byte* qcount = (FT_Byte*)parser->object + + field->count_offset; + + FT_Long val; + 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 += t2_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 = T2_Err_Invalid_Argument; + goto Exit; + + Stack_Underflow: + error = T2_Err_Invalid_Argument; + goto Exit; + + Syntax_Error: + error = T2_Err_Invalid_Argument; + goto Exit; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cff/t2parse.h b/reactos/subsys/win32k/freetype/src/cff/t2parse.h new file mode 100644 index 00000000000..2238444b7a1 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2parse.h @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* t2parse.h */ +/* */ +/* OpenType parser (specification). */ +/* */ +/* Copyright 1996-2000 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 T2PARSE_H +#define T2PARSE_H + +#include +#include + +#define T2_MAX_STACK_DEPTH 96 + +#define T2CODE_TOPDICT 0x1000 +#define T2CODE_PRIVATE 0x2000 + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct T2_Parser_ + { + FT_Byte* start; + FT_Byte* limit; + FT_Byte* cursor; + + FT_Byte* stack[T2_MAX_STACK_DEPTH + 1]; + FT_Byte** top; + + FT_UInt object_code; + void* object; + + } T2_Parser; + + + LOCAL_DEF + void T2_Parser_Init( T2_Parser* parser, + FT_UInt code, + void* object ); + + LOCAL_DEF + FT_Error T2_Parser_Run( T2_Parser* parser, + FT_Byte* start, + FT_Byte* limit ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2PARSE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cff/t2tokens.h b/reactos/subsys/win32k/freetype/src/cff/t2tokens.h new file mode 100644 index 00000000000..13a15e43df3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cff/t2tokens.h @@ -0,0 +1,96 @@ +/***************************************************************************/ +/* */ +/* t2tokens.h */ +/* */ +/* OpenType token definitions (specification only). */ +/* */ +/* Copyright 1996-2000 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 T2TYPE +#undef T2CODE +#define T2TYPE CFF_Font_Dict +#define T2CODE T2CODE_TOPDICT + + T2_FIELD_STRING ( 0, version ) + T2_FIELD_STRING ( 1, notice ) + T2_FIELD_STRING ( 0x100, copyright ) + T2_FIELD_STRING ( 2, full_name ) + T2_FIELD_STRING ( 3, family_name ) + T2_FIELD_STRING ( 4, weight ) + T2_FIELD_BOOL ( 0x101, is_fixed_pitch ) + T2_FIELD_FIXED ( 0x102, italic_angle ) + T2_FIELD_NUM ( 0x103, underline_position ) + T2_FIELD_NUM ( 0x104, underline_thickness ) + T2_FIELD_NUM ( 0x105, paint_type ) + T2_FIELD_NUM ( 0x106, charstring_type ) + T2_FIELD_CALLBACK( 0x107, font_matrix ) + T2_FIELD_NUM ( 13, unique_id ) + T2_FIELD_CALLBACK( 5, font_bbox ) + T2_FIELD_NUM ( 0x108, stroke_width ) + T2_FIELD_NUM ( 15, charset_offset ) + T2_FIELD_NUM ( 16, encoding_offset ) + T2_FIELD_NUM ( 17, charstrings_offset ) + T2_FIELD_CALLBACK( 18, private_dict ) + T2_FIELD_NUM ( 0x114, synthetic_base ) + T2_FIELD_STRING ( 0x115, postscript ) + T2_FIELD_STRING ( 0x116, base_font_name ) + +#if 0 + T2_FIELD_DELTA ( 0x117, base_font_blend, 16 ) + T2_FIELD_CALLBACK( 0x118, multiple_master ) + T2_FIELD_CALLBACK( 0x119, blend_axit_types ) +#endif + + T2_FIELD_CALLBACK( 0x11E, cid_ros ) + T2_FIELD_NUM ( 0x11F, cid_font_version ) + T2_FIELD_NUM ( 0x120, cid_font_revision ) + T2_FIELD_NUM ( 0x121, cid_font_type ) + T2_FIELD_NUM ( 0x122, cid_count ) + T2_FIELD_NUM ( 0x123, cid_uid_base ) + T2_FIELD_NUM ( 0x124, cid_fd_array_offset ) + T2_FIELD_NUM ( 0x125, cid_fd_select_offset ) + T2_FIELD_STRING ( 0x126, cid_font_name ) + +#if 0 + T2_FIELD_NUM ( 0x127, chameleon ) +#endif + + +#undef T2TYPE +#undef T2CODE +#define T2TYPE CFF_Private +#define T2CODE T2CODE_PRIVATE + + T2_FIELD_DELTA( 6, blue_values, 14 ) + T2_FIELD_DELTA( 7, other_blues, 10 ) + T2_FIELD_DELTA( 8, family_blues, 14 ) + T2_FIELD_DELTA( 9, family_other_blues, 10 ) + T2_FIELD_FIXED( 0x109, blue_scale ) + T2_FIELD_NUM ( 0x10A, blue_shift ) + T2_FIELD_NUM ( 0x10B, blue_fuzz ) + T2_FIELD_NUM ( 10, standard_width ) + T2_FIELD_NUM ( 11, standard_height ) + T2_FIELD_DELTA( 0x10C, snap_widths, 13 ) + T2_FIELD_DELTA( 0x10D, snap_heights, 13 ) + T2_FIELD_BOOL ( 0x10E, force_bold ) + T2_FIELD_FIXED( 0x10F, force_bold_threshold ) + T2_FIELD_NUM ( 0x110, lenIV ) + T2_FIELD_NUM ( 0x111, language_group ) + T2_FIELD_FIXED( 0x112, expansion_factor ) + T2_FIELD_NUM ( 0x113, initial_random_seed ) + T2_FIELD_NUM ( 19, local_subrs_offset ) + T2_FIELD_NUM ( 20, default_width ) + T2_FIELD_NUM ( 21, nominal_width ) + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/cidafm.c b/reactos/subsys/win32k/freetype/src/cid/cidafm.c new file mode 100644 index 00000000000..b5638836eac --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidafm.c @@ -0,0 +1,293 @@ +/***************************************************************************/ +/* */ +/* cidafm.c */ +/* */ +/* AFM support for CID-keyed fonts (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "cidafm.h" + +#else + +#include + +#endif + + +#include +#include +#include + +#include /* for qsort() */ +#include /* for strcmp() */ +#include /* 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_cidafm + + + LOCAL_FUNC + void CID_Done_AFM( FT_Memory memory, + CID_AFM* afm ) + { + FREE( afm->kern_pairs ); + afm->num_pairs = 0; + } + + +#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 = 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 */ + static + int compare_kern_pairs( const void* a, + const void* b ) + { + CID_Kern_Pair* pair1 = (CID_Kern_Pair*)a; + CID_Kern_Pair* pair2 = (CID_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 */ + LOCAL_FUNC + FT_Error CID_Read_AFM( FT_Face cid_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; + CID_Kern_Pair* pair; + T1_Font* type1 = &((T1_Face)t1_face)->type1; + CID_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 occurrences 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, CID_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; + + 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 ( CID_Kern_Pair ), + compare_kern_pairs ); + + Exit: + if ( error ) + FREE( afm ); + + FORGET_Frame(); + + return error; + } + + + /* find the kerning for a given glyph pair */ + LOCAL_FUNC + void CID_Get_Kerning( CID_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + CID_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/reactos/subsys/win32k/freetype/src/cid/cidafm.h b/reactos/subsys/win32k/freetype/src/cid/cidafm.h new file mode 100644 index 00000000000..542604e0ddb --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidafm.h @@ -0,0 +1,78 @@ +/***************************************************************************/ +/* */ +/* cidafm.h */ +/* */ +/* AFM support for CID-keyed fonts (specification). */ +/* */ +/* Copyright 1996-2000 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 CIDAFM_H +#define CIDAFM_H + + +#ifdef FT_FLAT_COMPILE + +#include "cidobjs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct CID_Kern_Pair_ + { + FT_UInt glyph1; + FT_UInt glyph2; + FT_Vector kerning; + + } CID_Kern_Pair; + + typedef struct CID_AFM_ + { + FT_UInt num_pairs; + CID_Kern_Pair* kern_pairs; + + } CID_AFM; + + + LOCAL_DEF + FT_Error CID_Read_AFM( FT_Face cid_face, + FT_Stream stream ); + + LOCAL_DEF + void CID_Done_AFM( FT_Memory memory, + CID_AFM* afm ); + + LOCAL_DEF + void CID_Get_Kerning( CID_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDAFM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/cidgload.c b/reactos/subsys/win32k/freetype/src/cid/cidgload.c new file mode 100644 index 00000000000..97c9252be2a --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidgload.c @@ -0,0 +1,1558 @@ +/***************************************************************************/ +/* */ +/* cidgload.c */ +/* */ +/* CID-keyed Type1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "cidload.h" +#include "cidgload.h" + +#else + +#include +#include + +#endif + + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /* forward */ + static + FT_Error cid_load_glyph( CID_Decoder* decoder, + FT_UInt glyph_index ); + + + typedef enum CID_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 */ + + } CID_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 */ + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + LOCAL_FUNC + void CID_Init_Builder( CID_Builder* builder, + CID_Face face, + CID_Size size, + CID_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.loader; + + + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; + + FT_GlyphLoader_Rewind( loader ); + } + + if ( size ) + { + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.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; + + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Builder */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + LOCAL_FUNC + void CID_Done_Builder( CID_Builder* builder ) + { + CID_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + LOCAL_FUNC + void CID_Init_Decoder( CID_Decoder* decoder ) + { + MEM_Set( decoder, 0, sizeof ( *decoder ) ); + + decoder->font_matrix.xx = 0x10000L; + decoder->font_matrix.yy = 0x10000L; + } + + + /* check that there is enough space for `count' more points */ + static + FT_Error check_points( CID_Builder* builder, + FT_Int count ) + { + return FT_GlyphLoader_Check_Points( builder->loader, count, 0 ); + } + + + /* add a new point, but do not check space */ + static + void add_point( CID_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; + point->y = y; + *control = 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( CID_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( CID_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return T1_Err_Ok; + } + + error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + + outline->n_contours++; + } + return error; + } + + + /* if a path has been started, add its first on-curve point */ + static + FT_Error start_point( CID_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + FT_Error error; + + + builder->path_begun = 1; + error = add_contour( builder ); + if ( error ) + return error; + } + + return add_point1( builder, x, y ); + } + + + /* close the current contour */ + static + void close_contour( CID_Builder* builder ) + { + FT_Outline* outline = builder->current; + + + /* XXX: 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; + + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + } + + +#if 0 + + + /*************************************************************************/ + /* */ + /* */ + /* lookup_glyph_by_stdcharcode */ + /* */ + /* */ + /* Looks up a given glyph by its StandardEncoding charcode. Used */ + /* to implement the SEAC Type 1 operator. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + static + FT_Int lookup_glyph_by_stdcharcode( CID_Face face, + FT_Int charcode ) + { + FT_Int n; + const FT_String* glyph_name; + PSNames_Interface* psnames = (PSNames_Interface*)face->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 < face->cid.cid_count; n++ ) + { + FT_String* name = (FT_String*)face->type1.glyph_names[n]; + + + if ( name && strcmp( name, glyph_name ) == 0 ) + return n; + } + + return -1; + } + + +#endif /* 0 */ + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_seac */ + /* */ + /* */ + /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error t1operator_seac( CID_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; + + + bchar_index = bchar; + achar_index = achar; + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return T1_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->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->current.subglyphs; + glyph->format = ft_glyph_format_composite; + + loader->current.num_subglyphs = 2; + } + + /* First load `bchar' in builder */ + /* now load the unscaled outline */ + if ( decoder->builder.loader ) + FT_GlyphLoader_Prepare( decoder->builder.loader ); + + error = cid_load_glyph( decoder, bchar_index ); /* load one glyph */ + 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 = cid_load_glyph( decoder, achar_index ); + if ( error ) + return error; + + /* 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 = base->n_points - n_base_points; + dummy.points = base->points + n_base_points; + FT_Outline_Translate( &dummy, adx - asb, ady ); + } + } + + Exit: + return error; + } + + +#define USE_ARGS( n ) do \ + { \ + top -= n; \ + if ( top < decoder->stack ) \ + goto Stack_Underflow; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given CID charstrings program. */ + /* */ + /* */ + /* decoder :: The current CID decoder. */ + /* */ + /* */ + /* charstring_base :: The base of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error CID_Parse_CharStrings( CID_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ) + { + FT_Error error; + CID_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + CID_Builder* builder = &decoder->builder; + FT_Outline* outline; + FT_Pos x, y; + + + /* 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 = T1_Err_Ok; + outline = builder->current; + + x = builder->pos_x; + y = builder->pos_y; + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Int* top = decoder->top; + CID_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(( "CID_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(( "CID_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + break; + + case 255: /* four bytes integer */ + if ( ip + 4 > limit ) + { + FT_ERROR(( "CID_Parse_CharStrings: unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = ( (long)ip[0] << 24 ) | + ( (long)ip[1] << 16 ) | + ( (long)ip[2] << 8 ) | + ip[3]; + ip += 4; + break; + + default: + if ( ip[-1] >= 32 ) + { + if ( ip[-1] < 247 ) + value = (long)ip[-1] - 139; + else + { + if ( ++ip > limit ) + { + FT_ERROR(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + if ( ip[-2] < 251 ) + value = ( (long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108; + else + value = -( ( ( (long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 ); + } + } + else + { + FT_ERROR(( "CID_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(( "CID_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(( "CID_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(( "CID_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(( "CID_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if ( ip[0] != 12 || ip[1] != 17 ) + { + FT_ERROR(( "CID_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; + +#if 0 + + case 14: + case 15: + case 16: + case 17: + case 18: /* multiple masters */ + { + T1_Blend* blend = decoder->blend; + FT_UInt num_points, nn, mm; + FT_Int* delta; + FT_Int* values; + + + if ( !blend ) + { + FT_ERROR(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " unexpected multiple masters operator!\n" )); + goto Syntax_Error; + } + + num_points = top[1] - 13 + ( top[1] == 18 ); + if ( top[0] != num_points * blend->num_designs ) + { + FT_ERROR(( "CID_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 x = values[0]; + + + for ( mm = 1; mm < blend->num_designs; mm++ ) + x += FT_MulFix( *delta++, blend->weight_vector[mm] ); + + *values++ = x; + } + /* note that `top' will be incremented later by calls to `pop' */ + } + break; + +#endif + + default: + Unexpected_OtherSubr: + FT_ERROR(( "CID_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 T1_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 T1_Err_Ok; + + break; + + case op_seac: + /* return immediately after 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 T1_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]; + 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]; + 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]; + break; + + case op_div: + FT_TRACE4(( " div" )); + + if ( top[1] ) + { + *top = top[0] / top[1]; + top++; + } + else + { + FT_ERROR(( "CID_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->subrs->num_subrs ) + { + FT_ERROR(( "CID_Parse_CharStrings: invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "CID_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = decoder->subrs->code[index] + decoder->lenIV; + zone->limit = decoder->subrs->code[index + 1]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "CID_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(( "CID_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(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + + default: + FT_ERROR(( "CID_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 T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + + Memory_Error: + return builder->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. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error CID_Compute_Max_Advance( CID_Face face, + FT_Int* max_advance ) + { + FT_Error error; + CID_Decoder decoder; + FT_Int glyph_index; + + + *max_advance = 0; + + /* Initialize load decoder */ + CID_Init_Decoder( &decoder ); + CID_Init_Builder( &decoder.builder, 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++ ) + { + /* 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 T1_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. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error cid_load_glyph( CID_Decoder* decoder, + FT_UInt glyph_index ) + { + CID_Face 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; + FT_Byte* charstring; + FT_UInt lenIV; + FT_Memory memory = face->root.memory; + + + /* setup subrs */ + decoder->subrs = face->subrs + fd_select; + + /* setup font matrix */ + dict = cid->font_dicts + fd_select; + decoder->font_matrix = dict->font_matrix; + lenIV = dict->private_dict.lenIV; + decoder->lenIV = 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 ) ) + { + cid_decrypt( charstring, glyph_len, 4330 ); + error = CID_Parse_CharStrings( decoder, + charstring + lenIV, + glyph_len - lenIV ); + } + + FREE( charstring ); + } + + Exit: + return error; + } + + + LOCAL_FUNC + FT_Error CID_Load_Glyph( CID_GlyphSlot glyph, + CID_Size size, + FT_Int glyph_index, + FT_Int load_flags ) + { + FT_Error error; + CID_Decoder decoder; + CID_Face face = (CID_Face)glyph->root.face; + FT_Bool hinting; + + + 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 = ( load_flags & FT_LOAD_NO_SCALE ) == 0 && + ( load_flags & FT_LOAD_NO_HINTING ) == 0; + + glyph->root.format = ft_glyph_format_outline; + + { + CID_Init_Decoder( &decoder ); + CID_Init_Builder( &decoder.builder, face, size, glyph ); + + /* set up the decoder */ + decoder.builder.no_recurse = + (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE ); + + error = cid_load_glyph( &decoder, glyph_index ); + + /* save new glyph tables */ + CID_Done_Builder( &decoder.builder ); + } + + /* 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 the left side bearing and the */ + /* advance width */ + if ( load_flags & FT_LOAD_NO_RECURSE ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.builder.advance.x; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.format = ft_glyph_format_outline; + + glyph->root.outline.flags &= ft_outline_owner; + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= ft_outline_high_precision; + + glyph->root.outline.flags |= ft_outline_reverse_fill; + +#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 + + 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 ); + } + + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, &decoder.font_matrix ); + + /* 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/reactos/subsys/win32k/freetype/src/cid/cidgload.h b/reactos/subsys/win32k/freetype/src/cid/cidgload.h new file mode 100644 index 00000000000..5f3913d5270 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidgload.h @@ -0,0 +1,198 @@ +/***************************************************************************/ +/* */ +/* cidgload.h */ +/* */ +/* OpenType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "cidobjs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* 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 CID_Builder_ + { + FT_Memory memory; + CID_Face face; + CID_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; + + } CID_Builder; + + + /* execution context charstring zone */ + + typedef struct CID_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } CID_Decoder_Zone; + + + typedef struct CID_Decoder_ + { + CID_Builder builder; + + FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS]; + FT_Int* top; + + CID_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1]; + CID_Decoder_Zone* zone; + + FT_Matrix font_matrix; + CID_Subrs* subrs; + FT_UInt lenIV; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + } CID_Decoder; + + + LOCAL_DEF + void CID_Init_Builder( CID_Builder* builder, + CID_Face face, + CID_Size size, + CID_GlyphSlot glyph ); + + LOCAL_DEF + void CID_Done_Builder( CID_Builder* builder ); + + + LOCAL_DEF + void CID_Init_Decoder( CID_Decoder* decoder ); + + +#if 0 + + /* Compute the maximum advance width of a font through quick parsing */ + LOCAL_DEF + FT_Error CID_Compute_Max_Advance( CID_Face face, + FT_Int* max_advance ); + +#endif + + /* This function is exported, because it is used by the T1Dump utility */ + LOCAL_DEF + FT_Error CID_Parse_CharStrings( CID_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ); + + LOCAL_DEF + FT_Error CID_Load_Glyph( CID_GlyphSlot glyph, + CID_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDGLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/cidload.c b/reactos/subsys/win32k/freetype/src/cid/cidload.c new file mode 100644 index 00000000000..1f7c7aea013 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidload.c @@ -0,0 +1,537 @@ +/***************************************************************************/ +/* */ +/* cidload.c */ +/* */ +/* CID-keyed Type1 font loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "cidload.h" + +#else + +#include + +#endif + + +#include +#include /* 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 */ + LOCAL_FUNC + 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; + } + + + LOCAL_FUNC + void cid_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ) + { + while ( length > 0 ) + { + FT_Byte plain; + + + plain = ( *buffer ^ ( seed >> 8 ) ); + seed = ( *buffer + seed ) * 52845 + 22719; + *buffer++ = plain; + length--; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 1 SYMBOL PARSING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error cid_load_keyword( CID_Face face, + CID_Loader* loader, + const CID_Field_Rec* keyword ) + { + FT_Error error; + CID_Parser* parser = &loader->parser; + FT_Byte* object; + CID_Info* cid = &face->cid; + + + /* if the keyword has a dedicated callback, call it */ + if ( keyword->type == t1_field_callback ) + { + error = keyword->reader( face, parser ); + 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 = T1_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; + } + } + } + + /* 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( parser, keyword, object ); + else + error = CID_Load_Field( parser, keyword, object ); + + Exit: + return error; + } + + + static + FT_Error parse_font_bbox( CID_Face face, + CID_Parser* parser ) + { + FT_Short temp[4]; + FT_BBox* bbox = &face->cid.font_bbox; + + + (void)CID_ToCoordArray( parser, 4, temp ); + bbox->xMin = temp[0]; + bbox->yMin = temp[1]; + bbox->xMax = temp[2]; + bbox->yMax = temp[3]; + + return T1_Err_Ok; /* this is a callback function; */ + /* we must return an error code */ + } + + + static + FT_Error parse_font_matrix( CID_Face face, + CID_Parser* parser ) + { + FT_Matrix* matrix; + CID_FontDict* dict; + FT_Fixed temp[4]; + + + if ( parser->num_dict >= 0 ) + { + dict = face->cid.font_dicts + parser->num_dict; + matrix = &dict->font_matrix; + + (void)CID_ToFixedArray( parser, 4, temp, 3 ); + matrix->xx = temp[0]; + matrix->yx = temp[1]; + matrix->xy = temp[2]; + matrix->yy = temp[3]; + } + + return T1_Err_Ok; /* this is a callback function; */ + /* we must return an error code */ + } + + + static + 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 = T1_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 CID_Field_Rec t1_field_records[] = + { + +#ifdef FT_FLAT_COMPILE + +#include "cidtokens.h" + +#else + +#include + +#endif + + { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 } + }; + + + static + int is_alpha( char c ) + { + return ( isalnum( c ) || + c == '.' || + c == '_' ); + } + + + static + void skip_whitespace( CID_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + + + while ( cur < parser->limit && isspace( *cur ) ) + cur++; + + parser->cursor = cur; + } + + + static + FT_Error parse_dict( CID_Face face, + CID_Loader* loader, + FT_Byte* base, + FT_Long size ) + { + CID_Parser* parser = &loader->parser; + + + parser->cursor = base; + parser->limit = base + size; + parser->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 = cur2 - cur; + if ( len > 0 && len < 22 ) + { + /* now compare the immediate name to the keyword table */ + const CID_Field_Rec* keyword = t1_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->cursor = cur2; + skip_whitespace( parser ); + parser->error = cid_load_keyword( face, loader, keyword ); + if ( parser->error ) + return parser->error; + + cur = parser->cursor; + break; + } + } + keyword++; + } + } + } + } + } + return parser->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_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 */ + 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 ); + } + + + LOCAL_FUNC + 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 ); + if ( error ) + goto Exit; + + error = 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/reactos/subsys/win32k/freetype/src/cid/cidload.h b/reactos/subsys/win32k/freetype/src/cid/cidload.h new file mode 100644 index 00000000000..7495da0dc1e --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidload.h @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* cidload.h */ +/* */ +/* CID-keyed Type1 font loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "cidparse.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct CID_Loader_ + { + CID_Parser parser; /* parser used to read the stream */ + FT_Int num_chars; /* number of characters in encoding */ + + } CID_Loader; + + + LOCAL_DEF + FT_Long cid_get_offset( FT_Byte** start, + FT_Byte offsize ); + + LOCAL_DEF + void cid_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ); + + LOCAL_DEF + FT_Error CID_Open_Face( CID_Face face ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/cidobjs.c b/reactos/subsys/win32k/freetype/src/cid/cidobjs.c new file mode 100644 index 00000000000..a75567b6bfc --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidobjs.c @@ -0,0 +1,380 @@ +/***************************************************************************/ +/* */ +/* cidobjs.c */ +/* */ +/* CID objects manager (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "cidgload.h" +#include "cidload.h" + +#else + +#include +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* 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 */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Face */ + /* */ + /* */ + /* Finalizes a given face object. */ + /* */ + /* */ + /* face :: A pointer to the face object to destroy. */ + /* */ + LOCAL_FUNC + 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Face */ + /* */ + /* */ + /* Initializes a given CID face object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + + 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; + } + + /* 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 = 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->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 = "Regular"; + } + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox = face->cid.font_bbox; + root->units_per_EM = 1000; + root->ascender = (FT_Short)face->cid.font_bbox.yMax; + root->descender = -(FT_Short)face->cid.font_bbox.yMin; + root->height = ( ( 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->max_points = 0; + root->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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Driver */ + /* */ + /* */ + /* Initializes a given CID driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error CID_Init_Driver( CID_Driver driver ) + { + FT_UNUSED( driver ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Driver */ + /* */ + /* */ + /* Finalizes a given CID driver. */ + /* */ + /* */ + /* driver :: A handle to the target CID driver. */ + /* */ + LOCAL_DEF + void CID_Done_Driver( CID_Driver driver ) + { + FT_UNUSED( driver ); + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/cidobjs.h b/reactos/subsys/win32k/freetype/src/cid/cidobjs.h new file mode 100644 index 00000000000..c28c59be25e --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidobjs.h @@ -0,0 +1,141 @@ +/***************************************************************************/ +/* */ +/* cidobjs.h */ +/* */ +/* CID objects manager (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Driver */ + /* */ + /* */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct CID_DriverRec_* CID_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Size */ + /* */ + /* */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct CID_SizeRec_* CID_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_GlyphSlot */ + /* */ + /* */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct CID_GlyphSlotRec_* CID_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_CharMap */ + /* */ + /* */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* */ + /* 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; + + + LOCAL_DEF + FT_Error CID_Init_Face( FT_Stream stream, + CID_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void CID_Done_Face( CID_Face face ); + + + LOCAL_DEF + FT_Error CID_Init_Driver( CID_Driver driver ); + + LOCAL_DEF + void CID_Done_Driver( CID_Driver driver ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDOBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/cidparse.c b/reactos/subsys/win32k/freetype/src/cid/cidparse.c new file mode 100644 index 00000000000..33d3d8af3c3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidparse.c @@ -0,0 +1,1024 @@ +/***************************************************************************/ +/* */ +/* cidparse.c */ +/* */ +/* CID-keyed Type1 parser (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "cidparse.h" + +#else + +#include + +#endif + + +#include /* 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 + + +#if 0 + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** IMPLEMENTATION OF CID_TABLE OBJECT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_New_Table */ + /* */ + /* */ + /* Initializes a CID_Table. */ + /* */ + /* */ + /* table :: The address of the target table. */ + /* */ + /* */ + /* count :: The table size, i.e., the maximal number of elements. */ + /* */ + /* memory :: The memory object to be used for all subsequent */ + /* reallocations. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error CID_New_Table( CID_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 = 0xDEADBEEFL; + table->num_elems = 0; + table->block = 0; + table->capacity = 0; + table->cursor = 0; + + Exit: + if ( error ) + FREE( table->elements ); + + return error; + } + + + static + void shift_elements( CID_Table* table, + FT_Byte* old_base ) + { + FT_Long delta = table->block - old_base; + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + if ( delta ) + for ( ; offset < limit; offset++ ) + { + if ( offset[0] ) + offset[0] += delta; + } + } + + + static + FT_Error reallocate_t1_table( CID_Table* table, + FT_Int new_size ) + { + FT_Memory memory = table->memory; + FT_Byte* old_base = table->block; + FT_Error error; + + + /* realloc the base block */ + if ( REALLOC( table->block, table->capacity, new_size ) ) + return error; + + table->capacity = new_size; + + /* shift all offsets when needed */ + if ( old_base ) + shift_elements( table, old_base ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Add_Table */ + /* */ + /* */ + /* Adds an object to a CID_Table, possibly growing its memory block. */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* index :: The index of the object in the table. */ + /* */ + /* object :: The address of the object to copy in the memory. */ + /* */ + /* length :: The length in bytes of the source object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. An error is returned if */ + /* reallocation fails. */ + /* */ + LOCAL_FUNC + FT_Error CID_Add_Table( CID_Table* table, + FT_Int index, + void* object, + FT_Int length ) + { + if ( index < 0 || index > table->max_elems ) + { + FT_ERROR(( "CID_Add_Table: invalid index\n" )); + return T1_Err_Syntax_Error; + } + + /* grow the base block if needed */ + if ( table->cursor + length > table->capacity ) + { + FT_Error error; + FT_Int new_size = table->capacity; + + + while ( new_size < table->cursor + length ) + new_size += 1024; + + error = reallocate_t1_table( table, new_size ); + if ( error ) + return error; + } + + /* 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 T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Table */ + /* */ + /* */ + /* Finalizes a CID_Table (reallocate it to its current cursor). */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* 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. */ + /* */ + LOCAL_FUNC + void CID_Done_Table( CID_Table* table ) + { + FT_Memory memory = table->memory; + FT_Error error; + FT_Byte* old_base; + + + /* should never fail, as rec.cursor <= rec.size */ + old_base = table->block; + if ( !old_base ) + return; + + (void)REALLOC( table->block, table->capacity, table->cursor ); + table->capacity = table->cursor; + + if ( old_base != table->block ) + shift_elements( table, old_base ); + } + + + LOCAL_FUNC + void CID_Release_Table( CID_Table* table ) + { + FT_Memory memory = table->memory; + + + if ( table->init == 0xDEADBEEFL ) + { + FREE( table->block ); + FREE( table->elements ); + FREE( table->lengths ); + table->init = 0; + } + } + +#endif /* 0 */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** INPUT STREAM PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define IS_CID_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' ) +#define IS_CID_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' ) + +#define IS_CID_SPACE( c ) ( IS_CID_WHITESPACE( c ) || IS_CID_LINESPACE( c ) ) + + + LOCAL_FUNC + void CID_Skip_Spaces( CID_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( !IS_CID_SPACE( c ) ) + break; + cur++; + } + + parser->cursor = cur; + } + + + LOCAL_FUNC + void CID_ToToken( CID_Parser* parser, + CID_Token_Rec* 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 */ + CID_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 is any token **********/ + default: + token->start = cur++; + token->type = t1_token_any; + while ( cur < limit && !IS_CID_SPACE( *cur ) ) + cur++; + + token->limit = cur; + } + + if ( !token->limit ) + { + token->start = 0; + token->type = t1_token_none; + } + + parser->cursor = cur; + } + } + + + LOCAL_FUNC + void CID_ToTokenArray( CID_Parser* parser, + CID_Token_Rec* tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ) + { + CID_Token_Rec master; + + + *pnum_tokens = -1; + + CID_ToToken( parser, &master ); + + if ( master.type == t1_token_array ) + { + FT_Byte* old_cursor = parser->cursor; + FT_Byte* old_limit = parser->limit; + CID_Token_Rec* cur = tokens; + CID_Token_Rec* limit = cur + max_tokens; + + + parser->cursor = master.start; + parser->limit = master.limit; + + while ( parser->cursor < parser->limit ) + { + CID_Token_Rec token; + + + CID_ToToken( parser, &token ); + if ( !token.type ) + break; + + if ( cur < limit ) + *cur = token; + + cur++; + } + + *pnum_tokens = 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, 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, read the integer part */ + result = t1_toint( &cur, limit ) << 16; + num = 0; + divider = 1; + + if ( result < 0 ) + { + sign = 1; + result = -result; + } + + 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 + int t1_tobool( FT_Byte** cursor, + FT_Byte* limit ) + { + FT_Byte* cur = *cursor; + FT_Bool result = 0; + + + /* return 1 if we find a "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; + } + + + 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; + } + + + /* Loads a simple field (i.e. non-table) into the current */ + /* list of objects */ + LOCAL_FUNC + FT_Error CID_Load_Field( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ) + { + CID_Token_Rec token; + FT_Byte* cur; + FT_Byte* limit; + FT_UInt count; + FT_UInt index; + FT_Error error; + + + CID_ToToken( parser, &token ); + if ( !token.type ) + goto Fail; + + count = 1; + index = 0; + cur = token.start; + limit = token.limit; + + { + FT_Byte* q = (FT_Byte*)object + 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, 0 ); + 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_Int32*)q = (FT_Int)val; + break; + + default: /* for 64-bit systems */ + *(FT_Long*)q = val; + } + break; + + case t1_field_string: + { + FT_Memory memory = parser->memory; + FT_UInt len = limit-cur; + + + if ( ALLOC( string, len + 1 ) ) + goto Exit; + + MEM_Copy( string, cur, len ); + string[len] = 0; + + *(FT_String**)q = string; + } + break; + + default: + /* an error occurred */ + goto Fail; + } + } + + error = 0; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + +#define T1_MAX_TABLE_ELEMENTS 32 + + + LOCAL_FUNC + FT_Error CID_Load_Field_Table( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ) + { + CID_Token_Rec elements[T1_MAX_TABLE_ELEMENTS]; + CID_Token_Rec* token; + FT_Int num_elements; + FT_Error error = 0; + FT_Byte* old_cursor; + FT_Byte* old_limit; + CID_Field_Rec fieldrec = *(CID_Field_Rec*)field; + + + fieldrec.type = t1_field_integer; + if ( field->type == t1_field_fixed_array ) + fieldrec.type = t1_field_fixed; + + CID_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 */ + if ( field->count_offset ) + *(FT_Byte*)( (FT_Byte*)object + field->count_offset ) = 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; + CID_Load_Field( parser, &fieldrec, object ); + fieldrec.offset += fieldrec.size; + } + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + + LOCAL_FUNC + FT_Long CID_ToInt( CID_Parser* parser ) + { + return t1_toint( &parser->cursor, parser->limit ); + } + + + LOCAL_FUNC + FT_Int CID_ToCoordArray( CID_Parser* parser, + FT_Int max_coords, + FT_Short* coords ) + { + return t1_tocoordarray( &parser->cursor, parser->limit, + max_coords, coords ); + } + + + LOCAL_FUNC + FT_Int CID_ToFixedArray( CID_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 + + /* 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; + } + +#endif /* 0 */ + + + LOCAL_FUNC + FT_Error CID_New_Parser( CID_Parser* parser, + FT_Stream stream, + FT_Memory memory ) + { + 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 ) ); + parser->stream = stream; + parser->memory = memory; + + 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 = FT_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; + + /* fill input buffer */ + buff_len -= 256; + if ( buff_len > 0 ) + MEM_Move( buffer, limit, buff_len ); + + if ( FILE_Read( buffer, 256 + 10 - buff_len ) ) + goto Exit; + + 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 = FILE_Pos() - ( 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->cursor = parser->postscript; + parser->limit = parser->cursor + ps_len; + parser->num_dict = -1; + + Exit: + return error; + } + + + LOCAL_FUNC + void CID_Done_Parser( CID_Parser* parser ) + { + /* always free the private dictionary */ + if ( parser->postscript ) + { + FT_Stream stream = parser->stream; + + + RELEASE_Frame( parser->postscript ); + } + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/cidparse.h b/reactos/subsys/win32k/freetype/src/cid/cidparse.h new file mode 100644 index 00000000000..7a8211ad305 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidparse.h @@ -0,0 +1,353 @@ +/***************************************************************************/ +/* */ +/* cidparse.h */ +/* */ +/* CID-keyed Type1 parser (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + +#if 0 + + /*************************************************************************/ + /* */ + /* */ + /* CID_Table */ + /* */ + /* */ + /* A CID_Table is a simple object used to store an array of objects */ + /* in a single memory block. */ + /* */ + /* */ + /* block :: The address in memory of the growheap's block. This */ + /* can change between two object adds, due to the use */ + /* of `realloc()'. */ + /* */ + /* cursor :: The current top of the growheap within its block. */ + /* */ + /* capacity :: The current size of the heap block. Increments by */ + /* blocks of 1 kByte. */ + /* */ + /* init :: A boolean. Set when the table has been initialized */ + /* (the table user should set this field). */ + /* */ + /* max_elems :: The maximal number of elements in the table. */ + /* */ + /* num_elems :: The current number of elements (in use) in the table. */ + /* */ + /* elements :: A table of element addresses within the block. */ + /* */ + /* lengths :: A table of element sizes within the block. */ + /* */ + /* memory :: The memory object used for memory operations */ + /* (allocation resp. reallocation). */ + /* */ + typedef struct CID_Table_ + { + FT_Byte* block; /* current memory block */ + FT_Int cursor; /* current cursor in memory block */ + FT_Int 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; + + } CID_Table; + + + LOCAL_DEF + FT_Error CID_New_Table( CID_Table* table, + FT_Int count, + CID_Memory memory ); + + LOCAL_DEF + FT_Error CID_Add_Table( CID_Table* table, + FT_Int index, + void* object, + FT_Int length ); + + LOCAL_DEF + void CID_Release_Table( CID_Table* table ); + +#endif /* 0 */ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Parser */ + /* */ + /* */ + /* A CID_Parser is an object used to parse a Type 1 fonts very */ + /* quickly. */ + /* */ + /* */ + /* stream :: The current input stream. */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* 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. */ + /* */ + /* cursor :: The current parser cursor. */ + /* */ + /* limit :: The current parser limit (i.e., the first byte */ + /* after the current dictionary). */ + /* */ + /* error :: The current parsing error. */ + /* */ + /* cid :: A structure which holds the information about */ + /* the current font. */ + /* */ + /* num_dict :: The number of font dictionaries. */ + /* */ + typedef struct CID_Parser_ + { + FT_Stream stream; + FT_Memory memory; + + FT_Byte* postscript; + FT_Int postscript_len; + + FT_ULong data_offset; + + FT_Byte* cursor; + FT_Byte* limit; + FT_Error error; + + CID_Info* cid; + FT_Int num_dict; + + } CID_Parser; + + + LOCAL_DEF + FT_Error CID_New_Parser( CID_Parser* parser, + FT_Stream stream, + FT_Memory memory ); + + LOCAL_DEF + void CID_Done_Parser( CID_Parser* parser ); + + + /*************************************************************************/ + /* */ + /* PARSING ROUTINES */ + /* */ + /*************************************************************************/ + + LOCAL_DEF + FT_Long CID_ToInt( CID_Parser* parser ); + + LOCAL_DEF + FT_Int CID_ToCoordArray( CID_Parser* parser, + FT_Int max_coords, + FT_Short* coords ); + + LOCAL_DEF + FT_Int CID_ToFixedArray( CID_Parser* parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ); + + LOCAL_DEF + void CID_Skip_Spaces( CID_Parser* parser ); + + + /* simple enumeration type used to identify token types */ + typedef enum CID_Token_Type_ + { + t1_token_none = 0, + t1_token_any, + t1_token_string, + t1_token_array, + + /* do not remove */ + t1_token_max + + } CID_Token_Type; + + + /* a simple structure used to identify tokens */ + typedef struct CID_Token_Rec_ + { + FT_Byte* start; /* first character of token in input stream */ + FT_Byte* limit; /* first character after the token */ + CID_Token_Type type; /* type of token */ + + } CID_Token_Rec; + + + LOCAL_DEF + void CID_ToToken( CID_Parser* parser, + CID_Token_Rec* token ); + + + /* enumeration type used to identify object fields */ + typedef enum CID_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 + + } CID_Field_Type; + + typedef enum CID_Field_Location_ + { + t1_field_cid_info, + t1_field_font_dict, + t1_field_font_info, + t1_field_private, + + /* do not remove */ + t1_field_location_max + + } CID_Field_Location; + + + typedef FT_Error (*CID_Field_Parser)( CID_Face face, + CID_Parser* parser ); + + /* structure type used to model object fields */ + typedef struct CID_Field_Rec_ + { + const char* ident; /* field identifier */ + CID_Field_Location location; + CID_Field_Type type; /* type of field */ + CID_Field_Parser reader; + FT_UInt offset; /* offset of field in object */ + FT_UInt 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 */ + } CID_Field_Rec; + + +#define CID_FIELD_REF( s, f ) ( ((s*)0)->f ) + +#define CID_NEW_SIMPLE_FIELD( _ident, _type, _fname ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \ + sizeof ( CID_FIELD_REF( T1TYPE, _fname ) ), \ + 0, 0 \ + }, + +#define CID_NEW_CALLBACK_FIELD( _ident, _reader ) \ + { \ + _ident, T1CODE, t1_field_callback, \ + _reader, \ + 0, 0, \ + 0, 0 \ + }, + +#define CID_NEW_TABLE_FIELD( _ident, _type, _fname, _max ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \ + sizeof ( CID_FIELD_REF( T1TYPE, _fname )[0] ), \ + _max, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, num_ ## _fname ) \ + }, + +#define CID_NEW_TABLE_FIELD2( _ident, _type, _fname, _max ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \ + sizeof ( CID_FIELD_REF( T1TYPE, _fname )[0] ), \ + _max, 0 \ + }, + + +#define CID_FIELD_BOOL( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_bool, _fname ) + +#define CID_FIELD_NUM( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_integer, _fname ) + +#define CID_FIELD_FIXED( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_fixed, _fname ) + +#define CID_FIELD_STRING( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_string, _fname ) + +#define CID_FIELD_NUM_TABLE( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD( _ident, t1_field_integer_array, \ + _fname, _fmax ) + +#define CID_FIELD_FIXED_TABLE( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD( _ident, t1_field_fixed_array, \ + _fname, _fmax ) + +#define CID_FIELD_NUM_TABLE2( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD2( _ident, t1_field_integer_array, \ + _fname, _fmax ) + +#define CID_FIELD_FIXED_TABLE2( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD2( _ident, t1_field_fixed_array, \ + _fname, _fmax ) + +#define CID_FIELD_CALLBACK( _ident, _name ) \ + CID_NEW_CALLBACK_FIELD( _ident, parse_ ## _name ) + + + LOCAL_DEF + FT_Error CID_Load_Field( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ); + + LOCAL_DEF + FT_Error CID_Load_Field_Table( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDPARSE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/cidriver.c b/reactos/subsys/win32k/freetype/src/cid/cidriver.c new file mode 100644 index 00000000000..f1c6b6a012f --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidriver.c @@ -0,0 +1,259 @@ +/***************************************************************************/ +/* */ +/* cidriver.c */ +/* */ +/* CID driver interface (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "cidriver.h" +#include "cidgload.h" + +#else + +#include +#include + +#endif + + +#include +#include +#include + +#include /* 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 + FT_Module_Interface CID_Get_Interface( FT_Driver driver, + const FT_String* interface ) + { + FT_UNUSED( driver ); + FT_UNUSED( interface ); + + 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 T1_Err_Ok; + } + + +#endif /* 0 */ + + + /*************************************************************************/ + /* */ + /* */ + /* Cid_Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* 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; + } + + + 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 + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverClass */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ + EXPORT_FUNC( FT_Driver_Class* ) getDriverClass( void ) + { + return &t1cid_driver_class; + } + + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/cidriver.h b/reactos/subsys/win32k/freetype/src/cid/cidriver.h new file mode 100644 index 00000000000..a9674eed441 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidriver.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* cidriver.h */ +/* */ +/* High-level CID driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + FT_EXPORT_VAR( const FT_Driver_Class ) t1cid_driver_class; + +#endif /* CIDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/cidtokens.h b/reactos/subsys/win32k/freetype/src/cid/cidtokens.h new file mode 100644 index 00000000000..a916cea3227 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/cidtokens.h @@ -0,0 +1,99 @@ +/***************************************************************************/ +/* */ +/* cidtokens.h */ +/* */ +/* CID token definitions (specification only). */ +/* */ +/* Copyright 1996-2000 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 T1TYPE +#undef T1CODE +#define T1TYPE CID_Info +#define T1CODE t1_field_cid_info + + CID_FIELD_STRING ( "CIDFontName", cid_font_name ) + CID_FIELD_NUM ( "CIDFontVersion", cid_version ) + CID_FIELD_NUM ( "CIDFontType", cid_font_type ) + CID_FIELD_STRING ( "Registry", registry ) + CID_FIELD_STRING ( "Ordering", ordering ) + CID_FIELD_NUM ( "Supplement", supplement ) + CID_FIELD_CALLBACK( "FontBBox", font_bbox ) + CID_FIELD_NUM ( "UIDBase", uid_base ) + CID_FIELD_CALLBACK( "FDArray", fd_array ) + CID_FIELD_NUM ( "CIDMapOffset", cidmap_offset ) + CID_FIELD_NUM ( "FDBytes", fd_bytes ) + CID_FIELD_NUM ( "GDBytes", gd_bytes ) + CID_FIELD_NUM ( "CIDCount", cid_count ) + + +#undef T1TYPE +#undef T1CODE +#define T1TYPE T1_FontInfo +#define T1CODE t1_field_font_info + + CID_FIELD_STRING( "version", version ) + CID_FIELD_STRING( "Notice", notice ) + CID_FIELD_STRING( "FullName", full_name ) + CID_FIELD_STRING( "FamilyName", family_name ) + CID_FIELD_STRING( "Weight", weight ) + CID_FIELD_FIXED ( "ItalicAngle", italic_angle ) + CID_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch ) + CID_FIELD_NUM ( "UnderlinePosition", underline_position ) + CID_FIELD_NUM ( "UnderlineThickness", underline_thickness ) + + +#undef T1TYPE +#undef T1CODE +#define T1TYPE CID_FontDict +#define T1CODE t1_field_font_dict + + CID_FIELD_CALLBACK( "FontMatrix", font_matrix ) + CID_FIELD_NUM ( "PaintType", paint_type ) + CID_FIELD_NUM ( "FontType", font_type ) + CID_FIELD_NUM ( "SubrMapOffset", subrmap_offset ) + CID_FIELD_NUM ( "SDBytes", sd_bytes ) + CID_FIELD_NUM ( "SubrCount", num_subrs ) + CID_FIELD_NUM ( "lenBuildCharArray", len_buildchar ) + CID_FIELD_FIXED ( "ForceBoldThreshold", forcebold_threshold ) + CID_FIELD_FIXED ( "ExpansionFactor", expansion_factor ) + CID_FIELD_NUM ( "StrokeWidth", stroke_width ) + + +#undef T1TYPE +#undef T1CODE +#define T1TYPE T1_Private +#define T1CODE t1_field_private + + CID_FIELD_NUM ( "UniqueID", unique_id ) + CID_FIELD_NUM ( "lenIV", lenIV ) + CID_FIELD_NUM ( "LanguageGroup", language_group ) + CID_FIELD_NUM ( "password", password ) + + CID_FIELD_FIXED ( "BlueScale", blue_scale ) + CID_FIELD_NUM ( "BlueShift", blue_shift ) + CID_FIELD_NUM ( "BlueFuzz", blue_fuzz ) + + CID_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 ) + CID_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 ) + CID_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 ) + CID_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 ) + + CID_FIELD_NUM_TABLE2( "StdHW", standard_width, 1 ) + CID_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 ) + CID_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 ) + + CID_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 ) + CID_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 ) + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/cid/module.mk b/reactos/subsys/win32k/freetype/src/cid/module.mk new file mode 100644 index 00000000000..3d13c9ca1d7 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/module.mk @@ -0,0 +1,6 @@ +make_module_list: add_type1cid_driver + +add_type1cid_driver: + $(OPEN_DRIVER)t1cid_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)cid $(ECHO_DRIVER_DESC)Postscript CID-keyed fonts, no known extension$(ECHO_DRIVER_DONE) +# EOF diff --git a/reactos/subsys/win32k/freetype/src/cid/rules.mk b/reactos/subsys/win32k/freetype/src/cid/rules.mk new file mode 100644 index 00000000000..cbaaec76857 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/rules.mk @@ -0,0 +1,69 @@ +# +# FreeType 2 CID driver configuration rules +# + + +# Copyright 1996-2000 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. + + +# CID driver directory +# +CID_DIR := $(SRC_)cid +CID_DIR_ := $(CID_DIR)$(SEP) + + +CID_COMPILE := $(FT_COMPILE) + + +# CID driver sources (i.e., C files) +# +CID_DRV_SRC := $(CID_DIR_)cidparse.c \ + $(CID_DIR_)cidload.c \ + $(CID_DIR_)cidriver.c \ + $(CID_DIR_)cidgload.c \ + $(CID_DIR_)cidobjs.c + +# CID driver headers +# +CID_DRV_H := $(CID_DRV_SRC:%.c=%.h) \ + $(CID_DIR_)cidtokens.h + + +# CID driver object(s) +# +# CID_DRV_OBJ_M is used during `multi' builds +# CID_DRV_OBJ_S is used during `single' builds +# +CID_DRV_OBJ_M := $(CID_DRV_SRC:$(CID_DIR_)%.c=$(OBJ_)%.$O) +CID_DRV_OBJ_S := $(OBJ_)type1cid.$O + +# CID driver source file for single build +# +CID_DRV_SRC_S := $(CID_DIR_)type1cid.c + + +# CID driver - single object +# +$(CID_DRV_OBJ_S): $(CID_DRV_SRC_S) $(CID_DRV_SRC) $(FREETYPE_H) $(CID_DRV_H) + $(CID_COMPILE) $T$@ $(CID_DRV_SRC_S) + + +# CID driver - multiple objects +# +$(OBJ_)%.$O: $(CID_DIR_)%.c $(FREETYPE_H) $(CID_DRV_H) + $(CID_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(CID_DRV_OBJ_S) +DRV_OBJS_M += $(CID_DRV_OBJ_M) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/cid/type1cid.c b/reactos/subsys/win32k/freetype/src/cid/type1cid.c new file mode 100644 index 00000000000..d26aee26f47 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/cid/type1cid.c @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* cff.c */ +/* */ +/* FreeType OpenType driver component (body only). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef FT_FLAT_COMPILE + +#include "cidparse.c" +#include "cidload.c" +#include "cidobjs.c" +#include "cidriver.c" +#include "cidgload.c" + +#else + +#include +#include +#include +#include +#include + +#endif + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/macfond/fonddrvr.c b/reactos/subsys/win32k/freetype/src/macfond/fonddrvr.c new file mode 100644 index 00000000000..45a91416494 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/macfond/fonddrvr.c @@ -0,0 +1,616 @@ +/***************************************************************************/ +/* */ +/* fonddrvr.c */ +/* */ +/* Mac FOND font driver. Written by just@letterror.com. */ +/* */ +/* Copyright 1996-2000 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 driver 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 the init_face() + method of the Type 1 driver. + (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 the init_face() + method if the TrueType driver. + + - In both cases, the original stream gets closed and *reinitialized* + to become a memory stream. Additionally, the face->driver field -- + which is set to the FOND driver upon entering our init_face() -- + gets *reset* to either the TT or the T1 driver. I had to make a minor + change to ftobjs.c to make this work. + + - We might consider creating an FT_New_Face_Mac() API call, as this + would avoid some of the mess described above. +*/ + +#include +#include + +#include +#include +#include + +#include /* for isupper() and isalnum() */ +#include /* for malloc() and free() */ + + +/* set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over + TrueType in case *both* are available */ +#ifndef PREFER_LWFN +#define PREFER_LWFN 1 +#endif + + + static + FT_Error init_driver( FT_Driver driver ) + { + /* we don't keep no stinkin' state ;-) */ + return FT_Err_Ok; + } + + static + FT_Error done_driver( FT_Driver driver ) + { + return FT_Err_Ok; + } + + + /* MacRoman glyph names, needed for FOND kerning support. */ + /* XXX which is not implemented yet! */ + static const char* mac_roman_glyph_names[256] = { + ".null", + }; + + + /* The FOND face object is just a union of TT and T1: both is possible, + and we don't need anything else. We still need to be able to hold + either, as the face object is not allocated by us. Again, creating + an FT_New_Face_Mac() would avoid this kludge. */ + typedef union FOND_FaceRec_ + { + TT_FaceRec tt; + T1_FaceRec t1; + } FOND_FaceRec, *FOND_Face; + + + /* given a pathname, fill in a File Spec */ + static + int make_file_spec( char* pathname, FSSpec *spec ) + { + Str255 p_path; + int path_len; + + /* convert path to a pascal string */ + path_len = strlen( pathname ); + if ( path_len > 255 ) + return -1; + p_path[0] = path_len; + strncpy( (char*)p_path+1, pathname, path_len ); + + if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr ) + return -1; + else + return 0; + } + + + /* is_suitcase() returns true if the file specified by 'pathname' + is a Mac suitcase file, and false if it ain't. */ + static + int is_suitcase( FSSpec *spec ) + { + FInfo finfo; + + if ( FSpGetFInfo( spec, &finfo ) != noErr ) + return 0; + if ( finfo.fdType == 'FFIL' || finfo.fdType == 'tfil' ) + return 1; + else + return 0; + } + + + /* 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 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; + unsigned char* p = lwfn_file_name; + char* q = 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++; + } + } + + + /* Suck the relevant info out of the FOND data */ + static + FT_Error parse_fond( char* fond_data, + short *have_sfnt, + short *sfnt_id, + Str255 lwfn_file_name ) + { + AsscEntry* assoc; + FamRec* fond; + + *sfnt_id = *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 ; iindexes[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 ); + } + return FT_Err_Ok; + } + + + /* Read Type 1 data from the POST resources inside the LWFN file, return a + PFB buffer -- apparently FT doesn't like a pure binary T1 stream. */ + static + unsigned char* read_type1_data( FT_Memory memory, FSSpec* lwfn_spec, unsigned long *size ) + { + short res_ref, res_id; + unsigned char *buffer, *p, *size_p; + unsigned long total_size = 0; + unsigned long post_size, pfb_chunk_size; + Handle post_data; + char code, last_code; + + res_ref = FSpOpenResFile( lwfn_spec, fsRdPerm ); + if ( ResError() ) + return NULL; + 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; + 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; + } + + buffer = memory->alloc( memory, total_size ); + if ( !buffer ) + goto error; + + /* second pass: append all POST data to the buffer, add PFB fields */ + p = buffer; + res_id = 501; + last_code = -1; + pfb_chunk_size = 0; + for (;;) + { + post_data = Get1Resource( 'POST', res_id++ ); + if ( post_data == NULL ) + break; + post_size = 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++ = pfb_chunk_size & 0xFF; + *size_p++ = (pfb_chunk_size >> 8) & 0xFF; + *size_p++ = (pfb_chunk_size >> 16) & 0xFF; + *size_p++ = (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; + } + + CloseResFile( res_ref ); + + *size = total_size; +/* printf( "XXX %d %d\n", p - buffer, total_size ); */ + return buffer; + +error: + CloseResFile( res_ref ); + return NULL; + } + + + /* Finalizer for the sfnt stream */ + static + void sfnt_stream_close( FT_Stream stream ) + { + Handle sfnt_data = stream->descriptor.pointer; + HUnlock( sfnt_data ); + DisposeHandle( sfnt_data ); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + stream->close = 0; + } + + + /* Finalizer for the LWFN stream */ + static + void lwfn_stream_close( FT_Stream stream ) + { + stream->memory->free( stream->memory, stream->base ); + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + stream->close = 0; + } + + + /* Main entry point. Determine whether we're dealing with a Mac + suitcase or not; then determine if we're dealing with Type 1 + or TrueType; delegate the work to the proper driver. */ + static + FT_Error init_face( FT_Stream stream, + FT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* parameters ) + { + FT_Error err; + FSSpec suit_spec, lwfn_spec; + short res_ref; + Handle fond_data, sfnt_data; + short res_index, sfnt_id, have_sfnt; + Str255 lwfn_file_name; + + if ( !stream->pathname.pointer ) + return FT_Err_Unknown_File_Format; + + if ( make_file_spec( stream->pathname.pointer, &suit_spec ) ) + return FT_Err_Invalid_Argument; + + if ( !is_suitcase( &suit_spec ) ) + return FT_Err_Unknown_File_Format; + + res_ref = FSpOpenResFile( &suit_spec, fsRdPerm ); + if ( ResError() ) + return FT_Err_Invalid_File_Format; + 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 = face_index + 1; + face_index = 0; + } + fond_data = Get1IndResource( 'FOND', res_index ); + if ( ResError() ) + { + CloseResFile( res_ref ); + return FT_Err_Invalid_File_Format; + } + /* Set the number of faces. Not that it helps much: the t1 driver + just sets it to 1 anyway :-( */ + face->num_faces = Count1Resources('FOND'); + + HLock( fond_data ); + err = parse_fond( *fond_data, &have_sfnt, &sfnt_id, lwfn_file_name ); + HUnlock( fond_data ); + if ( err ) + { + CloseResFile( res_ref ); + return FT_Err_Invalid_Handle; + } + + if ( lwfn_file_name[0] ) + { + /* We look for the LWFN file in the same directory as the suitcase + file. ATM would look in other places, too, but this is the usual + situation. */ + err = FSMakeFSSpec( suit_spec.vRefNum, suit_spec.parID, lwfn_file_name, &lwfn_spec ); + if ( err != noErr ) + lwfn_file_name[0] = 0; /* no LWFN file found */ + } + + if ( lwfn_file_name[0] && ( !have_sfnt || PREFER_LWFN ) ) + { + FT_Driver t1_driver; + unsigned char* type1_data; + unsigned long size; + + CloseResFile( res_ref ); /* XXX still need to read kerning! */ + + type1_data = read_type1_data( stream->memory, &lwfn_spec, &size ); + if ( !type1_data ) + { + return FT_Err_Out_Of_Memory; + } + +#if 0 + { + FILE* f; + char * path; + + path = p2c_str( lwfn_file_name ); + strcat( path, ".PFB" ); + f = fopen(path, "wb"); + if ( f ) + { + fwrite( type1_data, 1, size, f ); + fclose( f ); + } + } +#endif + + /* reinitialize the stream */ + if ( stream->close ) + stream->close( stream ); + stream->close = lwfn_stream_close; + stream->read = 0; /* it's now memory based */ + stream->base = type1_data; + stream->size = size; + stream->pos = 0; /* just in case */ + + /* delegate the work to the Type 1 module */ + t1_driver = (FT_Driver)FT_Get_Module( face->driver->root.library, "type1z" ); + if ( t1_driver ) + { + face->driver = t1_driver; + return t1_driver->clazz->init_face( stream, face, face_index, 0, NULL ); + } + else + return FT_Err_Invalid_Driver_Handle; + } + else if ( have_sfnt ) + { + FT_Driver tt_driver; + + sfnt_data = Get1Resource( 'sfnt', sfnt_id ); + if ( ResError() ) + { + CloseResFile( res_ref ); + return FT_Err_Invalid_Handle; + } + DetachResource( sfnt_data ); + CloseResFile( res_ref ); + HLockHi( sfnt_data ); + + /* reinitialize the stream */ + if ( stream->close ) + stream->close( stream ); + stream->close = sfnt_stream_close; + stream->descriptor.pointer = sfnt_data; + stream->read = 0; /* it's now memory based */ + stream->base = (unsigned char *)*sfnt_data; + stream->size = GetHandleSize( sfnt_data ); + stream->pos = 0; /* just in case */ + + /* delegate the work to the TrueType driver */ + tt_driver = (FT_Driver)FT_Get_Module( face->driver->root.library, "truetype" ); + if ( tt_driver ) + { + face->driver = tt_driver; + return tt_driver->clazz->init_face( stream, face, face_index, 0, NULL ); + } + else + return FT_Err_Invalid_Driver_Handle; + } + else + { + CloseResFile( res_ref ); + } + return FT_Err_Invalid_File_Format; + } + + + static + void done_face( FT_Face face ) + { + /* nothing to do */ + } + + /* The FT_DriverInterface structure is defined in ftdriver.h. */ + + const FT_Driver_Class fond_driver_class = + { + { + ft_module_font_driver | ft_module_driver_scalable, + sizeof ( FT_DriverRec ), + + "fond", /* driver name */ + 0x10000L, /* driver version == 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or above */ + + (void*)0, + + (FT_Module_Constructor) init_driver, + (FT_Module_Destructor) done_driver, + (FT_Module_Requester) 0 + }, + + sizeof ( FOND_FaceRec ), + 0, + 0, + + (FTDriver_initFace) init_face, + (FTDriver_doneFace) done_face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot) 0, + (FTDriver_doneGlyphSlot) 0, + + (FTDriver_setCharSizes) 0, + (FTDriver_setPixelSizes) 0, + (FTDriver_loadGlyph) 0, + (FTDriver_getCharIndex) 0, + + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, + (FTDriver_getAdvances) 0 + }; + + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverInterface */ + /* */ + /* */ + /* This function is used when compiling the FOND 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. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + FT_EXPORT_FUNC(const FT_Driver_Class*) getDriverClass( void ) + { + return &fond_driver_class; + } + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/otlayout/oltypes.c b/reactos/subsys/win32k/freetype/src/otlayout/oltypes.c new file mode 100644 index 00000000000..bd2fa2204c4 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/otlayout/oltypes.c @@ -0,0 +1,614 @@ +#include + + LOCAL_FUNC + TT_Error OTL_Table_Init( OTL_Table* table, + FT_Memory memory ) + { + MEM_Set( table, 0, sizeof(*table) ); + table->memory = memory; + } + + /* read a script list table */ + /* use with any table */ + LOCAL_FUNC + TT_Error OTL_Table_Set_Scripts( OTL_Table* table, + TT_Byte* bytes, + TT_Long len, + OTL_Type otl_type ) + { + TT_Byte* p; + TT_Byte* start = bytes; + TT_UInt count, max_langs; + TT_Error error; + + /* skip version of the JSTF table */ + if (otl_type == otl_jstf) + start += 4; + + p = start; + + /* we must allocate the script_tags and language_tags arrays */ + /* this requires that we compute the maximum number of languages */ + /* per script.. */ + + count = table->num_scripts = OTL_UShort(p); + max_langs = 0; + for ( ; count > 0; count++ ) + { + TT_Byte* script; + TT_UInt num_langs; + + p += 4; /* skip tag */ + script = bytes + OTL_UShort(p); + + /* skip the baseValues or extenders field of the BASE and JSTF table */ + if (otl_type == otl_type_base || otl_type == otl_type_jstf) + script += 2; + + /* test if there is a default language system */ + if ( OTL_UShort(script) ) + num_langs++; + + /* test other language systems */ + num_langs += OTL_UShort(script); /* add other lang sys */ + + if (num_langs > max_langs) + max_langs = num_langs; + } + + /* good, now allocate the tag arrays */ + if ( !ALLOC_ARRAY( table->script_tags, + table->num_scripts + max_langs, + TT_ULong ) ) + { + table->language_tags = table->script_tags + table->num_scripts; + table->max_languages = max_langs; + table->num_languages = 0; + table->otl_type = otl_type; + + table->scripts_table = bytes; + table->scripts_len = len; + + /* fill the script_tags array */ + { + TT_UInt n; + TT_Byte* p = start + 2; /* skip count */ + + for ( n = 0; n < table->num_scripts; n++ ) + { + table->script_tags[n] = OTL_ULong(p); + p += 2; /* skip offset */ + } + } + } + return error; + } + + + + /* add a features list to the table */ + /* use only with a GSUB or GPOS table */ + LOCAL_FUNC + TT_Error OTL_Table_Set_Features( OTL_Table* table, + TT_Byte* bytes, + TT_Long len ) + { + TT_Error error; + TT_Byte* p = bytes; + TT_UInt count; + + table->max_features = count = OTL_UShort(p); + if ( !ALLOC_ARRAY( table->feature_tags, count, TT_ULong ) && + !ALLOC_ARRAY( table->features, count, TT_Bool ) ) + { + table->features_table = bytes; + table->features_len = len; + } + return error; + } + + + /* add a lookup list to the table */ + /* use only with a GSUB or GPOS table */ + LOCAL_FUNC + TT_Error OTL_Table_Set_Lookups( OTL_Table* table, + TT_Byte* bytes, + TT_Long len ) + { + TT_Error error; + TT_Byte* p = bytes; + TT_UInt count; + + table->max_lookups = count = OTL_UShort(p); + if ( !ALLOC_ARRAY( table->lookups, count, TT_Bool ) ) + { + table->lookups_table = bytes; + table->lookups_len = len; + } + return error; + } + + /* discard table arrays */ + LOCAL_FUNC + void OTL_Table_Done( OTL_Table* table ) + { + FREE( table->scrip_tags ); + FREE( table->language_tags ); + FREE( table->feature_tags ); + FREE( table->lookups ); + } + + + /* return the list of available languages for a given script */ + /* use with any table.. */ + LOCAL_FUNC + void OTL_Get_Languages_List( OTL_Table* table, + TT_ULong script_tag ) + { + TT_UInt n; + TT_Byte* p; + TT_Byte* script = 0; + TT_Byte* start = table->scripts_table; + + if ( table->otl_type == otl_type_jstf ) /* skip version for JSTF */ + start += 4; + + p = start + 6; /* skip count+first tag */ + + for ( n = 0; n < table->num_scripts; n++, p += 6 ) + { + if ( table->script_tags[n] == script_tag ) + { + script = table->scripts_table + OTL_UShort(p); + break; + } + } + + table->cur_script = script; + if (!script) + table->num_languages = 0; + else + { + /* now fill the language_tags array with the appropriate values */ + /* not that we put a '0' tag in front of the list to indicate that */ + /* there is a default language for this script.. */ + TT_ULong* tags = table->language_tags; + + switch (table->otl_type) + { + case otl_type_base: + case otl_type_jstf: + script += 2; /* skip basevalue or extenders */ + /* fall-through */ + + default: + if ( OTL_UShort(script) ) + *tags++ = 0; + } + + count = OTL_UShort(script); + for ( ; count > 0; count-- ) + { + *tags++ = OTL_ULong(script); + script += 2; /* skip offset */ + } + + table->num_langs = tags - table->language_tags; + } + } + + + /* return the list of available features for the current script/language */ + /* use with a GPOS or GSUB script table */ + LOCAL_FUNC + void OTL_Get_Features_List( OTL_Table* table, + TT_ULong language_tag ) + { + TT_UInt n; + TT_Byte* script = table->cur_script; + TT_Byte* language = 0; + TT_UShort offset; + + /* clear feature selection table */ + for ( n = 0; n < table->max_features; n++ ) + table->features[n] = 0; + + /* now, look for the current language */ + if ( language_tag == 0 ) + { + offset = OTL_UShort(script); + if (!offset) return; /* if there is no default language, exit */ + + language = script - 2 + offset; + } + else + { + TT_Byte* p = script + 8; /* skip default+count+1st tag */ + TT_UShort index; + + for ( n = 0; n < table->num_languages; n++, p+=6 ) + { + if ( table->language_tags[n] == language_tag ) + { + language = script + OTL_UShort(p); + break; + } + } + + table->cur_language = language; + if (!language) return; + + p = language + 2; /* skip lookup order */ + index = OTL_UShort(p); /* required feature index */ + if (index != 0xFFFF) + { + if (index < table->max_features) + table->features[index] = 1; + } + + count = OTL_UShort(p); + for ( ; count > 0; count-- ) + { + index = OTL_UShort(p); + if (index < table->max_features) + table->features[index] = 1; + } + } + } + + + /* return the list of lookups for the current features list */ + /* use only with a GSUB or GPOS table */ + LOCAL_FUNC + void OTL_Get_Lookups_List( OTL_Table* table ) + { + TT_UInt n; + TT_Byte* features = table->features_table; + TT_Byte* p = features + 6; /* skip count+1st tag */ + + /* clear lookup list */ + for ( n = 0; n < table->max_lookups; n++ ) + table->lookups[n] = 0; + + /* now, parse the features list */ + for ( n = 0; n < table->features; n++ ) + { + if (table->features[n]) + { + TT_UInt count; + TT_UShort index; + TT_Byte* feature; + + feature = features + OTL_UShort(p); + p += 4; /* skip tag */ + + /* now, select all lookups from this feature */ + count = OTL_UShort(feature); + for ( ; count > 0; count-- ) + { + index = OTL_UShort(feature); + if (index < table->max_lookups) + table->lookups[index] = 1; + } + } + } + } + + + /* find the basevalues and minmax for the current script/language */ + /* only use it with a BASE table.. */ + LOCAL_FUNC + void OTL_Get_Baseline_Values( OTL_Table* table, + TT_ULong language_tag ) + { + TT_Byte* script = table->cur_script; + TT_Byte* p = script; + TT_UShort offset, count; + + table->cur_basevalues = 0; + table->cur_minmax = 0; + + /* read basevalues */ + offset = OTL_UShort(p); + if (offset) + table->cur_basevalues = script + offset; + + offset = OTL_UShort(p); + if (offset) + table->cur_minmax = script + offset; + + count = OTL_UShort(p); + for ( ; count > 0; count-- ) + { + TT_ULong tag; + + tag = OTL_ULong(p); + if ( language_tag == tag ) + { + table->cur_minmax = script + OTL_UShort(p); + break; + } + p += 2; /* skip offset */ + } + } + + + /* compute the coverage value of a given glyph id */ + LOCAL_FUNC + TT_Long OTL_Get_Coverage_Index( TT_Byte* coverage, + TT_UInt glyph_id ) + { + TT_Long result = -1; + TT_UInt count, index, start, end; + TT_Byte* p = coverage; + + switch ( OTL_UShort(p) ) + { + case 1: /* coverage format 1 - array of glyph indices */ + { + count = OTL_UShort(p); + for ( index = 0; index < count; index++ ) + { + if ( OTL_UShort(p) == glyph_id ) + { + result = index; + break; + } + } + } + break; + + case 2: + { + count = OTL_UShort(p); + for ( ; count > 0; count-- ) + { + start = OTL_UShort(p); + end = OTL_UShort(p); + index = OTL_UShort(p); + if (start <= glyph_id && glyph_id <= end) + { + result = glyph_id - start + index; + break; + } + } + } + break; + } + return result; + } + + + /* compute the class value of a given glyph_id */ + LOCAL_FUNC + TT_UInt OTL_Get_Glyph_Class( TT_Byte* class_def, + TT_UInt glyph_id ) + { + TT_Byte* p = class_def; + TT_UInt result = 0; + TT_UInt start, end, count, index; + + switch ( OTL_UShort(p) ) + { + case 1: + { + start = OTL_UShort(p); + count = OTL_UShort(p); + + glyph_id -= start; + if (glyph_id < count) + { + p += 2*glyph_id; + result = OTL_UShort(p); + } + } + break; + + case 2: + { + count = OTL_UShort(p); + for ( ; count > 0; count-- ) + { + start = OTL_UShort(p); + end = OTL_UShort(p); + index = OTL_UShort(p); + if ( start <= glyph_id && glyph_id <= end ) + { + result = index; + break; + } + } + } + break; + } + return result; + } + + + /* compute the adjustement necessary for a given device size */ + LOCAL_FUNC + TT_Int OTL_Get_Device_Adjustment( TT_Byte* device, + TT_UInt size ) + { + TT_Byte* p = device; + TT_Int result = 0; + TT_UInt start, end; + TT_Short value; + + start = OTL_UShort(p); + end = OTL_UShort(p); + if (size >= start && size <= end) + { + /* I know we could do all of this without a switch, with */ + /* clever shifts and everything, but it makes the code */ + /* really difficult to understand.. */ + + size -= start; + switch ( OTL_UShort(p) ) + { + case 1: /* 2-bits per value */ + { + p += 2*(size >> 3); + size = (size & 7) << 1; + value = (TT_Short)((TT_Short)OTL_UShort(p) << size); + result = value >> 14; + } + break; + + case 2: /* 4-bits per value */ + { + p += 2*(size >> 2); + size = (size & 3) << 2; + value = (TT_Short)((TT_Short)OTL_UShort(p) << size); + result = value >> 12; + } + break; + + case 3: /* 8-bits per value */ + { + p += 2*(size >> 1); + size = (size & 1) << 3; + value = (TT_Short)((TT_Short)OTL_UShort(p) << size); + result = value >> 8; + } + break; + } + } + return result; + } + + /* extract a BaseCoord value */ + LOCAL_FUNC + void OTL_Get_Base_Coordinate( TT_Byte* base_coord, + OTL_ValueRecord* coord ) + { + TT_Byte* p = base_coord; + TT_Int result = 0; + + coord->format = OTL_UShort(p); + coord->coordinate = OTL_Short(p); + coord->device = 0; + + switch (coord->format) + { + case 2: /* format 2 */ + coord->ref_glyph = OTL_UShort(p); + coord->ref_point = OTL_UShort(p); + break; + + case 3: /* format 3 */ + coord->device = p - 4 + OTL_UShort(p); + break; + + default: + ; + } + } + + + /* compute size of ValueRecord */ + LOCAL_FUNC + TT_Int OTL_ValueRecord_Size( TT_UShort format ) + { + TT_Int count; + + /* each bit in the value format corresponds to a single ushort */ + /* we thus count the bits, and multiply the result by 2 */ + + count = (TT_Int)(format & 0xFF); + count = ((count & 0xAA) >> 1) + (count & 0x55); + count = ((count & 0xCC) >> 2) + (count & 0x33); + count = ((count & 0xF0) >> 4) + (count & 0x0F); + + return count*2; + } + + + + /* extract ValueRecord */ + LOCAL_FUNC + void OTL_Get_ValueRecord( TT_Byte* value_record, + TT_UShort value_format, + TT_Byte* pos_table, + OTL_ValueRecord* record ) + { + TT_Byte* p = value_record; + + /* clear vectors */ + record->placement.x = 0; + record->placement.y = 0; + record->advance.x = 0; + record->advance.y = 0; + + record->device_pla_x = 0; + record->device_pla_y = 0; + record->device_adv_x = 0; + record->device_adv_y = 0; + + if (value_format & 1) record->placement.x = NEXT_Short(p); + if (value_format & 2) record->placement.y = NEXT_Short(p); + if (value_format & 4) record->advance.x = NEXT_Short(p); + if (value_format & 8) record->advance.y = NEXT_Short(p); + + if (value_format & 16) record->device_pla_x = pos_table + NEXT_UShort(p); + if (value_format & 32) record->device_pla_y = pos_table + NEXT_UShort(p); + if (value_format & 64) record->device_adv_x = pos_table + NEXT_UShort(p); + if (value_format & 128) record->device_adv_y = pos_table + NEXT_UShort(p); + } + + + + /* extract Anchor */ + LOCAL_FUNC + void OTL_Get_Anchor( TT_Byte* anchor_table, + OTL_Anchor* anchor ) + { + TT_Byte* p = anchor_table; + + anchor->format = NEXT_UShort(p); + anchor->coord.x = NEXT_Short(p); + anchor->coord.y = NEXT_Short(p); + anchor->point = 0; + anchor->device_x = 0; + anchor->device_y = 0; + + switch (anchor->format) + { + case 2: + anchor->point = NEXT_UShort(p); + break; + + case 3: + anchor->device_x = anchor_table + NEXT_UShort(p); + anchor->device_y = anchor_table + NEXT_UShort(p); + break; + + default: + ; + } + } + + + + /* extract Mark from MarkArray */ + LOCAL_FUNC + void OTL_Get_Mark( TT_Byte* mark_array, + TT_UInt index, + TT_UShort* clazz, + OTL_Anchor* anchor ) + { + TT_Byte* p = mark_array; + TT_UInt count; + + *clazz = 0; + MEM_Set( anchor, 0, sizeof(*anchor) ); + + count = NEXT_UShort(p); + if (index < count) + { + p += 4*index; + *clazz = NEXT_UShort(p); + OTL_Get_Anchor( mark_array + NEXT_UShort(p), anchor ); + } + } + diff --git a/reactos/subsys/win32k/freetype/src/otlayout/oltypes.h b/reactos/subsys/win32k/freetype/src/otlayout/oltypes.h new file mode 100644 index 00000000000..b4a4d802eb6 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/otlayout/oltypes.h @@ -0,0 +1,310 @@ +#ifndef OLTYPES_H +#define OLTYPES_H + +#include +#include + + /************************************************************* + * + * OTL_Table + * + * + * The base table of most OpenType Layout sub-tables. + * Provides a simple way to scan a table for script, + * languages, features and lookups.. + * + * + * num_scripts :: number of scripts in table's script list + * script_tags :: array of tags for each table script + * + * max_languages :: max number of languages for any script in + * the table. + * num_languages :: number of languages available for current script + * language_tags :: tags of all languages available for current script. + * + * max_features :: total number of features in table + * feature_tags :: tags of all features for current script/language + * features :: selection flags for all features in current script/lang + * + * max_lookups :: total number of lookups in table + * lookups :: selection flags for all lookups for current + * feature list. + * + ****************************************************************/ + + typedef enum OTL_Type_ + { + otl_type_none = 0, + otl_type_base, + otl_type_gdef, + otl_type_gpos, + otl_type_gsub, + otl_type_jstf + + } OTL_Type; + + + typedef struct OTL_Table_ + { + FT_Memory memory; + + TT_Int num_scripts; + TT_Tag* script_tags; + + TT_Int max_languages; + TT_Int num_languages; + TT_Tag* language_tags; + + TT_Int max_features; + TT_Tag* feature_tags; + TT_Bool* features; + + TT_Int max_lookups; + TT_Bool* lookups; + + TT_Byte* scripts_table; + TT_Long scripts_len; + + TT_Byte* features_table; + TT_Long* features_len; + + TT_Byte* lookups_table; + TT_Byte* lookups_len; + + TT_Byte* cur_script; /* current script */ + TT_Byte* cur_language; /* current language */ + + TT_Byte* cur_base_values; + TT_Byte* cur_min_max; + + OTL_Type otl_type; + + } OTL_Table; + + + typedef struct OTL_BaseCoord_ + { + TT_UShort format; + TT_Short coordinate; + TT_UShort ref_glyph; + TT_UShort ref_point; + TT_Byte* device; + + } OTL_BaseCoord; + + + typedef struct OTL_ValueRecord_ + { + TT_Vector placement; + TT_Vector advance; + + TT_Byte* device_pla_x; + TT_Byte* device_pla_y; + TT_Byte* device_adv_x; + TT_Byte* device_adv_y; + + } OTL_ValueRecord; + + + typedef struct OTL_Anchor_ + { + TT_UInt format; + TT_Vector coord; + TT_UInt anchor_point; + TT_Byte* device_x; + TT_Byte* device_y; + + } OTL_Anchor; + + LOCAL_DEF + TT_Error OTL_Table_Init( OTL_Table* table, + FT_Memory memory ); + + LOCAL_DEF + TT_Error OTL_Table_Set_Scripts( OTL_Table* table, + TT_Byte* bytes, + TT_Long len, + OTL_Type otl_type ); + + LOCAL_DEF + TT_Error OTL_Table_Set_Features( OTL_Table* table, + TT_Byte* bytes, + TT_Long len ); + + LOCAL_DEF + TT_Error OTL_Table_Set_Lookups( OTL_Table* table, + TT_Byte* bytes, + TT_Long len ); + + LOCAL_DEF + void OTL_Table_Done( OTL_Table* table ); + + + +/***************************************************** + * + * Typical uses: + * + * - after OTL_Table_Set_Scripts have been called : + * + * table->script_tags contains the list of tags of all + * scripts defined for this table. + * + * table->num_scripts is the number of scripts + * + */ + +/******************************************************** + * + * - after calling OTL_Table_Set_Features: + * + * table->max_features is the number of all features + * in the table + * + * table->feature_tags is the list of tags of all + * features in the table + * + * table->features[] is an array of boolean used to + * indicate which feature is active for a given script/language + * it is empty (zero-filled) by default. + * + */ + +/******************************************************************* + * + * - after calling OTL_Get_Languages_List(script_tag): + * + * table->num_languages is the number of language systems + * available for the script, including the default + * langsys if there is one + * + * table->language_tags contains the list of tags of all + * languages for the script. Note that the default langsys + * has tag "0" and is always placed first in "language_tags". + * + * + * + */ + LOCAL_DEF + void OTL_Get_Languages_List( OTL_Table* table, + TT_ULong script_tag ); + + +/******************************************************************* + * + * - after calling OTL_Get_Features_List(language_tag): + * + * table->features[] is an array of booleans used to indicate + * which features are active for the current script/language + * + * note that this function must be called after OTL_Get_Languages + * which remembers the last "script_tag" used.. + * + * A client application can change the table->features[] array + * to add or remove features from the list. + * + * + * + */ + LOCAL_DEF + void OTL_Get_Features_List( OTL_Table* table, + TT_ULong language_tag ); + + LOCAL_DEF + void OTL_Get_Baseline_Values( OTL_Table* table, + TT_ULong language_tag ); + + LOCAL_DEF + void OTL_Get_Justification( OTL_Table* table, + TT_ULong language_tag ); + +/******************************************************************* + * + * - after calling OTL_Get_Lookups_List(): + * + * The function uses the table->features[] array of boolean + * to determine which lookups must be processed. + * + * It fills the table->lookups[] array accordingly. It is also + * an array of booleans (one for each lookup). + * + * + */ + + LOCAL_DEF + void OTL_Get_Lookups_List( OTL_Table* table ); + + +/*************************************************************** + * + * So the whole thing looks like: + * + * + * 1. A client specifies a given script and requests available + * language through OTL_Get_Languages_List() + * + * 2. It selects the language tag it needs, then calls + * OTL_Get_Features_List() + * + * 3. It updates the list of active features if it needs to + * + * 4. It calls OTL_Get_Lookups_List() + * It now has a list of active lookups in "table->lookups[]" + * + * 5. The lookups are processed according to the table's type.. + * + */ + + + + + LOCAL_DEF + TT_Long OTL_Get_Coverage_Index( TT_Byte* coverage, + TT_UInt glyph_id ); + + LOCAL_DEF + TT_UInt OTL_Get_Glyph_Class( TT_Byte* class_def, + TT_UInt glyph_id ); + + LOCAL_DEF + TT_Int OTL_Get_Device_Adjustment( TT_Byte* device, + TT_UInt size ); + + LOCAL_DEF + void OTL_Get_Base_Coordinate( TT_Byte* base_coord, + OTL_BaseCoord* coord ); + + + LOCAL_DEF + TT_Int OTL_ValueRecord_Size( TT_UShort value_format ); + + + LOCAL_DEF + void OTL_Get_ValueRecord( TT_Byte* value_record, + TT_UShort value_format, + TT_Byte* pos_table, + OTL_ValueRecord* record ); + + + LOCAL_DEF + void OTL_Get_Anchor( TT_Byte* anchor_table, + OTL_Anchor* anchor ); + + + LOCAL_DEF + void OTL_Get_Mark( TT_Byte* mark_array, + TT_UInt index, + TT_UShort* clazz, + OTL_Anchor* anchor ); + + + +#define OTL_Byte(p) (p++, p[-1]) + +#define OTL_UShort(p) (p+=2, ((TT_UShort)p[-2] << 8) | p[-1]) + +#define OTL_ULong(p) (p+=4, ((TT_ULong)p[-4] << 24) | \ + ((TT_ULong)p[-3] << 16) | \ + ((TT_ULong)p[-2] << 8 ) | p[-1] ) + +#endif /* OLTYPES_H */ diff --git a/reactos/subsys/win32k/freetype/src/psnames/module.mk b/reactos/subsys/win32k/freetype/src/psnames/module.mk new file mode 100644 index 00000000000..3d33c120dd9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/psnames/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_psnames_module + +add_psnames_module: + $(OPEN_DRIVER)psnames_module_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)psnames $(ECHO_DRIVER_DESC)Postscript & Unicode Glyph name handling$(ECHO_DRIVER_DONE) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/psnames/psmodule.c b/reactos/subsys/win32k/freetype/src/psnames/psmodule.c new file mode 100644 index 00000000000..55ab5dfce08 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/psnames/psmodule.c @@ -0,0 +1,320 @@ +/***************************************************************************/ +/* */ +/* psmodule.c */ +/* */ +/* PSNames module implementation (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "psmodule.h" +#include "pstables.h" + +#else + +#include +#include + +#endif + + +#include /* for qsort() */ +#include /* 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 + 4; + + + for ( count = 4; count > 0; count--, p++ ) + { + char c = *p; + unsigned char 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 = 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 = t1_standard_glyphs[n]; + + + if ( first == name[0] && strcmp( glyph_name, name ) == 0 ) + return 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 */ + static + 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 && uni_char != 0xFFFF ) + { + map->unicode = uni_char; + map->glyph_index = n; + map++; + } + } + } + + /* now, compress the table a bit */ + count = 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 = FT_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 standard_glyph_names[mac_standard_names[name_index]]; + } + + + static + const char* PS_Standard_Strings( FT_UInt sid ) + { + return ( sid < NUM_STD_GLYPHS ? t1_standard_glyphs[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 */ + + + 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/reactos/subsys/win32k/freetype/src/psnames/psmodule.h b/reactos/subsys/win32k/freetype/src/psnames/psmodule.h new file mode 100644 index 00000000000..ff7ef065037 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/psnames/psmodule.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* psmodule.h */ +/* */ +/* High-level PSNames module interface (specification). */ +/* */ +/* Copyright 1996-2000 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 PSDRIVER_H +#define PSDRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Module_Class ) psnames_module_class; + +#endif /* PSDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/psnames/psnames.c b/reactos/subsys/win32k/freetype/src/psnames/psnames.c new file mode 100644 index 00000000000..0491b4814ea --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/psnames/psnames.c @@ -0,0 +1,24 @@ +/***************************************************************************/ +/* */ +/* psnames.c */ +/* */ +/* FreeType PSNames module component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/psnames/pstables.h b/reactos/subsys/win32k/freetype/src/psnames/pstables.h new file mode 100644 index 00000000000..094bc27c335 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/psnames/pstables.h @@ -0,0 +1,2942 @@ +/***************************************************************************/ +/* */ +/* pstables.h */ +/* */ +/* PostScript glyph names (specification only). */ +/* */ +/* Copyright 2000 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* standard_glyph_names[] = + { + ".null", + "CR", + "notequal", + "infinity", + "lessequal", + "greaterequal", + "partialdiff", + "summation", + "product", + "pi", + "integral", + "Omega", + "radical", + "approxequal", + "Delta", + "nbspace", + "lozenge", + "periodcentered", + "apple", + "lslash", + "franc", + "Gbreve", + "gbreve", + "Idot", + "Scedilla", + "scedilla", + "Cacute", + "cacute", + "Ccaron", + "ccaron", + "dmacron", + ".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", + "periodcenter", + "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", + "Islash", + "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", + "Uacautesmall", + "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", + "Caron", + "Ccircumflex", + "Cdotaccent", + "Chi", + "Dcaron", + "Dcroat", + "Dieresis", + "DieresisAcute", + "DieresisGrave", + "Ebreve", + "Ecaron", + "Edotaccent", + "Emacron", + "Eng", + "Eogonek", + "Epsilon", + "Epsilontonos", + "Eta", + "Etatonos", + "Euro", + "Gamma", + "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", + "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", + "Scircumflex", + "Scommaaccent", + "Sigma", + "Tau", + "Tbar", + "Tcaron", + "Tcommaaccent", + "Tcommaaccent", + "Theta", + "Uacutesmall", + "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", + "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", + "carriagereturn", + "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", + "gamma", + "gcaron", + "gcircumflex", + "gcommaaccent", + "gdotaccent", + "gradient", + "gravecomb", + "hbar", + "hcircumflex", + "heart", + "hookabovecomb", + "house", + "ibreve", + "ij", + "imacron", + "integralbt", + "integralex", + "integraltp", + "intersection", + "invbullet", + "invcircle", + "invsmileface", + "iogonek", + "iota", + "iotadieresis", + "iotadieresistonos", + "iotatonos", + "itilde", + "jcircumflex", + "kappa", + "kcommaaccent", + "kgreenlandic", + "lacute", + "lambda", + "lcaron", + "lcommaaccent", + "ldot", + "lfblock", + "lira", + "ll", + "logicaland", + "logicalor", + "longs", + "ltshade", + "male", + "minute", + "musicalnote", + "musicalnotedbl", + "nacute", + "napostrophe", + "ncaron", + "ncommaaccent", + "notelement", + "notsubset", + "nu", + "obreve", + "ohorn", + "ohungarumlaut", + "omacron", + "omega", + "omega1", + "omegatonos", + "omicron", + "omicrontonos", + "openbullet", + "orthogonal", + "oslashacute", + "parenleftbt", + "parenleftex", + "parenlefttp", + "parenrightbt", + "parenrightex", + "parenrighttp", + "perpendicular", + "peseta", + "phi", + "phi1", + "prescription", + "propersubset", + "propersuperset", + "proportional", + "psi", + "quotereversed", + "racute", + "radicalex", + "rcaron", + "rcommaaccent", + "reflexsubset", + "reflexsuperset", + "registersans", + "registerserif", + "revlogicalnot", + "rho", + "rtblock", + "sacute", + "scircumflex", + "scommaaccent", + "second", + "shade", + "sigma", + "sigma1", + "similar", + "smileface", + "spade", + "suchthat", + "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 */ + + 0 + }; + + + static const char** t1_standard_glyphs = standard_glyph_names + 31; + + +#define NUM_STD_GLYPHS 391 + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST +#define NUM_ADOBE_GLYPHS 1032 +#else +#define NUM_ADOBE_GLYPHS 391 +#endif + + + static const unsigned short mac_standard_names[259] = + { + 0, + 0, + 1, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 104, + 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, + 124, + 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, + 173, + 175, + 177, + 178, + 186, + 189, + 195, + 200, + 203, + 201, + 202, + 205, + 204, + 206, + 207, + 210, + 208, + 209, + 211, + 214, + 212, + 213, + 215, + 216, + 219, + 217, + 218, + 220, + 222, + 225, + 223, + 224, + 112, + 161, + 97, + 98, + 102, + 116, + 115, + 149, + 165, + 170, + 153, + 125, + 131, + 2, + 138, + 141, + 3, + 156, + 4, + 5, + 100, + 152, + 6, + 7, + 8, + 9, + 10, + 139, + 143, + 11, + 144, + 147, + 123, + 96, + 151, + 12, + 101, + 13, + 14, + 106, + 120, + 121, + 15, + 174, + 176, + 191, + 142, + 148, + 111, + 137, + 105, + 119, + 65, + 8, + 159, + 16, + 227, + 198, + 99, + 103, + 107, + 108, + 109, + 110, + 113, + 17, + 117, + 118, + 122, + 172, + 179, + 171, + 180, + 181, + 182, + 183, + 184, + 185, + 187, + 188, + 18, + 190, + 193, + 194, + 196, + 145, + 126, + 127, + 128, + 129, + 130, + 132, + 133, + 134, + 135, + 136, + 140, + 19, + 192, + 221, + 199, + 228, + 160, + 154, + 167, + 197, + 226, + 157, + 162, + 166, + 168, + 150, + 164, + 169, + 155, + 158, + 163, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 0 + }; + + + + static const unsigned short names_to_unicode[1033] = + { + 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, + 0, + 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, + 0, + 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, + 0, + 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, + 0xF6CA, + 0x0108, + 0x010A, + 0x03A7, + 0x010E, + 0x0110, + 0xF6CB, + 0xF6CC, + 0xF6CD, + 0x0114, + 0x011A, + 0x0116, + 0x0112, + 0x014A, + 0x0118, + 0x0395, + 0x0388, + 0x0397, + 0x0389, + 0x20AC, + 0x0393, + 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, + 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, + 0x015C, + 0x0218, + 0x03A3, + 0x03A4, + 0x0166, + 0x0164, + 0x0162, + 0x0162, + 0x0398, + 0xF7FA, + 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, + 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, + 0x21B5, + 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, + 0x03B3, + 0x01E7, + 0x011D, + 0x0123, + 0x0121, + 0x2207, + 0x0300, + 0x0127, + 0x0125, + 0x2665, + 0x0309, + 0x2302, + 0x012D, + 0x0133, + 0x012B, + 0x2321, + 0xF8F5, + 0x2320, + 0x2229, + 0x25D8, + 0x25D9, + 0x263B, + 0x012F, + 0x03B9, + 0x03CA, + 0x0390, + 0x03AF, + 0x0129, + 0x0135, + 0x03BA, + 0x0137, + 0x0138, + 0x013A, + 0x03BB, + 0x013E, + 0x013C, + 0x0140, + 0x258C, + 0x20A4, + 0xF6C0, + 0x2227, + 0x2228, + 0x017F, + 0x2591, + 0x2642, + 0x2032, + 0x266A, + 0x266B, + 0x0144, + 0x0149, + 0x0148, + 0x0146, + 0x2209, + 0x2284, + 0x03BD, + 0x014F, + 0x01A1, + 0x0151, + 0x014D, + 0x03C9, + 0x03D6, + 0x03CE, + 0x03BF, + 0x03CC, + 0x25E6, + 0x221F, + 0x01FF, + 0xF8ED, + 0xF8EC, + 0xF8EB, + 0xF8F8, + 0xF8F7, + 0xF8F6, + 0x22A5, + 0x20A7, + 0x03C6, + 0x03D5, + 0x211E, + 0x2282, + 0x2283, + 0x221D, + 0x03C8, + 0x201B, + 0x0155, + 0xF8E5, + 0x0159, + 0x0157, + 0x2286, + 0x2287, + 0xF8E8, + 0xF6DA, + 0x2310, + 0x03C1, + 0x2590, + 0x015B, + 0x015D, + 0x0219, + 0x2033, + 0x2592, + 0x03C3, + 0x03C2, + 0x223C, + 0x263A, + 0x2660, + 0x220B, + 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, + 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, + 0 + }; + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/psnames/rules.mk b/reactos/subsys/win32k/freetype/src/psnames/rules.mk new file mode 100644 index 00000000000..25552b26638 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/psnames/rules.mk @@ -0,0 +1,70 @@ +# +# FreeType 2 PSNames driver configuration rules +# + + +# Copyright 1996-2000 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. + + +# PSNames driver directory +# +PSNAMES_DIR := $(SRC_)psnames +PSNAMES_DIR_ := $(PSNAMES_DIR)$(SEP) + + +# compilation flags for the driver +# +PSNAMES_COMPILE := $(FT_COMPILE) + + +# PSNames driver sources (i.e., C files) +# +PSNAMES_DRV_SRC := $(PSNAMES_DIR_)psmodule.c + + +# PSNames driver headers +# +PSNAMES_DRV_H := $(PSNAMES_DRV_SRC:%.c=%.h) \ + $(PSNAMES_DIR_)pstables.h + + +# PSNames driver object(s) +# +# PSNAMES_DRV_OBJ_M is used during `multi' builds +# PSNAMES_DRV_OBJ_S is used during `single' builds +# +PSNAMES_DRV_OBJ_M := $(PSNAMES_DRV_SRC:$(PSNAMES_DIR_)%.c=$(OBJ_)%.$O) +PSNAMES_DRV_OBJ_S := $(OBJ_)psnames.$O + +# PSNames driver source file for single build +# +PSNAMES_DRV_SRC_S := $(PSNAMES_DIR_)psmodule.c + + +# PSNames driver - single object +# +$(PSNAMES_DRV_OBJ_S): $(PSNAMES_DRV_SRC_S) $(PSNAMES_DRV_SRC) \ + $(FREETYPE_H) $(PSNAMES_DRV_H) + $(PSNAMES_COMPILE) $T$@ $(PSNAMES_DRV_SRC_S) + + +# PSNames driver - multiple objects +# +$(OBJ_)%.$O: $(PSNAMES_DIR_)%.c $(FREETYPE_H) $(PSNAMES_DRV_H) + $(PSNAMES_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(PSNAMES_DRV_OBJ_S) +DRV_OBJS_M += $(PSNAMES_DRV_OBJ_M) + + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/raster1/ftraster.c b/reactos/subsys/win32k/freetype/src/raster1/ftraster.c new file mode 100644 index 00000000000..65d04057d70 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/raster1/ftraster.c @@ -0,0 +1,3300 @@ +/***************************************************************************/ +/* */ +/* ftraster.c */ +/* */ +/* The FreeType glyph rasterizer (body). */ +/* */ +/* Copyright 1996-2000 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 "ftraster.h" +#include /* 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 +#include /* for FT_TRACE() and FT_ERROR() */ + +#define Raster_Err_None FT_Err_Ok +#define Raster_Err_Not_Ini FT_Err_Raster_Uninitialized +#define Raster_Err_Overflow FT_Err_Raster_Overflow +#define Raster_Err_Neg_Height FT_Err_Raster_Negative_Height +#define Raster_Err_Invalid FT_Err_Invalid_Outline +#define Raster_Err_Unsupported FT_Err_Unimplemented_Feature + + +#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 */ + + UShort 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[2 * 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 **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Set_High_Precision */ + /* */ + /* */ + /* Sets precision variables according to param flag. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* New_Profile */ + /* */ + /* */ + /* Creates a new profile in the render pool. */ + /* */ + /* */ + /* aState :: The state/orientation of the new profile. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* End_Profile */ + /* */ + /* */ + /* Finalizes the current profile. */ + /* */ + /* */ + /* SUCCESS on success. FAILURE in case of overflow or incoherency. */ + /* */ + static + Bool End_Profile( RAS_ARG ) + { + Long h; + PProfile oldProfile; + + + h = 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Insert_Y_Turn */ + /* */ + /* */ + /* Inserts a salient into the sorted list placed on top of the render */ + /* pool. */ + /* */ + /* */ + /* New y scanline position. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Finalize_Profile_Table */ + /* */ + /* */ + /* Adjusts all links in the profiles list. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Split_Conic */ + /* */ + /* */ + /* Subdivides one conic Bezier into two joint sub-arcs in the Bezier */ + /* stack. */ + /* */ + /* */ + /* None (subdivided Bezier is taken from the top of the stack). */ + /* */ + /* */ + /* 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 ;-) */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Split_Cubic */ + /* */ + /* */ + /* Subdivides a third-order Bezier arc into two joint sub-arcs in the */ + /* Bezier stack. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_Up */ + /* */ + /* */ + /* Computes the x-coordinates of an ascending line segment and stores */ + /* them in the render pool. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 = ( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_Down */ + /* */ + /* */ + /* Computes the x-coordinates of an descending line segment and */ + /* stores them in the render pool. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 ); + + + /*************************************************************************/ + /* */ + /* */ + /* Bezier_Up */ + /* */ + /* */ + /* Computes the x-coordinates of an ascending Bezier arc and stores */ + /* them in the render pool. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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 = 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Bezier_Down */ + /* */ + /* */ + /* Computes the x-coordinates of an descending Bezier arc and stores */ + /* them in the render pool. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_To */ + /* */ + /* */ + /* Injects a new line segment and adjusts Profiles list. */ + /* */ + /* */ + /* 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'). */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Conic_To */ + /* */ + /* */ + /* Injects a new conic arc and adjusts the profile list. */ + /* */ + /* */ + /* 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'). */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Cubic_To */ + /* */ + /* */ + /* Injects a new cubic arc and adjusts the profile list. */ + /* */ + /* */ + /* 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'). */ + /* */ + /* */ + /* 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 ) + + + /*************************************************************************/ + /* */ + /* */ + /* Decompose_Curve */ + /* */ + /* */ + /* 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! */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + + char 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Convert_Glyph */ + /* */ + /* */ + /* Converts a glyph into a series of segments and arcs and makes a */ + /* profiles list with them. */ + /* */ + /* */ + /* flipped :: If set, flip the direction of curve. */ + /* */ + /* */ + /* SUCCESS on success, FAILURE if any error was encountered during */ + /* rendering. */ + /* */ + static + Bool Convert_Glyph( RAS_ARGS int flipped ) + { + Short i; + UShort 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 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 ( 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 = ¤t->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 = ¤t->link; + current = *old; + } + + /* we should never get there, unless the profile was not part of */ + /* the list. */ + } + + + /*************************************************************************/ + /* */ + /* Update */ + /* */ + /* Update all X offsets of a drawing list. */ + /* */ + static + void Update( PProfile first ) + { + PProfile current = first; + + + while ( current ) + { + current->X = *current->offset; + current->offset += current->flow; + current->height--; + current = current->link; + } + } + + + /*************************************************************************/ + /* */ + /* 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 */ + Update( *list ); + + /* Then sort them */ + old = list; + current = *old; + + if ( !current ) + return; + + next = current->link; + + while ( next ) + { + if ( current->X <= next->X ) + { + old = ¤t->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; + Short 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 = (unsigned char)0xFF >> ( e1 & 7 ); + f2 = ~( (unsigned char)0x7F >> ( e2 & 7 ) ); + + if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1; + if ( ras.gray_max_x < c2 ) ras.gray_max_x = 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 = 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 = 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 = 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 = 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 */ + + { + PProfile Q, P; + + + P = draw_left; + while ( P ) + { + Q = P->link; + if ( P->height == 0 ) + DelOld( &draw_left, P ); + P = Q; + } + } + + { + PProfile 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Render_Single_Pass */ + /* */ + /* */ + /* Performs one sweep with sub-banding. */ + /* */ + /* */ + /* flipped :: If set, flip the direction of the outline. */ + /* */ + /* */ + /* 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 = ( 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 = k - 1; + + ras.band_top++; + } + else + { + if ( ras.fProfile ) + if ( Draw_Sweep( RAS_VAR ) ) + return ras.error; + ras.band_top--; + } + } + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Render_Glyph */ + /* */ + /* */ + /* Renders a glyph in a bitmap. Sub-banding if needed. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* XXX Fixme: ftraster's error codes don't harmonize with FT2's ones! */ + /* */ + LOCAL_FUNC + 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 = !( 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 = ras.target.rows - 1; + + ras.bWidth = 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 = ras.target.width - 1; + + if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 ) + return error; + } + + return FT_Err_Ok; + } + + +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + + /*************************************************************************/ + /* */ + /* */ + /* Render_Gray_Glyph */ + /* */ + /* */ + /* Renders a glyph with grayscaling. Sub-banding if needed. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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 FT_Err_Ok; + } + +#else /* FT_RASTER_OPTION_ANTI_ALIASING */ + + LOCAL_FUNC + FT_Error Render_Gray_Glyph( RAS_ARG ) + { + FT_UNUSED_RASTER; + + return FT_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; + + if ( !outline || !outline->contours || !outline->points ) + return Raster_Err_Invalid; + + /* return immediately if the outline is empty */ + if ( outline->n_points == 0 || outline->n_contours <= 0 ) + return Raster_Err_None; + + if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 ) + return Raster_Err_Invalid; + + if ( !target_map || !target_map->buffer ) + 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; + + ras.outline = *outline; + ras.target = *target_map; + + return ( ( params->flags & ft_raster_flag_aa ) + ? Render_Gray_Glyph( raster ) + : Render_Glyph( raster ) ); + } + + + 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/reactos/subsys/win32k/freetype/src/raster1/ftraster.h b/reactos/subsys/win32k/freetype/src/raster1/ftraster.h new file mode 100644 index 00000000000..5c7faae5a26 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/raster1/ftraster.h @@ -0,0 +1,50 @@ +/***************************************************************************/ +/* */ +/* ftraster.h */ +/* */ +/* The FreeType glyph rasterizer (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef __cplusplus + extern "C" { +#endif + +#include + + + /*************************************************************************/ + /* */ + /* Uncomment the following line if you are using ftraster.c as a */ + /* standalone module, fully independent of FreeType. */ + /* */ +/* #define _STANDALONE_ */ + +#ifndef FT_EXPORT_VAR +#define FT_EXPORT_VAR( x ) extern x +#endif + + FT_EXPORT_VAR( FT_Raster_Funcs ) ft_standard_raster; + +#ifdef __cplusplus + } +#endif + + +#endif /* FTRASTER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/raster1/ftrend1.c b/reactos/subsys/win32k/freetype/src/raster1/ftrend1.c new file mode 100644 index 00000000000..d774cf1d404 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/raster1/ftrend1.c @@ -0,0 +1,275 @@ +/***************************************************************************/ +/* */ +/* ftrend1.c */ +/* */ +/* The FreeType glyph rasterizer interface (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ftrend1.h" +#include "ftraster.h" + +#else + +#include +#include + +#endif + + + /* 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 FT_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 = FT_Err_Ok; + + + if ( slot->format != render->glyph_format ) + { + error = FT_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 = FT_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 FT_Err_Cannot_Render_Glyph; + } + else + { + /* raster5 is only capable of producing 5-gray-levels bitmaps */ + if ( render->clazz == &ft_raster5_renderer_class ) + return FT_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, ¶ms ); + 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; + } + + + 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'll need */ + /* to register it by hand in your application. It should only be */ + /* used for backwards-compatibility with FT 1.x anyway. */ + 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/reactos/subsys/win32k/freetype/src/raster1/ftrend1.h b/reactos/subsys/win32k/freetype/src/raster1/ftrend1.h new file mode 100644 index 00000000000..b8fff83114a --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/raster1/ftrend1.h @@ -0,0 +1,37 @@ +/***************************************************************************/ +/* */ +/* ftrend1.h */ +/* */ +/* The FreeType glyph rasterizer interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + + 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; + + +#endif /* FTREND1_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/raster1/module.mk b/reactos/subsys/win32k/freetype/src/raster1/module.mk new file mode 100644 index 00000000000..c1ceb21293c --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/raster1/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_raster1_module + +add_raster1_module: + $(OPEN_DRIVER)ft_raster1_renderer_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)raster1 $(ECHO_DRIVER_DESC)monochrome bitmap renderer$(ECHO_DRIVER_DONE) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/raster1/raster1.c b/reactos/subsys/win32k/freetype/src/raster1/raster1.c new file mode 100644 index 00000000000..cf2835abc59 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/raster1/raster1.c @@ -0,0 +1,35 @@ +/***************************************************************************/ +/* */ +/* raster1.c */ +/* */ +/* FreeType monochrome rasterer module component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ftraster.c" +#include "ftrend1.c" + +#else + +#include +#include + +#endif + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/raster1/rules.mk b/reactos/subsys/win32k/freetype/src/raster1/rules.mk new file mode 100644 index 00000000000..38108450ef5 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/raster1/rules.mk @@ -0,0 +1,69 @@ +# +# FreeType 2 renderer module build rules +# + + +# Copyright 1996-2000 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. + + +# raster1 driver directory +# +RAS1_DIR := $(SRC_)raster1 +RAS1_DIR_ := $(RAS1_DIR)$(SEP) + +# compilation flags for the driver +# +RAS1_COMPILE := $(FT_COMPILE) + + +# raster1 driver sources (i.e., C files) +# +RAS1_DRV_SRC := $(RAS1_DIR_)ftraster.c \ + $(RAS1_DIR_)ftrend1.c + + +# raster1 driver headers +# +RAS1_DRV_H := $(RAS1_DRV_SRC:%.c=%.h) + + +# raster1 driver object(s) +# +# RAS1_DRV_OBJ_M is used during `multi' builds. +# RAS1_DRV_OBJ_S is used during `single' builds. +# +RAS1_DRV_OBJ_M := $(RAS1_DRV_SRC:$(RAS1_DIR_)%.c=$(OBJ_)%.$O) +RAS1_DRV_OBJ_S := $(OBJ_)raster1.$O + +# raster1 driver source file for single build +# +RAS1_DRV_SRC_S := $(RAS1_DIR_)raster1.c + + +# raster1 driver - single object +# +$(RAS1_DRV_OBJ_S): $(RAS1_DRV_SRC_S) $(RAS1_DRV_SRC) \ + $(FREETYPE_H) $(RAS1_DRV_H) + $(RAS1_COMPILE) $T$@ $(RAS1_DRV_SRC_S) + + +# raster1 driver - multiple objects +# +$(OBJ_)%.$O: $(RAS1_DIR_)%.c $(FREETYPE_H) $(RAS1_DRV_H) + $(RAS1_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(RAS1_DRV_OBJ_S) +DRV_OBJS_M += $(RAS1_DRV_OBJ_M) + + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/sfnt/module.mk b/reactos/subsys/win32k/freetype/src/sfnt/module.mk new file mode 100644 index 00000000000..48b494f4d2c --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_sfnt_module + +add_sfnt_module: + $(OPEN_DRIVER)sfnt_module_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)sfnt $(ECHO_DRIVER_DESC)helper module for TrueType & OpenType formats$(ECHO_DRIVER_DONE) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/sfnt/rules.mk b/reactos/subsys/win32k/freetype/src/sfnt/rules.mk new file mode 100644 index 00000000000..2255e6a087f --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/rules.mk @@ -0,0 +1,73 @@ +# +# FreeType 2 SFNT driver configuration rules +# + + +# Copyright 1996-2000 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. + + +# SFNT driver directory +# +SFNT_DIR := $(SRC_)sfnt +SFNT_DIR_ := $(SFNT_DIR)$(SEP) + + +# compilation flags for the driver +# +SFNT_COMPILE := $(FT_COMPILE) + + +# SFNT driver sources (i.e., C files) +# +SFNT_DRV_SRC := $(SFNT_DIR_)ttload.c \ + $(SFNT_DIR_)ttcmap.c \ + $(SFNT_DIR_)ttsbit.c \ + $(SFNT_DIR_)ttpost.c \ + $(SFNT_DIR_)sfobjs.c \ + $(SFNT_DIR_)sfdriver.c + +# SFNT driver headers +# +SFNT_DRV_H := $(SFNT_DRV_SRC:%c=%h) + + +# SFNT driver object(s) +# +# SFNT_DRV_OBJ_M is used during `multi' builds. +# SFNT_DRV_OBJ_S is used during `single' builds. +# +SFNT_DRV_OBJ_M := $(SFNT_DRV_SRC:$(SFNT_DIR_)%.c=$(OBJ_)%.$O) +SFNT_DRV_OBJ_S := $(OBJ_)sfnt.$O + +# SFNT driver source file for single build +# +SFNT_DRV_SRC_S := $(SFNT_DIR_)sfnt.c + + +# SFNT driver - single object +# +$(SFNT_DRV_OBJ_S): $(SFNT_DRV_SRC_S) $(SFNT_DRV_SRC) \ + $(FREETYPE_H) $(SFNT_DRV_H) + $(SFNT_COMPILE) $T$@ $(SFNT_DRV_SRC_S) + + +# SFNT driver - multiple objects +# +$(OBJ_)%.$O: $(SFNT_DIR_)%.c $(FREETYPE_H) $(SFNT_DRV_H) + $(SFNT_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(SFNT_DRV_OBJ_S) +DRV_OBJS_M += $(SFNT_DRV_OBJ_M) + + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/sfnt/sfdriver.c b/reactos/subsys/win32k/freetype/src/sfnt/sfdriver.c new file mode 100644 index 00000000000..96a738b43cc --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/sfdriver.c @@ -0,0 +1,225 @@ +/***************************************************************************/ +/* */ +/* sfdriver.c */ +/* */ +/* High-level SFNT driver interface (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "sfdriver.h" +#include "ttload.h" +#include "ttsbit.h" +#include "ttpost.h" +#include "ttcmap.h" +#include "sfobjs.h" + +#else + +#include +#include +#include +#include +#include +#include + +#endif + + +#include /* 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 = strlen( gname ); + + + if ( len >= buffer_max ) + len = buffer_max - 1; + + MEM_Copy( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return error; + } + + +#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + + static + 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 + 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 `ttsbit.h' */ + TT_Load_SBit_Strikes, + TT_Load_SBit_Image, + TT_Free_SBit_Strikes, + +#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + 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, + }; + + + 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/reactos/subsys/win32k/freetype/src/sfnt/sfdriver.h b/reactos/subsys/win32k/freetype/src/sfnt/sfdriver.h new file mode 100644 index 00000000000..92c9c8129d1 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/sfdriver.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* sfdriver.h */ +/* */ +/* High-level SFNT driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + FT_EXPORT_VAR( const FT_Module_Class ) sfnt_module_class; + +#endif /* SFDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/sfnt/sfnt.c b/reactos/subsys/win32k/freetype/src/sfnt/sfnt.c new file mode 100644 index 00000000000..cca73425cec --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/sfnt.c @@ -0,0 +1,57 @@ +/***************************************************************************/ +/* */ +/* sfnt.c */ +/* */ +/* Single object library component. */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.c" +#include "ttcmap.c" +#include "sfobjs.c" + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS +#include "ttsbit.c" +#endif + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include "ttpost.c" +#endif + +#include "sfdriver.c" + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS +#include +#endif + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include +#endif + +#include + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/sfnt/sfobjs.c b/reactos/subsys/win32k/freetype/src/sfnt/sfobjs.c new file mode 100644 index 00000000000..4ae85022e8e --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/sfobjs.c @@ -0,0 +1,561 @@ +/***************************************************************************/ +/* */ +/* sfobjs.c */ +/* */ +/* SFNT object management (base). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "sfobjs.h" + +#else + +#include + +#endif + + +#include +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Name */ + /* */ + /* */ + /* Returns a given ENGLISH name record in ASCII. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* nameid :: The name id of the name record to 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_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; + } + + + LOCAL_FUNC + 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 = FT_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 ) ) \ + != TT_Err_Ok ) + + + LOCAL_FUNC + 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; + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + FT_UNUSED( face_index ); + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + /* Load tables */ + if ( LOAD_( header ) || + LOAD_( max_profile ) || + + /* load the `hhea' & `hmtx' tables at once */ + ( error = sfnt->load_metrics( face, stream, 0 ) ) != TT_Err_Ok || + + /* try to load the `vhea' & `vmtx' at once if present */ + ( error = sfnt->load_metrics( face, stream, 1 ) ) != TT_Err_Ok || + + LOAD_( charmaps ) || + LOAD_( names ) || + LOAD_( os2 ) || + LOAD_( psnames ) ) + goto Exit; + + /* the optional tables */ + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + /* embedded bitmap support. */ + if ( sfnt->load_sbits && LOAD_( sbits ) ) + 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 ) ) != TT_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; + TT_CharMap charmap; + FT_Int n; + FT_Memory memory; + + + memory = root->memory; + + /*********************************************************************/ + /* */ + /* Compute face flags. */ + /* */ + flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ + 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 ( 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 = platform; + charmap->root.encoding_id = 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->num_fixed_sizes = face->num_sbit_strikes; + if ( ALLOC_ARRAY( root->available_sizes, + face->num_sbit_strikes, + FT_Bitmap_Size ) ) + return error; + + 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 + +#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + { + root->num_fixed_sizes = 0; + root->available_sizes = 0; + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /*********************************************************************/ + /* */ + /* Set up metrics. */ + /* */ + 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; + + /* The ascender/descender/height are computed from the OS/2 table */ + /* when found. Otherwise, they're taken from the horizontal header. */ + if ( face->os2.version != 0xFFFF ) + { + root->ascender = face->os2.sTypoAscender; + root->descender = -face->os2.sTypoDescender; + root->height = root->ascender + root->descender + + face->os2.sTypoLineGap; + } + else + { + root->ascender = face->horizontal.Ascender; + root->descender = face->horizontal.Descender; + root->height = root->ascender + root->descender + + face->horizontal.Line_Gap; + } + + root->max_advance_width = face->horizontal.advance_Width_Max; + + root->max_advance_height = 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_ + + + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/src/sfnt/sfobjs.h b/reactos/subsys/win32k/freetype/src/sfnt/sfobjs.h new file mode 100644 index 00000000000..35d92f9d198 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/sfobjs.h @@ -0,0 +1,57 @@ +/***************************************************************************/ +/* */ +/* sfobjs.h */ +/* */ +/* SFNT object management (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error SFNT_Init_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + FT_Error SFNT_Load_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void SFNT_Done_Face( TT_Face face ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* SFDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/sfnt/ttcmap.c b/reactos/subsys/win32k/freetype/src/sfnt/ttcmap.c new file mode 100644 index 00000000000..87ad04f0148 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/ttcmap.c @@ -0,0 +1,550 @@ +/***************************************************************************/ +/* */ +/* ttcmap.c */ +/* */ +/* TrueType character mapping table (cmap) support (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.h" +#include "ttcmap.h" + +#else + +#include +#include + +#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_ttcmap + + + static FT_UInt code_to_index0( TT_CMapTable* charmap, + FT_ULong char_code ); + static FT_UInt code_to_index2( TT_CMapTable* charmap, + FT_ULong char_code ); + static FT_UInt code_to_index4( TT_CMapTable* charmap, + FT_ULong char_code ); + static FT_UInt code_to_index6( TT_CMapTable* charmap, + FT_ULong char_code ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Load */ + /* */ + /* */ + /* Loads a given TrueType character map into memory. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* stream :: A handle to the current stream object. */ + /* */ + /* */ + /* table :: A pointer to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The function assumes that the stream is already in use (i.e., */ + /* opened). In case of error, all partially allocated tables are */ + /* released. */ + /* */ + LOCAL_FUNC + 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_UShort u, l; + + TT_CMap0* cmap0; + TT_CMap2* cmap2; + TT_CMap4* cmap4; + TT_CMap6* cmap6; + + TT_CMap2SubHeader* cmap2sub; + TT_CMap4Segment* segments; + + + if ( cmap->loaded ) + return TT_Err_Ok; + + memory = stream->memory; + + if ( FILE_Seek( cmap->offset ) ) + return error; + + switch ( cmap->format ) + { + case 0: + cmap0 = &cmap->c.cmap0; + + if ( 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( 512L ) ) + goto Fail; + + for ( i = 0; i < 256; i++ ) + { + u = GET_UShort() / 8; + cmap2->subHeaderKeys[i] = u; + + if ( num_SH < u ) + num_SH = u; + } + + FORGET_Frame(); + + /* load subheaders */ + + cmap2->numGlyphId = l = + ( ( 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 ) ) + 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 = 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 ) ) + 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( 8L ) ) + goto Fail; + + cmap4->segCountX2 = GET_UShort(); + cmap4->searchRange = GET_UShort(); + cmap4->entrySelector = GET_UShort(); + cmap4->rangeShift = GET_UShort(); + + num_Seg = 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 = + ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFF ) / 2; + + /* load IDs */ + + if ( ALLOC_ARRAY( cmap4->glyphIdArray, l, FT_UShort ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap4->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + + cmap->get_index = code_to_index4; + + cmap4->last_segment = cmap4->segments; + break; + + case 6: + cmap6 = &cmap->c.cmap6; + + if ( ACCESS_Frame( 4L ) ) + goto Fail; + + cmap6->firstCode = GET_UShort(); + cmap6->entryCount = GET_UShort(); + + FORGET_Frame(); + + l = cmap6->entryCount; + + if ( ALLOC_ARRAY( cmap6->glyphIdArray, + cmap6->entryCount, + 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; + + default: /* corrupt character mapping table */ + return TT_Err_Invalid_CharMap_Format; + + } + + return TT_Err_Ok; + + Fail: + TT_CharMap_Free( face, cmap ); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Free */ + /* */ + /* */ + /* Destroys a character mapping table. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* cmap :: A handle to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_CharMap_Free( TT_Face face, + TT_CMapTable* cmap ) + { + FT_Memory memory; + + + if ( !cmap ) + return TT_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; + + default: + /* invalid table format, do nothing */ + ; + } + + cmap->loaded = FALSE; + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index0 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 0. */ + /* `charCode' must be in the range 0x00-0xFF (otherwise 0 is */ + /* returned). */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap0 :: A pointer to a cmap table in format 0. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + FT_UInt code_to_index0( TT_CMapTable* cmap, + FT_ULong charCode ) + { + TT_CMap0* cmap0 = &cmap->c.cmap0; + + + return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index2 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 2. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap2 :: A pointer to a cmap table in format 2. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + 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 */ + if ( cmap2->subHeaderKeys[char_lo] == 0 ) + result = cmap2->glyphIdArray[char_lo]; + } + else + { + /* a 16-bit character code */ + index1 = cmap2->subHeaderKeys[char_hi & 0xFF]; + if ( index1 ) + { + sh2 = cmap2->subHeaders + index1; + char_lo -= sh2->firstCode; + + if ( char_lo < sh2->entryCount ) + { + offset = sh2->idRangeOffset / 2 + char_lo; + if ( offset < cmap2->numGlyphId ) + { + result = cmap2->glyphIdArray[offset]; + if ( result ) + result = ( result + sh2->idDelta ) & 0xFFFF; + } + } + } + } + + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index4 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 4. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap4 :: A pointer to a cmap table in format 4. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + 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; + seg4 = cmap4->segments; + limit = seg4 + segCount; + + /* check against the last segment */ + seg4 = cmap4->last_segment; + + /* the following is equivalent to performing two tests, as in */ + /* */ + /* if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */ + /* */ + /* Yes, that's a bit strange, but it's 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 Found; + + 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 > seg4->endCount ) + continue; + + if ( charCode >= seg4->startCount ) + goto Found; + } + return 0; + + Found: + cmap4->last_segment = seg4; + + /* 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 = seg4->idRangeOffset / 2 + + ( charCode - seg4->startCount ) + + ( seg4 - cmap4->segments ) + - segCount; + + if ( index1 < cmap4->numGlyphId && + cmap4->glyphIdArray[index1] != 0 ) + result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFF; + } + + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index6 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 6. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap6 :: A pointer to a cmap table in format 6. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + FT_UInt code_to_index6( TT_CMapTable* cmap, + FT_ULong charCode ) + { + TT_CMap6* cmap6; + FT_UInt result = 0; + + + cmap6 = &cmap->c.cmap6; + result = 0; + charCode -= cmap6->firstCode; + + if ( charCode < cmap6->entryCount ) + result = cmap6->glyphIdArray[charCode]; + + return result; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/sfnt/ttcmap.h b/reactos/subsys/win32k/freetype/src/sfnt/ttcmap.h new file mode 100644 index 00000000000..609972a901e --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/ttcmap.h @@ -0,0 +1,45 @@ +/***************************************************************************/ +/* */ +/* ttcmap.h */ +/* */ +/* TrueType character mapping table (cmap) support (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error TT_CharMap_Load( TT_Face face, + TT_CMapTable* cmap, + FT_Stream input ); + + LOCAL_DEF + FT_Error TT_CharMap_Free( TT_Face face, + TT_CMapTable* cmap ); + +#ifdef __cplusplus + } +#endif + +#endif /* TTCMAP_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/sfnt/ttload.c b/reactos/subsys/win32k/freetype/src/sfnt/ttload.c new file mode 100644 index 00000000000..e7871874df1 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/ttload.c @@ -0,0 +1,1676 @@ +/***************************************************************************/ +/* */ +/* ttload.c */ +/* */ +/* Load the basic TrueType tables, i.e., tables that can be either in */ +/* TTF or OTF fonts (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.h" +#include "ttcmap.h" + +#else + +#include +#include + +#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_ttload + + + /*************************************************************************/ + /* */ + /* */ + /* TT_LookUp_Table */ + /* */ + /* */ + /* Looks for a TrueType table by name. */ + /* */ + /* */ + /* face :: A face object handle. */ + /* tag :: The searched tag. */ + /* */ + /* */ + /* A pointer to the table directory entry. 0 if not found. */ + /* */ + LOCAL_FUNC + 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'\n", + 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 ) + return entry; + } + + FT_TRACE3(( " Could not find table!\n" )); + return 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Goto_Table */ + /* */ + /* */ + /* Looks for a TrueType table by name, then seek a stream to it. */ + /* */ + /* */ + /* face :: A face object handle. */ + /* tag :: The searched tag. */ + /* stream :: The stream to seek when the table is found. */ + /* */ + /* */ + /* length :: The length of the table if found, undefined otherwise. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + + (void)FILE_Seek( table->Offset ); + } + else + error = TT_Err_Table_Missing; + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SFNT_Header */ + /* */ + /* */ + /* Loads the header of a SFNT font file. Supports collections. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* sfnt :: The SFNT header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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'. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_USHORT( SFNT_Header, num_tables ), + FT_FRAME_USHORT( SFNT_Header, search_range ), + FT_FRAME_USHORT( SFNT_Header, entry_selector ), + FT_FRAME_USHORT( SFNT_Header, range_shift ), + FT_FRAME_END + }; + + const FT_Frame_Field ttc_header_fields[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_LONG( TTC_Header, version ), + FT_FRAME_LONG( TTC_Header, 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 = TT_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 = FT_Err_Unknown_File_Format; + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Directory */ + /* */ + /* */ + /* Loads the table directory into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* sfnt :: The SFNT directory header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Any */ + /* */ + /* */ + /* Loads any font table into client memory. */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* buffer :: The address of target buffer. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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 = TT_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 TT_Err_Ok; + } + + if ( length ) + size = *length; + + stream = face->root.stream; + (void)FILE_Read_At( offset, buffer, size ); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Header */ + /* */ + /* */ + /* Loads the TrueType font header. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Header( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_Header* header; + + static const FT_Frame_Field header_fields[] = + { + FT_FRAME_START( 54 ), + FT_FRAME_ULONG( TT_Header, Table_Version ), + FT_FRAME_ULONG( TT_Header, Font_Revision ), + FT_FRAME_LONG( TT_Header, CheckSum_Adjust ), + FT_FRAME_LONG( TT_Header, Magic_Number ), + FT_FRAME_USHORT( TT_Header, Flags ), + FT_FRAME_USHORT( TT_Header, Units_Per_EM ), + FT_FRAME_LONG( TT_Header, Created[0] ), + FT_FRAME_LONG( TT_Header, Created[1] ), + FT_FRAME_LONG( TT_Header, Modified[0] ), + FT_FRAME_LONG( TT_Header, Modified[1] ), + FT_FRAME_SHORT( TT_Header, xMin ), + FT_FRAME_SHORT( TT_Header, yMin ), + FT_FRAME_SHORT( TT_Header, xMax ), + FT_FRAME_SHORT( TT_Header, yMax ), + FT_FRAME_USHORT( TT_Header, Mac_Style ), + FT_FRAME_USHORT( TT_Header, Lowest_Rec_PPEM ), + FT_FRAME_SHORT( TT_Header, Font_Direction ), + FT_FRAME_SHORT( TT_Header, Index_To_Loc_Format ), + FT_FRAME_SHORT( TT_Header, Glyph_Data_Format ), + FT_FRAME_END + }; + + + FT_TRACE2(( "Load_TT_Header: %08p\n", face )); + + error = face->goto_table( face, TTAG_head, stream, 0 ); + if ( error ) + { + FT_TRACE0(( "Font Header 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(( "Font Header Loaded.\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_MaxProfile */ + /* */ + /* */ + /* Loads the maximum profile into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 32 ), + FT_FRAME_ULONG( TT_MaxProfile, version ), + FT_FRAME_USHORT( TT_MaxProfile, numGlyphs ), + FT_FRAME_USHORT( TT_MaxProfile, maxPoints ), + FT_FRAME_USHORT( TT_MaxProfile, maxContours ), + FT_FRAME_USHORT( TT_MaxProfile, maxCompositePoints ), + FT_FRAME_USHORT( TT_MaxProfile, maxCompositeContours ), + FT_FRAME_USHORT( TT_MaxProfile, maxZones ), + FT_FRAME_USHORT( TT_MaxProfile, maxTwilightPoints ), + FT_FRAME_USHORT( TT_MaxProfile, maxStorage ), + FT_FRAME_USHORT( TT_MaxProfile, maxFunctionDefs ), + FT_FRAME_USHORT( TT_MaxProfile, maxInstructionDefs ), + FT_FRAME_USHORT( TT_MaxProfile, maxStackElements ), + FT_FRAME_USHORT( TT_MaxProfile, maxSizeOfInstructions ), + FT_FRAME_USHORT( TT_MaxProfile, maxComponentElements ), + FT_FRAME_USHORT( TT_MaxProfile, 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; + + /* 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.max_points = MAX( maxProfile->maxCompositePoints, + maxProfile->maxPoints ); + + face->root.max_contours = 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.max_points += 8; + face->root.max_contours += 4; + + FT_TRACE2(( "MAXP loaded.\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Metrics */ + /* */ + /* */ + /* Loads the horizontal or vertical metrics table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* */ + /* 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 = TT_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 = TT_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 ? TT_Err_Invalid_Vert_Metrics + : TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Metrics_Header */ + /* */ + /* */ + /* Loads the horizontal or vertical header in a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 36 ), + FT_FRAME_ULONG( TT_HoriHeader, Version ), + FT_FRAME_SHORT( TT_HoriHeader, Ascender ), + FT_FRAME_SHORT( TT_HoriHeader, Descender ), + FT_FRAME_SHORT( TT_HoriHeader, Line_Gap ), + FT_FRAME_USHORT( TT_HoriHeader, advance_Width_Max ), + FT_FRAME_SHORT( TT_HoriHeader, min_Left_Side_Bearing ), + FT_FRAME_SHORT( TT_HoriHeader, min_Right_Side_Bearing ), + FT_FRAME_SHORT( TT_HoriHeader, xMax_Extent ), + FT_FRAME_SHORT( TT_HoriHeader, caret_Slope_Rise ), + FT_FRAME_SHORT( TT_HoriHeader, caret_Slope_Run ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[0] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[1] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[2] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[3] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[4] ), + FT_FRAME_SHORT( TT_HoriHeader, metric_Data_Format ), + FT_FRAME_USHORT( TT_HoriHeader, 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 = TT_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 = TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Names */ + /* */ + /* */ + /* Loads the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 6 ), + FT_FRAME_USHORT( TT_NameTable, format ), + FT_FRAME_USHORT( TT_NameTable, numNameRecords ), + FT_FRAME_USHORT( TT_NameTable, storageOffset ), + FT_FRAME_END + }; + + const FT_Frame_Field name_record_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_USHORT( TT_NameRec, platformID ), + FT_FRAME_USHORT( TT_NameRec, encodingID ), + FT_FRAME_USHORT( TT_NameRec, languageID ), + FT_FRAME_USHORT( TT_NameRec, nameID ), + FT_FRAME_USHORT( TT_NameRec, stringLength ), + FT_FRAME_USHORT( TT_NameRec, 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 = TT_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; + + + (void)READ_Fields( name_record_fields, cur ); + + 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 < 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Names */ + /* */ + /* */ + /* Frees the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_CMap */ + /* */ + /* */ + /* Loads the cmap directory in a face object. The cmaps itselves are */ + /* loaded on demand in the `ttcmap.c' module. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 4 ), + FT_FRAME_USHORT( TT_CMapDir, tableVersionNumber ), + FT_FRAME_USHORT( TT_CMapDir, numCMaps ), + FT_FRAME_END + }; + + const FT_Frame_Field cmap_rec_fields[] = + { + FT_FRAME_START( 6 ), + FT_FRAME_USHORT( TT_CMapTable, format ), + FT_FRAME_USHORT( TT_CMapTable, length ), + FT_FRAME_USHORT( TT_CMapTable, version ), + FT_FRAME_END + }; + + + FT_TRACE2(( "CMaps " )); + + error = face->goto_table( face, TTAG_cmap, stream, 0 ); + if ( error ) + { + error = TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_OS2 */ + /* */ + /* */ + /* Loads the OS2 table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_OS2( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_OS2* os2; + + const FT_Frame_Field os2_fields[] = + { + FT_FRAME_START( 78 ), + FT_FRAME_USHORT( TT_OS2, version ), + FT_FRAME_SHORT( TT_OS2, xAvgCharWidth ), + FT_FRAME_USHORT( TT_OS2, usWeightClass ), + FT_FRAME_USHORT( TT_OS2, usWidthClass ), + FT_FRAME_SHORT( TT_OS2, fsType ), + FT_FRAME_SHORT( TT_OS2, ySubscriptXSize ), + FT_FRAME_SHORT( TT_OS2, ySubscriptYSize ), + FT_FRAME_SHORT( TT_OS2, ySubscriptXOffset ), + FT_FRAME_SHORT( TT_OS2, ySubscriptYOffset ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptXSize ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptYSize ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptXOffset ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptYOffset ), + FT_FRAME_SHORT( TT_OS2, yStrikeoutSize ), + FT_FRAME_SHORT( TT_OS2, yStrikeoutPosition ), + FT_FRAME_SHORT( TT_OS2, sFamilyClass ), + FT_FRAME_BYTE( TT_OS2, panose[0] ), + FT_FRAME_BYTE( TT_OS2, panose[1] ), + FT_FRAME_BYTE( TT_OS2, panose[2] ), + FT_FRAME_BYTE( TT_OS2, panose[3] ), + FT_FRAME_BYTE( TT_OS2, panose[4] ), + FT_FRAME_BYTE( TT_OS2, panose[5] ), + FT_FRAME_BYTE( TT_OS2, panose[6] ), + FT_FRAME_BYTE( TT_OS2, panose[7] ), + FT_FRAME_BYTE( TT_OS2, panose[8] ), + FT_FRAME_BYTE( TT_OS2, panose[9] ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange1 ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange2 ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange3 ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange4 ), + FT_FRAME_BYTE( TT_OS2, achVendID[0] ), + FT_FRAME_BYTE( TT_OS2, achVendID[1] ), + FT_FRAME_BYTE( TT_OS2, achVendID[2] ), + FT_FRAME_BYTE( TT_OS2, achVendID[3] ), + + FT_FRAME_USHORT( TT_OS2, fsSelection ), + FT_FRAME_USHORT( TT_OS2, usFirstCharIndex ), + FT_FRAME_USHORT( TT_OS2, usLastCharIndex ), + FT_FRAME_SHORT( TT_OS2, sTypoAscender ), + FT_FRAME_SHORT( TT_OS2, sTypoDescender ), + FT_FRAME_SHORT( TT_OS2, sTypoLineGap ), + FT_FRAME_USHORT( TT_OS2, usWinAscent ), + FT_FRAME_USHORT( TT_OS2, usWinDescent ), + FT_FRAME_END + }; + + const FT_Frame_Field os2_fields_extra[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_ULONG( TT_OS2, ulCodePageRange1 ), + FT_FRAME_ULONG( TT_OS2, ulCodePageRange2 ), + FT_FRAME_END + }; + + const FT_Frame_Field os2_fields_extra2[] = + { + FT_FRAME_START( 10 ), + FT_FRAME_SHORT( TT_OS2, sxHeight ), + FT_FRAME_SHORT( TT_OS2, sCapHeight ), + FT_FRAME_USHORT( TT_OS2, usDefaultChar ), + FT_FRAME_USHORT( TT_OS2, usBreakChar ), + FT_FRAME_USHORT( TT_OS2, 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 = TT_Err_Ok; + goto Exit; + } + + os2 = &face->os2; + + if ( READ_Fields( os2_fields, os2 ) ) + goto Exit; + + os2->ulCodePageRange1 = 0; + os2->ulCodePageRange2 = 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Postscript */ + /* */ + /* */ + /* Loads the Postscript table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 32 ), + FT_FRAME_ULONG( TT_Postscript, FormatType ), + FT_FRAME_ULONG( TT_Postscript, italicAngle ), + FT_FRAME_SHORT( TT_Postscript, underlinePosition ), + FT_FRAME_SHORT( TT_Postscript, underlineThickness ), + FT_FRAME_ULONG( TT_Postscript, isFixedPitch ), + FT_FRAME_ULONG( TT_Postscript, minMemType42 ), + FT_FRAME_ULONG( TT_Postscript, maxMemType42 ), + FT_FRAME_ULONG( TT_Postscript, minMemType1 ), + FT_FRAME_ULONG( TT_Postscript, maxMemType1 ), + FT_FRAME_END + }; + + + FT_TRACE2(( "PostScript " )); + + error = face->goto_table( face, TTAG_post, stream, 0 ); + if ( error ) + return TT_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 TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_PCLT */ + /* */ + /* */ + /* Loads the PCL 5 Table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_PCLT( TT_Face face, + FT_Stream stream ) + { + static const FT_Frame_Field pclt_fields[] = + { + FT_FRAME_START( 54 ), + FT_FRAME_ULONG ( TT_PCLT, Version ), + FT_FRAME_ULONG ( TT_PCLT, FontNumber ), + FT_FRAME_USHORT( TT_PCLT, Pitch ), + FT_FRAME_USHORT( TT_PCLT, xHeight ), + FT_FRAME_USHORT( TT_PCLT, Style ), + FT_FRAME_USHORT( TT_PCLT, TypeFamily ), + FT_FRAME_USHORT( TT_PCLT, CapHeight ), + FT_FRAME_BYTES ( TT_PCLT, TypeFace, 16 ), + FT_FRAME_BYTES ( TT_PCLT, CharacterComplement, 8 ), + FT_FRAME_BYTES ( TT_PCLT, FileName, 6 ), + FT_FRAME_CHAR ( TT_PCLT, StrokeWeight ), + FT_FRAME_CHAR ( TT_PCLT, WidthType ), + FT_FRAME_BYTE ( TT_PCLT, SerifStyle ), + FT_FRAME_BYTE ( TT_PCLT, 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 TT_Err_Ok; + } + + if ( READ_Fields( pclt_fields, pclt ) ) + goto Exit; + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Gasp */ + /* */ + /* */ + /* Loads the `gasp' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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 TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Kern */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Kern( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_UInt n, num_tables, version; + + + /* the kern table is optional; exit silently if it is missing */ + error = face->goto_table( face, TTAG_kern, stream, 0 ); + if ( error ) + return TT_Err_Ok; + + if ( ACCESS_Frame( 4L ) ) + goto Exit; + + version = GET_UShort(); + 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; + + version = 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; + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Hdmx */ + /* */ + /* */ + /* Loads the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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 TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Hdmx */ + /* */ + /* */ + /* Frees the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/src/sfnt/ttload.h b/reactos/subsys/win32k/freetype/src/sfnt/ttload.h new file mode 100644 index 00000000000..dd0de6a4f1c --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/ttload.h @@ -0,0 +1,132 @@ +/***************************************************************************/ +/* */ +/* ttload.h */ +/* */ +/* Load the basic TrueType tables, i.e., tables that can be either in */ +/* TTF or OTF fonts (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + TT_Table* TT_LookUp_Table( TT_Face face, + FT_ULong tag ); + + LOCAL_DEF + FT_Error TT_Goto_Table( TT_Face face, + FT_ULong tag, + FT_Stream stream, + FT_ULong* length ); + + + LOCAL_DEF + FT_Error TT_Load_SFNT_Header( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header* sfnt ); + LOCAL_DEF + FT_Error TT_Load_Directory( TT_Face face, + FT_Stream stream, + SFNT_Header* sfnt ); + + LOCAL_DEF + FT_Error TT_Load_Any( TT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ); + + + LOCAL_DEF + FT_Error TT_Load_Header( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Metrics_Header( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + LOCAL_DEF + FT_Error TT_Load_CMap( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_MaxProfile( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Names( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_OS2( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_PostScript( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Hdmx( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + FT_Error TT_Load_PCLT( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void TT_Free_Names( TT_Face face ); + + + LOCAL_DEF + void TT_Free_Hdmx ( TT_Face face ); + + + LOCAL_DEF + FT_Error TT_Load_Kern( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Gasp( TT_Face face, + FT_Stream stream ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/sfnt/ttpost.c b/reactos/subsys/win32k/freetype/src/sfnt/ttpost.c new file mode 100644 index 00000000000..c83205baed7 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/ttpost.c @@ -0,0 +1,536 @@ +/***************************************************************************/ +/* */ +/* ttpost.c */ +/* */ +/* Postcript name table processing for TrueType and OpenType fonts */ +/* (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttpost.h" +#include "ttload.h" + +#else + +#include +#include + +#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_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 + +#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_Int 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 = TT_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 = index; + } + } + } + + /* now load the name strings */ + { + FT_Int 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 = num_glyphs; + table->num_names = num_names; + table->glyph_indices = glyph_indices; + table->glyph_names = name_strings; + } + return TT_Err_Ok; + + + Fail1: + { + FT_Int 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 = TT_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 = TT_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 = num_glyphs; + table->offsets = offset_table; + } + + return TT_Err_Ok; + + Fail: + FREE( offset_table ); + + Exit: + return error; + } + + + static + FT_Error Load_Post_Names( TT_Face face ) + { + FT_Stream stream; + FT_Error error; + + /* 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; + + /* now read postscript table */ + switch ( face->postscript.FormatType ) + { + case 0x00020000L: + error = Load_Format_20( face, stream ); + break; + + case 0x00028000L: + error = Load_Format_25( face, stream ); + break; + + default: + error = TT_Err_Invalid_File_Format; + } + + face->postscript_names.loaded = 1; + + Exit: + return error; + } + + + LOCAL_FUNC + 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_UInt 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_PS_Name */ + /* */ + /* */ + /* Gets the PostScript glyph name of a glyph. */ + /* */ + /* */ + /* 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! */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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 TT_Err_Invalid_Face_Handle; + + if ( index >= (FT_UInt)face->root.num_glyphs ) + return TT_Err_Invalid_Glyph_Index; + +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + psnames = (PSNames_Interface*)face->psnames; + if ( !psnames ) + return TT_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 < 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 < table->num_glyphs ) /* paranoid checking */ + { + index += table->offsets[index]; + *PSname = MAC_NAME( index ); + } + } + break; + + case 0x00030000L: + break; /* nothing to do */ + } + + return TT_Err_Ok; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/sfnt/ttpost.h b/reactos/subsys/win32k/freetype/src/sfnt/ttpost.h new file mode 100644 index 00000000000..e3da83606d0 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/ttpost.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ttpost.h */ +/* */ +/* Postcript name table processing for TrueType and OpenType fonts */ +/* (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +#define TT_Err_Invalid_Post_Table_Format 0x0B00 +#define TT_Err_Invalid_Post_Table 0x0B01 + + + LOCAL_DEF + FT_Error TT_Get_PS_Name( TT_Face face, + FT_UInt index, + FT_String** PSname ); + + LOCAL_DEF + void TT_Free_Post_Names( TT_Face face ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTPOST_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/sfnt/ttsbit.c b/reactos/subsys/win32k/freetype/src/sfnt/ttsbit.c new file mode 100644 index 00000000000..9a5455afb8d --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/ttsbit.c @@ -0,0 +1,1444 @@ +/***************************************************************************/ +/* */ +/* ttsbit.c */ +/* */ +/* TrueType and OpenType embedded bitmap support (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttsbit.h" + +#else + +#include + +#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_ttsbit + + + /*************************************************************************/ + /* */ + /* */ + /* blit_sbit */ + /* */ + /* */ + /* Blits a bitmap from an input stream into a given target. Supports */ + /* x and y offsets as well as byte padded lines. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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_Byte 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 = x_offset & 7; /* current write shift */ + FT_Byte space = 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 ( loaded < count ) + { + acc |= (FT_UShort)*source++ << ( 8 - loaded ); + loaded += 8; + } + + /* now write remaining bits */ + val = ( (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 = loaded = 0; /* clear accumulator on byte-padded lines */ + + line_buff += line_incr; + } + } + + + const FT_Frame_Field sbit_metrics_fields[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_BYTE( TT_SBit_Metrics, height ), + FT_FRAME_BYTE( TT_SBit_Metrics, width ), + + FT_FRAME_CHAR( TT_SBit_Metrics, horiBearingX ), + FT_FRAME_CHAR( TT_SBit_Metrics, horiBearingY ), + FT_FRAME_BYTE( TT_SBit_Metrics, horiAdvance ), + + FT_FRAME_CHAR( TT_SBit_Metrics, vertBearingX ), + FT_FRAME_CHAR( TT_SBit_Metrics, vertBearingY ), + FT_FRAME_BYTE( TT_SBit_Metrics, vertAdvance ), + FT_FRAME_END + }; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Const_Metrics */ + /* */ + /* */ + /* Loads the metrics for `EBLC' index tables format 2 and 5. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Range_Codes */ + /* */ + /* */ + /* Loads the range codes for `EBLC' index tables format 4 and 5. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* load_offsets :: A flag whether to load the glyph offset table. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Range */ + /* */ + /* */ + /* Loads a given `EBLC' index/range table. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* 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 = ( 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 = TT_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Strikes */ + /* */ + /* */ + /* Loads the table of embedded bitmap sizes for this face. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + /* no FT_FRAME_START */ + FT_FRAME_CHAR( TT_SBit_Line_Metrics, ascender ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, descender ), + FT_FRAME_BYTE( TT_SBit_Line_Metrics, max_width ), + + FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_slope_numerator ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_slope_denominator ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_offset ), + + FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_origin_SB ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_advance_SB ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, max_before_BL ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_after_BL ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, pads[0] ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, pads[1] ), + FT_FRAME_END + }; + + const FT_Frame_Field strike_start_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_ULONG( TT_SBit_Strike, ranges_offset ), + FT_FRAME_SKIP_LONG, + FT_FRAME_ULONG( TT_SBit_Strike, num_ranges ), + FT_FRAME_ULONG( TT_SBit_Strike, color_ref ), + FT_FRAME_END + }; + + const FT_Frame_Field strike_end_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_USHORT( TT_SBit_Strike, start_glyph ), + FT_FRAME_USHORT( TT_SBit_Strike, end_glyph ), + FT_FRAME_BYTE ( TT_SBit_Strike, x_ppem ), + FT_FRAME_BYTE ( TT_SBit_Strike, y_ppem ), + FT_FRAME_BYTE ( TT_SBit_Strike, bit_depth ), + FT_FRAME_CHAR ( TT_SBit_Strike, 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 ) + { + error = 0; + 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 = TT_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 ) + { + (void)READ_Fields( strike_start_fields, strike ); + + (void)READ_Fields( sbit_line_metrics_fields, &strike->hori ); + (void)READ_Fields( sbit_line_metrics_fields, &strike->vert ); + + (void)READ_Fields( strike_end_fields, strike ); + + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_SBit_Strikes */ + /* */ + /* */ + /* Releases the embedded bitmap tables. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Find_SBit_Range */ + /* */ + /* */ + /* Scans a given strike's ranges and return, for a given glyph */ + /* index, the corresponding sbit range, and `EBDT' offset. */ + /* */ + /* */ + /* glyph_index :: The glyph index. */ + /* strike :: The source/current sbit strike. */ + /* */ + /* */ + /* arange :: The sbit range containing the glyph index. */ + /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ + /* */ + /* */ + /* 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 < strike->start_glyph || + glyph_index > 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 >= range->first_glyph && + glyph_index <= range->last_glyph ) + { + FT_UShort delta = 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 ( 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 TT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Find_SBit_Image */ + /* */ + /* */ + /* Checks whether an embedded bitmap (an `sbit') exists for a given */ + /* glyph, at given x and y ppems. */ + /* */ + /* */ + /* face :: The target face object. */ + /* glyph_index :: The glyph index. */ + /* x_ppem :: The horizontal resolution in points per EM. */ + /* y_ppem :: The vertical resolution in points per EM. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. Returns */ + /* TT_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_Int x_ppem, + FT_Int y_ppem, + + TT_SBit_Range** arange, + TT_SBit_Strike** astrike, + FT_ULong* aglyph_offset ) + { + TT_SBit_Strike* strike = face->sbit_strikes; + TT_SBit_Strike* strike_limit = strike + face->num_sbit_strikes; + + + if ( !strike ) + goto Fail; + + for ( ; strike < strike_limit; strike++ ) + { + if ( strike->x_ppem == x_ppem && strike->y_ppem == y_ppem ) + { + FT_Error error; + + + error = Find_SBit_Range( glyph_index, strike, + arange, aglyph_offset ); + if ( error ) + goto Fail; + + *astrike = strike; + + return TT_Err_Ok; + } + } + + Fail: + /* no embedded bitmap for this glyph in face */ + *arange = 0; + *astrike = 0; + *aglyph_offset = 0; + + return TT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Load_SBit_Metrics */ + /* */ + /* */ + /* Gets the big metrics for a given SBit. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* range :: The SBit range containing the glyph. */ + /* */ + /* */ + /* big_metrics :: A big SBit metrics structure for the glyph. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 = TT_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[] = + { + FT_FRAME_START( 5 ), + FT_FRAME_BYTE( TT_SBit_Small_Metrics, height ), + FT_FRAME_BYTE( TT_SBit_Small_Metrics, width ), + FT_FRAME_CHAR( TT_SBit_Small_Metrics, bearingX ), + FT_FRAME_CHAR( TT_SBit_Small_Metrics, bearingY ), + FT_FRAME_BYTE( TT_SBit_Small_Metrics, 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 */ + (void)READ_Fields( sbit_metrics_fields, metrics ); + break; + + case 5: + default: /* constant metrics */ + if ( range->index_format == 2 || range->index_format == 5 ) + *metrics = range->metrics; + else + return TT_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Crop_Bitmap */ + /* */ + /* */ + /* Crops a bitmap to its tightest bounding box, and adjusts its */ + /* metrics. */ + /* */ + /* */ + /* image :: The input glyph slot. */ + /* */ + /* 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 -= count; + metrics->horiBearingY -= count; + 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 -= 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 = cur[0] << 1; + for ( n = 8; n < width; n += 8 ) + { + FT_Byte val; + + + val = cur[1]; + cur[0] = old | ( val >> 7 ); + old = 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 = 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 = TT_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 TT_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 TT_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 TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Image */ + /* */ + /* */ + /* Loads a given glyph sbit image from the font resource. This also */ + /* returns its metrics. */ + /* */ + /* */ + /* 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. */ + /* */ + /* load_flags :: The glyph load flags (the code checks for the flag */ + /* FT_LOAD_CROP_BITMAP */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* map :: The target pixmap. */ + /* */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* */ + /* FreeType error code. 0 means success. Returns an error if no */ + /* glyph sbit exists for the index. */ + /* */ + /* */ + /* The `map.buffer' field is always freed before the glyph is loaded. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_SBit_Image( TT_Face face, + FT_Int x_ppem, + FT_Int y_ppem, + 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, x_ppem, y_ppem, + &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; + FT_Int top; + + + advance = strike->hori.ascender - strike->hori.descender; + top = advance / 10; + + /* some heuristic values */ + + metrics->vertBearingX = -metrics->width / 2; + metrics->vertBearingY = advance / 10; + metrics->vertAdvance = 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/reactos/subsys/win32k/freetype/src/sfnt/ttsbit.h b/reactos/subsys/win32k/freetype/src/sfnt/ttsbit.h new file mode 100644 index 00000000000..e77de538720 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/sfnt/ttsbit.h @@ -0,0 +1,65 @@ +/***************************************************************************/ +/* */ +/* ttsbit.h */ +/* */ +/* TrueType and OpenType embedded bitmap support (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error TT_Load_SBit_Strikes( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void TT_Free_SBit_Strikes( TT_Face face ); + + LOCAL_DEF + FT_Error TT_Load_SBit_Image( TT_Face face, + FT_Int x_ppem, + FT_Int y_ppem, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTSBIT_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/smooth/ftgrays.c b/reactos/subsys/win32k/freetype/src/smooth/ftgrays.c new file mode 100644 index 00000000000..7ed08388503 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/smooth/ftgrays.c @@ -0,0 +1,1969 @@ +/***************************************************************************/ +/* */ +/* ftgrays.c */ +/* */ +/* A new `perfect' anti-aliasing renderer (body). */ +/* */ +/* Copyright 2000 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_grays_raster.grays_raster_new'; an anti-aliased bitmap can be */ + /* generated with a call to `ft_grays_raster.grays_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 /* for memcpy() */ + + + /*************************************************************************/ + /* */ + /* 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 + + +#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_ */ + + +#ifdef FT_FLAT_COMPILE + +#include "ftgrays.h" + +#else + +#include + +#endif + + +#include /* for FT_UNUSED() */ +#include /* for FT_TRACE() and FT_ERROR() */ +#include /* for FT_Outline_Decompose() */ + +#define ErrRaster_Invalid_Mode FT_Err_Cannot_Render_Glyph +#define ErrRaster_Invalid_Outline FT_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 */ + /* */ + typedef int TScan; /* integer scanline/pixel coordinate */ + typedef long TPos; /* sub-pixel coordinate */ + + /* 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; + int 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; + + int area; + int cover; + int invalid; + + TScan ex, ey; + TScan cx, cy; + TPos x, y; + + TScan last_ey; + + FT_Vector bez_stack[32 * 3]; + int lev_stack[32]; + + FT_Outline outline; + FT_Bitmap target; + + 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; + + } TRaster, *PRaster; + + + /*************************************************************************/ + /* */ + /* Initialize the cells table. */ + /* */ + static + void 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 compute_cbox( RAS_ARG_ FT_Outline* 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 + int record_cell( RAS_ARG ) + { + PCell cell; + + + if ( !ras.invalid && ( ras.area | ras.cover ) ) + { + if ( ras.num_cells >= ras.max_cells ) + return 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; + } + + return 0; + } + + + /*************************************************************************/ + /* */ + /* Set the current cell to a new position. */ + /* */ + static + int 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 ) && record_cell( RAS_VAR ) ) + return 1; + + if ( clean ) + { + ras.area = 0; + ras.cover = 0; + } + + ras.invalid = invalid; + ras.ex = ex; + ras.ey = ey; + return 0; + } + + + /*************************************************************************/ + /* */ + /* Start a new contour at a given cell. */ + /* */ + static + void 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; + + (void)set_cell( RAS_VAR_ ex, ey ); + } + + + /*************************************************************************/ + /* */ + /* Render a scanline as one or more cells. */ + /* */ + static + int 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 ) + return set_cell( RAS_VAR_ ex2, ey ); + + /* everything is located in a single cell. That is easy! */ + /* */ + if ( ex1 == ex2 ) + { + delta = y2 - y1; + ras.area += ( fx1 + fx2 ) * delta; + ras.cover += delta; + return 0; + } + + /* 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 += ( fx1 + first ) * delta; + ras.cover += delta; + + ex1 += incr; + if ( set_cell( RAS_VAR_ ex1, ey ) ) + goto Error; + 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 += ONE_PIXEL * delta; + ras.cover += delta; + y1 += delta; + ex1 += incr; + if ( set_cell( RAS_VAR_ ex1, ey ) ) + goto Error; + } + } + + delta = y2 - y1; + ras.area += ( fx2 + ONE_PIXEL - first ) * delta; + ras.cover += delta; + + return 0; + + Error: + return 1; + } + + + /*************************************************************************/ + /* */ + /* Render a given line as a series of scanlines. */ + /* */ + static + int 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 ) + { + if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 ) ) + goto Error; + 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; + if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first ) ) + goto Error; + + ey1 += incr; + if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) ) + goto Error; + + 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; + if ( render_scanline( RAS_VAR_ ey1, + x, ONE_PIXEL - first, x2, first ) ) + goto Error; + x = x2; + ey1 += incr; + if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) ) + goto Error; + } + } + + if ( render_scanline( RAS_VAR_ ey1, + x, ONE_PIXEL - first, to_x, fy2 ) ) + goto Error; + + End: + ras.x = to_x; + ras.y = to_y; + ras.last_ey = SUBPIXELS( ey2 ); + + return 0; + + Error: + return 1; + } + + + static + void 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 + int 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 >>= 1; + level++; + } + + /* a shortcut to speed things up */ + if ( level <= 1 ) + { + /* we compute the mid-point directly in order to avoid */ + /* calling 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; + + return render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ); + } + + 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; + + 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; + + if ( render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ) ) + return 1; + + top--; + arc -= 2; + } + } + return 0; + } + + + static + void 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 + int 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 >>= 1; + db >>= 2; + 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; + + return render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ); + } + + 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; + 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; + + if ( render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ) ) + return 1; + top --; + arc -= 3; + } + } + return 0; + } + + + /* 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 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 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 = 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 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 Move_To( FT_Vector* to, + FT_Raster raster ) + { + TPos x, y; + + + /* record current cell, if any */ + record_cell( (PRaster)raster ); + + /* start to a new position */ + x = UPSCALE( to->x ); + y = UPSCALE( to->y ); + start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) ); + ((PRaster)raster)->x = x; + ((PRaster)raster)->y = y; + return 0; + } + + + static + int Line_To( FT_Vector* to, + FT_Raster raster ) + { + return render_line( (PRaster)raster, + UPSCALE( to->x ), UPSCALE( to->y ) ); + } + + + static + int Conic_To( FT_Vector* control, + FT_Vector* to, + FT_Raster raster ) + { + return render_conic( (PRaster)raster, control, to ); + } + + + static + int Cubic_To( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + FT_Raster raster ) + { + return render_cubic( (PRaster)raster, control1, control2, to ); + } + + + static + void grays_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 + + static + void 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 grays_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 += acount; + return; + } + + if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS ) + { + if ( ras.render_span ) + 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 grays_sweep( RAS_ARG_ FT_Bitmap* target ) + { + TScan x, y, cover, area; + PCell start, cur, limit; + + FT_UNUSED( target ); + + + 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 ) + { + grays_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 ) + grays_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 ) + grays_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. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Decompose */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* Error code. 0 means sucess. */ + /* */ + static + int FT_Outline_Decompose( FT_Outline* outline, + 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; + + int n; /* index of contour in outline */ + int first; /* index of first point in contour */ + int error; + char tag; /* current point's state */ + + int shift = interface->shift; + FT_Pos delta = interface->delta; + + + 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 grays_convert_glyph( RAS_ARG_ FT_Outline* outline ) + { + static + FT_Outline_Funcs interface = + { + (FT_Outline_MoveTo_Func) Move_To, + (FT_Outline_LineTo_Func) Line_To, + (FT_Outline_ConicTo_Func)Conic_To, + (FT_Outline_CubicTo_Func)Cubic_To, + 0, + 0 + }; + + TBand bands[40], *band; + int n, num_bands; + TPos min, max, max_y; + + + /* Set up state in the raster object */ + compute_cbox( RAS_VAR_ outline ); + + /* clip to target bitmap, exit if nothing to do */ + if ( ras.max_ex <= 0 || ras.min_ex >= ras.target.width || + ras.max_ey <= 0 || ras.min_ey >= ras.target.rows ) + return 0; + + if ( ras.min_ex < 0 ) ras.min_ex = 0; + if ( ras.min_ey < 0 ) ras.min_ey = 0; + + if ( ras.max_ex > ras.target.width ) ras.max_ex = ras.target.width; + if ( ras.max_ey > ras.target.rows ) ras.max_ey = ras.target.rows; + + /* simple heuristic used to speed-up the bezier decomposition -- see */ + /* the code in render_conic() and 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 += 2; + + 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; + + error = FT_Outline_Decompose( outline, &interface, &ras ) || + record_cell( RAS_VAR ); + + if ( !error ) + { +#ifdef SHELL_SORT + shell_sort( ras.cells, ras.num_cells ); +#else + quick_sort( ras.cells, ras.num_cells ); +#endif + +#ifdef DEBUG_GRAYS + check_sort( ras.cells, ras.num_cells ); + dump_cells( RAS_VAR ); +#endif + + grays_sweep( RAS_VAR_ &ras.target ); + band--; + continue; + } + + /* 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 grays_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 ( !target_map || !target_map->buffer ) + return -1; + + /* XXX: this version does not support monochrome rendering yet! */ + if ( !(params->flags & ft_raster_flag_aa) ) + return ErrRaster_Invalid_Mode; + + ras.outline = *outline; + ras.target = *target_map; + ras.num_cells = 0; + ras.invalid = 1; + + ras.render_span = (FT_Raster_Span_Func)grays_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 grays_convert_glyph( (PRaster)raster, outline ); + } + + + /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/ + /**** a static object. *****/ + +#ifdef _STANDALONE_ + + static + int grays_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 grays_raster_done( FT_Raster raster ) + { + /* nothing */ + FT_UNUSED( raster ); + } + +#else /* _STANDALONE_ */ + + static + int grays_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 grays_raster_done( FT_Raster raster ) + { + FT_Memory memory = (FT_Memory)((PRaster)raster)->memory; + + + FREE( raster ); + } + +#endif /* _STANDALONE_ */ + + + static + void grays_raster_reset( FT_Raster raster, + const char* pool_base, + long pool_size ) + { + PRaster rast = (PRaster)raster; + + + if ( raster && pool_base && pool_size >= 4096 ) + init_cells( rast, (char*)pool_base, pool_size ); + + rast->band_size = ( pool_size / sizeof ( TCell ) ) / 8; + } + + + FT_Raster_Funcs ft_grays_raster = + { + ft_glyph_format_outline, + + (FT_Raster_New_Func) grays_raster_new, + (FT_Raster_Reset_Func) grays_raster_reset, + (FT_Raster_Set_Mode_Func)0, + (FT_Raster_Render_Func) grays_raster_render, + (FT_Raster_Done_Func) grays_raster_done + }; + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/smooth/ftgrays.h b/reactos/subsys/win32k/freetype/src/smooth/ftgrays.h new file mode 100644 index 00000000000..2423a0e45ef --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/smooth/ftgrays.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ftgrays.h */ +/* */ +/* FreeType smooth renderer declaration */ +/* */ +/* Copyright 1996-2000 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 +#endif + + /*************************************************************************/ + /* */ + /* To make ftgrays.h independent from configuration files we check */ + /* whether FT_EXPORT_DEF 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( FT_Raster_Funcs ) ft_grays_raster; + +#ifdef __cplusplus + } +#endif + +#endif /* FTGRAYS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/smooth/ftsmooth.c b/reactos/subsys/win32k/freetype/src/smooth/ftsmooth.c new file mode 100644 index 00000000000..6f399acf59a --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/smooth/ftsmooth.c @@ -0,0 +1,220 @@ +/***************************************************************************/ +/* */ +/* ftsmooth.c */ +/* */ +/* Anti-aliasing renderer interface (body). */ +/* */ +/* Copyright 2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ftsmooth.h" +#include "ftgrays.h" + +#else + +#include +#include + +#endif + + + /* 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 = FT_Err_Ok; + + + if ( slot->format != render->glyph_format ) + { + error = FT_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 = FT_Err_Invalid_Argument; + goto Exit; + } + + /* check mode */ + if ( mode != ft_render_mode_normal ) + return FT_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, ¶ms ); + 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; + } + + + 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/reactos/subsys/win32k/freetype/src/smooth/ftsmooth.h b/reactos/subsys/win32k/freetype/src/smooth/ftsmooth.h new file mode 100644 index 00000000000..4b8a5334376 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/smooth/ftsmooth.h @@ -0,0 +1,35 @@ +/***************************************************************************/ +/* */ +/* ftsmooth.h */ +/* */ +/* Anti-aliasing renderer interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#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 + +#endif /* FTSMOOTH_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/smooth/module.mk b/reactos/subsys/win32k/freetype/src/smooth/module.mk new file mode 100644 index 00000000000..b93bc4d3ddf --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/smooth/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_smooth_renderer + +add_smooth_renderer: + $(OPEN_DRIVER)ft_smooth_renderer_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)smooth $(ECHO_DRIVER_DESC)anti-aliased bitmap renderer$(ECHO_DRIVER_DONE) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/smooth/rules.mk b/reactos/subsys/win32k/freetype/src/smooth/rules.mk new file mode 100644 index 00000000000..a81d60ae86f --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/smooth/rules.mk @@ -0,0 +1,69 @@ +# +# FreeType 2 renderer module build rules +# + + +# Copyright 1996-2000 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. + + +# smooth driver directory +# +SMOOTH_DIR := $(SRC_)smooth +SMOOTH_DIR_ := $(SMOOTH_DIR)$(SEP) + +# compilation flags for the driver +# +SMOOTH_COMPILE := $(FT_COMPILE) + + +# smooth driver sources (i.e., C files) +# +SMOOTH_DRV_SRC := $(SMOOTH_DIR_)ftgrays.c \ + $(SMOOTH_DIR_)ftsmooth.c + + +# smooth driver headers +# +SMOOTH_DRV_H := $(SMOOTH_DRV_SRC:%c=%h) + + +# smooth driver object(s) +# +# SMOOTH_DRV_OBJ_M is used during `multi' builds. +# SMOOTH_DRV_OBJ_S is used during `single' builds. +# +SMOOTH_DRV_OBJ_M := $(SMOOTH_DRV_SRC:$(SMOOTH_DIR_)%.c=$(OBJ_)%.$O) +SMOOTH_DRV_OBJ_S := $(OBJ_)smooth.$O + +# smooth driver source file for single build +# +SMOOTH_DRV_SRC_S := $(SMOOTH_DIR_)smooth.c + + +# smooth driver - single object +# +$(SMOOTH_DRV_OBJ_S): $(SMOOTH_DRV_SRC_S) $(SMOOTH_DRV_SRC) \ + $(FREETYPE_H) $(SMOOTH_DRV_H) + $(SMOOTH_COMPILE) $T$@ $(SMOOTH_DRV_SRC_S) + + +# smooth driver - multiple objects +# +$(OBJ_)%.$O: $(SMOOTH_DIR_)%.c $(FREETYPE_H) $(SMOOTH_DRV_H) + $(SMOOTH_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(SMOOTH_DRV_OBJ_S) +DRV_OBJS_M += $(SMOOTH_DRV_OBJ_M) + + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/smooth/smooth.c b/reactos/subsys/win32k/freetype/src/smooth/smooth.c new file mode 100644 index 00000000000..41cc4aea528 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/smooth/smooth.c @@ -0,0 +1,35 @@ +/***************************************************************************/ +/* */ +/* smooth.c */ +/* */ +/* FreeType anti-aliasing rasterer module component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ftgrays.c" +#include "ftsmooth.c" + +#else + +#include +#include + +#endif + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/truetype/module.mk b/reactos/subsys/win32k/freetype/src/truetype/module.mk new file mode 100644 index 00000000000..79072bb54ba --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_truetype_driver + +add_truetype_driver: + $(OPEN_DRIVER)tt_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)truetype $(ECHO_DRIVER_DESC)Windows/Mac font files with extension *.ttf or *.ttc$(ECHO_DRIVER_DONE) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/truetype/rules.mk b/reactos/subsys/win32k/freetype/src/truetype/rules.mk new file mode 100644 index 00000000000..9289378cb59 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/rules.mk @@ -0,0 +1,70 @@ +# +# FreeType 2 TrueType driver configuration rules +# + + +# Copyright 1996-2000 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. + + +# TrueType driver directory +# +TT_DIR := $(SRC_)truetype +TT_DIR_ := $(TT_DIR)$(SEP) + + +# compilation flags for the driver +# +TT_COMPILE := $(FT_COMPILE) + + +# TrueType driver sources (i.e., C files) +# +TT_DRV_SRC := $(TT_DIR_)ttobjs.c \ + $(TT_DIR_)ttpload.c \ + $(TT_DIR_)ttgload.c \ + $(TT_DIR_)ttinterp.c \ + $(TT_DIR_)ttdriver.c + +# TrueType driver headers +# +TT_DRV_H := $(TT_DRV_SRC:%.c=%.h) + + +# TrueType driver object(s) +# +# TT_DRV_OBJ_M is used during `multi' builds +# TT_DRV_OBJ_S is used during `single' builds +# +TT_DRV_OBJ_M := $(TT_DRV_SRC:$(TT_DIR_)%.c=$(OBJ_)%.$O) +TT_DRV_OBJ_S := $(OBJ_)truetype.$O + +# TrueType driver source file for single build +# +TT_DRV_SRC_S := $(TT_DIR_)truetype.c + + +# TrueType driver - single object +# +$(TT_DRV_OBJ_S): $(TT_DRV_SRC_S) $(TT_DRV_SRC) $(FREETYPE_H) $(TT_DRV_H) + $(TT_COMPILE) $T$@ $(TT_DRV_SRC_S) + + +# driver - multiple objects +# +$(OBJ_)%.$O: $(TT_DIR_)%.c $(FREETYPE_H) $(TT_DRV_H) + $(TT_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(TT_DRV_OBJ_S) +DRV_OBJS_M += $(TT_DRV_OBJ_M) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/truetype/truetype.c b/reactos/subsys/win32k/freetype/src/truetype/truetype.c new file mode 100644 index 00000000000..55ba0c9d41c --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/truetype.c @@ -0,0 +1,47 @@ +/***************************************************************************/ +/* */ +/* truetype.c */ +/* */ +/* FreeType TrueType driver component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#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" /* bytecode interpreter */ +#endif + +#else /* FT_FLAT_COMPILE */ + +#include /* driver interface */ +#include /* tables loader */ +#include /* glyph loader */ +#include /* object manager */ + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include /* bytecode interpreter */ +#endif + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/truetype/ttdriver.c b/reactos/subsys/win32k/freetype/src/truetype/ttdriver.c new file mode 100644 index 00000000000..0b3cb480c59 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/ttdriver.c @@ -0,0 +1,511 @@ +/***************************************************************************/ +/* */ +/* ttdriver.c */ +/* */ +/* TrueType font driver implementation (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttdriver.h" +#include "ttgload.h" + +#else + +#include +#include + +#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_ttdriver + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F A C E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#undef PAIR_TAG +#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ + (FT_ULong)right ) + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Char_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in fractional points. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* 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; + + return TT_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Pixel_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in integer pixels. */ + /* */ + /* */ + /* pixel_width :: The character width expressed in integer pixels. */ + /* */ + /* pixel_height :: The character height expressed in integer pixels. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* 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; + + return TT_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Load_Glyph */ + /* */ + /* */ + /* A driver method used to load a glyph within a given glyph slot. */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* 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_Glyph_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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* 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. */ + + 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 + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverInterface */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ + EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void ) + { + return &tt_driver_class; + } + + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/truetype/ttdriver.h b/reactos/subsys/win32k/freetype/src/truetype/ttdriver.h new file mode 100644 index 00000000000..9867fbc3095 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/ttdriver.h @@ -0,0 +1,31 @@ +/***************************************************************************/ +/* */ +/* ttdriver.h */ +/* */ +/* High-level TrueType driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + + FT_EXPORT_VAR( const FT_Driver_Class ) tt_driver_class; + + +#endif /* TTDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/truetype/ttgload.c b/reactos/subsys/win32k/freetype/src/truetype/ttgload.c new file mode 100644 index 00000000000..e9b87fa67ed --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/ttgload.c @@ -0,0 +1,1477 @@ +/***************************************************************************/ +/* */ +/* ttgload.c */ +/* */ +/* TrueType Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttgload.h" + +#else + +#include + +#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_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 + + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_Metrics */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* header :: A pointer to either the horizontal or vertical metrics */ + /* structure. */ + /* */ + /* index :: The glyph index. */ + /* */ + /* */ + /* bearing :: The bearing, either left side or top side. */ + /* */ + /* advance :: The advance width resp. advance height. */ + /* */ + /* */ + /* This function will much probably move to another component in the */ + /* near future, but I haven't decided which yet. */ + /* */ + LOCAL_FUNC + 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 < 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 = load->outline.n_points - start_point; + zone->n_contours = 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. */ + /* */ + /*************************************************************************/ + + static + 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; + + + /* the following line sets the `error' variable through macros! */ + (void)( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) ); + + FT_TRACE5(( "Glyph %ld\n", glyph_index )); + return error; + } + + + static + void TT_Forget_Glyph_Frame( TT_Loader* loader ) + { + FT_Stream stream = loader->stream; + + + FORGET_Frame(); + } + + + static + 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 FT_Err_Ok; + } + + + static + 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_Ins; + goto Fail; + } + + if ( stream->cursor + n_ins > stream->limit ) + { + FT_TRACE0(( "ERROR: Instruction count mismatch!\n" )); + error = TT_Err_Too_Many_Ins; + 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 = n_points; + outline->n_contours = n_contours; + + Fail: + return error; + } + + + static + 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 = FILE_Pos() + stream->cursor - stream->limit; + } +#endif + + Fail: + return error; + } + + + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Process_Simple_Glyph */ + /* */ + /* */ + /* 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 = FT_Err_Ok; + + + 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 = FT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* load_truetype_glyph */ + /* */ + /* */ + /* 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 ) + { + FT_Stream stream = loader->stream; + FT_Error error; + TT_Face face = (TT_Face)loader->face; + FT_ULong offset; + FT_Int contours_count; + FT_UInt index, num_points, num_contours, count; + FT_Fixed x_scale, y_scale; + FT_ULong ins_offset; + 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_contours = 0; + num_points = 0; + ins_offset = 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; + } + + 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 = FT_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; + + 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; + } + } + } + + translate_array( num_new_points, loader->zone.cur, x, y ); + cur_to_org( num_new_points, &loader->zone ); + } + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + + /* 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_Ins; + } + + /* 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 = 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 x_scale, y_scale; + TT_GlyphSlot glyph = loader->glyph; + TT_Size size = (TT_Size)loader->size; + + + x_scale = 0x10000L; + y_scale = 0x10000L; + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + x_scale = size->root.metrics.x_scale; + 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->loader, loader->gloader ); + glyph->outline = glyph->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->advance; + + + /* 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 original vertical top 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 = face->os2.sTypoLineGap / 2; + advance_height = (FT_UShort)( face->os2.sTypoAscender - + face->os2.sTypoDescender + + face->os2.sTypoLineGap ); + } + else + { + top_bearing = 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, y_scale ); + top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale ) + - bbox.yMax; + advance = FT_MulFix( advance_height, y_scale ); + } + else + { + Top = top_bearing; + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Glyph */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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_Memory memory; + FT_Error error; + TT_Loader loader; + + + face = (TT_Face)glyph->face; + sfnt = (SFNT_Interface*)face->sfnt; + stream = face->root.stream; + memory = face->root.memory; + 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 */ + if ( size && + ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && + sfnt->load_sbits ) + { + TT_SBit_Metrics metrics; + + + error = sfnt->load_sbit_image( face, + size->root.metrics.x_ppem, + size->root.metrics.y_ppem, + 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/reactos/subsys/win32k/freetype/src/truetype/ttgload.h b/reactos/subsys/win32k/freetype/src/truetype/ttgload.h new file mode 100644 index 00000000000..2f3e96b7b04 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/ttgload.h @@ -0,0 +1,69 @@ +/***************************************************************************/ +/* */ +/* ttgload.h */ +/* */ +/* TrueType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ttobjs.h" + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include "ttinterp.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + void TT_Get_Metrics( TT_HoriHeader* header, + FT_UInt index, + FT_Short* bearing, + FT_UShort* advance ); + + LOCAL_DEF + void TT_Init_Glyph_Loading( TT_Face face ); + + LOCAL_DEF + FT_Error TT_Load_Glyph( TT_Size size, + TT_GlyphSlot glyph, + FT_UShort glyph_index, + FT_UInt load_flags ); + +#ifdef __cplusplus + } +#endif + +#endif /* TTGLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/truetype/ttinterp.c b/reactos/subsys/win32k/freetype/src/truetype/ttinterp.c new file mode 100644 index 00000000000..9dc0c190a70 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/ttinterp.c @@ -0,0 +1,7544 @@ +/***************************************************************************/ +/* */ +/* ttinterp.c */ +/* */ +/* TrueType bytecode interpreter (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttinterp.h" + +#else + +#include + +#endif + + +#include + + +#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 CALC_Length() \ + Calc_Length( 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 */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Goto_CodeRange */ + /* */ + /* */ + /* Switches to a new code range (updates the code related elements in */ + /* `exec', and `IP'). */ + /* */ + /* */ + /* range :: The new execution code range. */ + /* */ + /* IP :: The new IP in the new code range. */ + /* */ + /* */ + /* exec :: The target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Set_CodeRange */ + /* */ + /* */ + /* Sets a code range. */ + /* */ + /* */ + /* range :: The code range index. */ + /* */ + /* base :: The new code base. */ + /* */ + /* length :: The range size in bytes. */ + /* */ + /* */ + /* exec :: The target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Clear_CodeRange */ + /* */ + /* */ + /* Clears a code range. */ + /* */ + /* */ + /* range :: The code range index. */ + /* */ + /* */ + /* exec :: The target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Does not set the Error variable. */ + /* */ + LOCAL_FUNC + 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 */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Destroy_Context */ + /* */ + /* */ + /* Destroys a given context. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Init_Context */ + /* */ + /* */ + /* Initializes a context object. */ + /* */ + /* */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* face :: A handle to the source TrueType face object. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Update_Max */ + /* */ + /* */ + /* Checks the size of a buffer and reallocates it if necessary. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* size :: The address of the buffer's current size expressed */ + /* in elements. */ + /* */ + /* buff :: The address of the buffer base pointer. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Context */ + /* */ + /* */ + /* Prepare an execution context for glyph hinting. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* size :: A handle to the source size object. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Save_Context */ + /* */ + /* */ + /* Saves the code ranges in a `size' object. */ + /* */ + /* */ + /* exec :: A handle to the source execution context. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Run_Context */ + /* */ + /* */ + /* Executes one or more instructions in the execution context. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* TrueTyoe error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + 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 + }; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_New_Context */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* A handle to the execution context. Initialized for `face'. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Context */ + /* */ + /* */ + /* Discards an execution context. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + FT_Error TT_Done_Context( TT_ExecContext exec ) + { + /* Nothing at all for now */ + FT_UNUSED( exec ); + + return TT_Err_Ok; + } + + +#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 ); + } + +#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 + + + /*************************************************************************/ + /* */ + /* */ + /* Current_Ratio */ + /* */ + /* */ + /* Returns the current aspect ratio scaling factor depending on the */ + /* projection vector's state and device resolutions. */ + /* */ + /* */ + /* 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; + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + 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 ); + +#else + + x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x8000 ); + y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x8000 ); + CUR.tt_metrics.ratio = FT_Sqrt32( x * x + y * y ) << 1; + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + } + + 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). */ + /* */ + /*************************************************************************/ + + + static + FT_F26Dot6 Read_CVT( EXEC_OP_ FT_ULong index ) + { + return CUR.cvt[index]; + } + + + static + FT_F26Dot6 Read_CVT_Stretched( EXEC_OP_ FT_ULong index ) + { + return TT_MULFIX( CUR.cvt[index], CURRENT_Ratio() ); + } + + + static + void Write_CVT( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] = value; + } + + + static + void Write_CVT_Stretched( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] = FT_DivFix( value, CURRENT_Ratio() ); + } + + + static + void Move_CVT( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] += value; + } + + + static + void Move_CVT_Stretched( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] += FT_DivFix( value, CURRENT_Ratio() ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* GetShortIns */ + /* */ + /* */ + /* Returns a short integer taken from the instruction stream at */ + /* address IP. */ + /* */ + /* */ + /* Short read at code[IP]. */ + /* */ + /* */ + /* 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] ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Ins_Goto_CodeRange */ + /* */ + /* */ + /* Goes to a certain code range in the instruction stream. */ + /* */ + /* */ + /* aRange :: The index of the code range. */ + /* */ + /* aIP :: The new IP address in the code range. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Direct_Move */ + /* */ + /* */ + /* Moves a point by a given distance along the freedom vector. The */ + /* point will be `touched'. */ + /* */ + /* */ + /* point :: The index of the point to move. */ + /* */ + /* distance :: The distance to apply. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_None */ + /* */ + /* */ + /* Does not round, but adds engine compensation. */ + /* */ + /* */ + /* distance :: The distance (not) to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* The compensated distance. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_To_Grid */ + /* */ + /* */ + /* Rounds value to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_To_Half_Grid */ + /* */ + /* */ + /* Rounds value to half grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Down_To_Grid */ + /* */ + /* */ + /* Rounds value down to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Up_To_Grid */ + /* */ + /* */ + /* Rounds value up to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_To_Double_Grid */ + /* */ + /* */ + /* Rounds value to double grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Super */ + /* */ + /* */ + /* Super-rounds value to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Super_45 */ + /* */ + /* */ + /* Super-rounds value to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Compute_Round */ + /* */ + /* */ + /* Sets the rounding mode. */ + /* */ + /* */ + /* 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* SetSuperRound */ + /* */ + /* */ + /* Sets Super Round parameters. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Project */ + /* */ + /* */ + /* Computes the projection of vector given by (v2-v1) along the */ + /* current projection vector. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Dual_Project */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* current dual vector. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Free_Project */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* current freedom vector. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Project_x */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* horizontal axis. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Project_y */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* vertical axis. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Compute_Funcs */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Normalize */ + /* */ + /* */ + /* Norms a vector. */ + /* */ + /* */ + /* Vx :: The horizontal input vector coordinate. */ + /* Vy :: The vertical input vector coordinate. */ + /* */ + /* */ + /* R :: The normed unit vector. */ + /* */ + /* */ + /* Returns FAILURE if a vector parameter is zero. */ + /* */ + /* */ + /* 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_F26Dot6 u, v, d; + FT_Int shift; + FT_ULong H, L, L2, hi, lo, med; + + + u = ABS( Vx ); + v = ABS( Vy ); + + if ( u < v ) + { + d = u; + u = v; + v = d; + } + + R->x = 0; + R->y = 0; + + /* check that we are not trying to normalise zero! */ + if ( u == 0 ) + return SUCCESS; + + /* 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 */ + if ( H == 0 ) + { + shift = 0; + while ( ( L & 0xC0000000L ) == 0 ) + { + L <<= 2; + shift++; + } + + d = FT_Sqrt32( L ); + R->x = (FT_F2Dot14)TT_MULDIV( Vx << shift, 0x4000, d ); + R->y = (FT_F2Dot14)TT_MULDIV( Vy << shift, 0x4000, d ); + } + /* if the value is greater than 64-bits */ + else + { + shift = 0; + while ( H ) + { + L = ( L >> 2 ) | ( H << 30 ); + H >>= 2; + shift++; + } + + d = FT_Sqrt32( L ); + R->x = (FT_F2Dot14)TT_MULDIV( Vx >> shift, 0x4000, d ); + R->y = (FT_F2Dot14)TT_MULDIV( Vy >> shift, 0x4000, d ); + } + + { + FT_ULong x, y, w; + FT_Int sx, sy; + + + sx = R->x >= 0 ? 1 : -1; + sy = R->y >= 0 ? 1 : -1; + x = (FT_ULong)sx * R->x; + y = (FT_ULong)sy * R->y; + + w = x * x + y * y; + + /* we now want to adjust (x,y) in order to have sqrt(w) == 0x4000 */ + /* which means 0x1000000 <= w < 0x1004000 */ + while ( w <= 0x10000000L ) + { + /* increment the smallest coordinate */ + if ( x < y ) + x++; + else + y++; + + w = x * x + y * y; + } + + while ( w >= 0x10040000L ) + { + /* decrement the smallest coordinate */ + if ( x < y ) + x--; + else + y--; + + w = x * x + y * y; + } + + R->x = sx * x; + R->y = sy * y; + } + + 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 = ( nIfs == 1 ); + break; + + case 0x59: /* EIF */ + nIfs--; + Out = ( 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_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 = 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 = 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 = 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 ( 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. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_RunIns */ + /* */ + /* */ + /* Executes one or more instruction in the execution context. This */ + /* is the main function of the TrueType opcode interpreter. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 = AA ^ (FT_Short)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 == 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/reactos/subsys/win32k/freetype/src/truetype/ttinterp.h b/reactos/subsys/win32k/freetype/src/truetype/ttinterp.h new file mode 100644 index 00000000000..6e92699cdca --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/ttinterp.h @@ -0,0 +1,278 @@ +/***************************************************************************/ +/* */ +/* ttinterp.h */ +/* */ +/* TrueType bytecode interpreter (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ttobjs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + +#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_UInt 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; + + + LOCAL_DEF + FT_Error TT_Goto_CodeRange( TT_ExecContext exec, + FT_Int range, + FT_Long IP ); + + LOCAL_DEF + FT_Error TT_Set_CodeRange( TT_ExecContext exec, + FT_Int range, + void* base, + FT_Long length ); + + LOCAL_DEF + FT_Error TT_Clear_CodeRange( TT_ExecContext exec, + FT_Int range ); + + FT_EXPORT_DEF( TT_ExecContext ) TT_New_Context( TT_Face face ); + + LOCAL_DEF + FT_Error TT_Done_Context( TT_ExecContext exec ); + + LOCAL_DEF + FT_Error TT_Destroy_Context( TT_ExecContext exec, + FT_Memory memory ); + + LOCAL_DEF + FT_Error TT_Load_Context( TT_ExecContext exec, + TT_Face face, + TT_Size size ); + + LOCAL_DEF + FT_Error TT_Save_Context( TT_ExecContext exec, + TT_Size ins ); + + LOCAL_DEF + FT_Error TT_Run_Context( TT_ExecContext exec, + FT_Bool debug ); + + FT_EXPORT_DEF( FT_Error ) TT_RunIns( TT_ExecContext exec ); + + +#ifdef __cplusplus + } +#endif + +#endif /* TTINTERP_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/truetype/ttobjs.c b/reactos/subsys/win32k/freetype/src/truetype/ttobjs.c new file mode 100644 index 00000000000..2ba715dc114 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/ttobjs.c @@ -0,0 +1,734 @@ +/***************************************************************************/ +/* */ +/* ttobjs.c */ +/* */ +/* Objects manager (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttgload.h" +#include "ttpload.h" + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include "ttinterp.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#include + + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* GLYPH ZONE FUNCTIONS */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_GlyphZone */ + /* */ + /* */ + /* Deallocates a glyph zone. */ + /* */ + /* */ + /* zone :: A pointer to the target glyph zone. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_New_GlyphZone */ + /* */ + /* */ + /* Allocates a new glyph zone. */ + /* */ + /* */ + /* memory :: A handle to the current memory object. */ + /* */ + /* maxPoints :: The capacity of glyph zone in points. */ + /* */ + /* maxContours :: The capacity of glyph zone in contours. */ + /* */ + /* */ + /* zone :: A pointer to the target glyph zone record. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Face */ + /* */ + /* */ + /* Initializes a given TrueType face object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + 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; + + 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 = FT_Err_Unknown_File_Format; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Face */ + /* */ + /* */ + /* Finalizes a given face object. */ + /* */ + /* */ + /* face :: A pointer to the face object to destroy. */ + /* */ + 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 */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Size */ + /* */ + /* */ + /* Initializes a new TrueType size object. */ + /* */ + /* */ + /* size :: A handle to the size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + 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: + +#endif + + TT_Done_Size( size ); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Size */ + /* */ + /* */ + /* The TrueType size object finalizer. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Reset_Size */ + /* */ + /* */ + /* Resets a TrueType size when resolutions and character dimensions */ + /* have been changed. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_DEF + FT_Error TT_Reset_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_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 < 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 < 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Driver */ + /* */ + /* */ + /* Initializes a given TrueType driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Driver */ + /* */ + /* */ + /* Finalizes a given TrueType driver. */ + /* */ + /* */ + /* driver :: A handle to the target TrueType driver. */ + /* */ + LOCAL_FUNC + 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; + } + +#endif + + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/truetype/ttobjs.h b/reactos/subsys/win32k/freetype/src/truetype/ttobjs.h new file mode 100644 index 00000000000..3e55de3cb17 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/ttobjs.h @@ -0,0 +1,412 @@ +/***************************************************************************/ +/* */ +/* ttobjs.h */ +/* */ +/* Objects manager (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Driver */ + /* */ + /* */ + /* A handle to a TrueType driver object. */ + /* */ + typedef struct TT_DriverRec_* TT_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Instance */ + /* */ + /* */ + /* A handle to a TrueType size object. */ + /* */ + typedef struct TT_SizeRec_* TT_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GlyphSlot */ + /* */ + /* */ + /* A handle to a TrueType glyph slot object. */ + /* */ + /* */ + /* This is a direct typedef of FT_GlyphSlot, as there is nothing */ + /* specific about the TrueType glyph slot. */ + /* */ + typedef FT_GlyphSlot TT_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GraphicsState */ + /* */ + /* */ + /* 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; + + + LOCAL_DEF void TT_Done_GlyphZone( TT_GlyphZone* zone ); + + LOCAL_DEF FT_Error TT_New_GlyphZone( FT_Memory memory, + FT_UShort maxPoints, + FT_Short maxContours, + TT_GlyphZone* zone ); + + + /*************************************************************************/ + /* */ + /* 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_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 */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void TT_Done_Face( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* Size functions */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Size( TT_Size size ); + + LOCAL_DEF + void TT_Done_Size( TT_Size size ); + + LOCAL_DEF + FT_Error TT_Reset_Size( TT_Size size ); + + + /*************************************************************************/ + /* */ + /* Driver functions */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Driver( TT_Driver driver ); + + LOCAL_DEF + void TT_Done_Driver( TT_Driver driver ); + + +#ifdef __cplusplus + } +#endif + +#endif /* TTOBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/truetype/ttpload.c b/reactos/subsys/win32k/freetype/src/truetype/ttpload.c new file mode 100644 index 00000000000..d82dd45bea6 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/ttpload.c @@ -0,0 +1,273 @@ +/***************************************************************************/ +/* */ +/* ttpload.h */ +/* */ +/* TrueType glyph data/program tables loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + +#ifdef FT_FLAT_COMPILE +#include "ttpload.h" +#else +#include +#endif + +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Locations */ + /* */ + /* */ + /* Loads the locations table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_CVT */ + /* */ + /* */ + /* Loads the control value table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Progams */ + /* */ + /* */ + /* Loads the font program and the cvt program. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/src/truetype/ttpload.h b/reactos/subsys/win32k/freetype/src/truetype/ttpload.h new file mode 100644 index 00000000000..77802a6424a --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/truetype/ttpload.h @@ -0,0 +1,51 @@ +/***************************************************************************/ +/* */ +/* ttpload.h */ +/* */ +/* TrueType glyph data/program tables loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error TT_Load_Locations( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + FT_Error TT_Load_CVT( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + FT_Error TT_Load_Programs( TT_Face face, + FT_Stream stream ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTPLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/module.mk0 b/reactos/subsys/win32k/freetype/src/type1/module.mk0 new file mode 100644 index 00000000000..af99eae25f0 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/module.mk0 @@ -0,0 +1,6 @@ +make_module_list: add_type1_driver + +add_type1_driver: + $(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)type1 $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE) + diff --git a/reactos/subsys/win32k/freetype/src/type1/rules.mk0 b/reactos/subsys/win32k/freetype/src/type1/rules.mk0 new file mode 100644 index 00000000000..b544446ae6f --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/rules.mk0 @@ -0,0 +1,74 @@ +# +# FreeType 2 Type 1 driver configuration rules +# + + +# Copyright 1996-2000 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. + + +# Type1 driver directory +# +T1_DIR := $(SRC_)type1 +T1_DIR_ := $(T1_DIR)$(SEP) + + +# compilation flags for the driver +# +T1_COMPILE := $(FT_COMPILE) + + +# Type1 driver sources (i.e., C files) +# +T1_DRV_SRC := $(T1_DIR_)t1objs.c \ + $(T1_DIR_)t1load.c \ + $(T1_DIR_)t1parse.c \ + $(T1_DIR_)t1tokens.c \ + $(T1_DIR_)t1driver.c \ + $(T1_DIR_)t1hinter.c \ + $(T1_DIR_)t1afm.c \ + $(T1_DIR_)t1gload.c + +# Type1 driver headers +# +T1_DRV_H := $(T1_DRV_SRC:%.c=%.h) + + +# Type1 driver object(s) +# +# T1_DRV_OBJ_M is used during `multi' builds +# T1_DRV_OBJ_S is used during `single' builds +# +T1_DRV_OBJ_M := $(T1_DRV_SRC:$(T1_DIR_)%.c=$(OBJ_)%.$O) +T1_DRV_OBJ_S := $(OBJ_)type1.$O + +# Type1 driver source file for single build +# +T1_DRV_SRC_S := $(T1_DIR_)type1.c + + +# Type1 driver - single object +# +$(T1_DRV_OBJ_S): $(T1_DRV_SRC_S) $(T1_DRV_SRC) $(FREETYPE_H) $(T1_DRV_H) + $(T1_COMPILE) $T$@ $(T1_DRV_SRC_S) + + +# Type1 driver - multiple objects +# +$(OBJ_)%.$O: $(T1_DIR_)%.c $(FREETYPE_H) $(T1_DRV_H) + $(T1_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(T1_DRV_OBJ_S) +DRV_OBJS_M += $(T1_DRV_OBJ_M) + + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/type1/t1afm.c b/reactos/subsys/win32k/freetype/src/type1/t1afm.c new file mode 100644 index 00000000000..a6ac1b98a69 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1afm.c @@ -0,0 +1,293 @@ +/***************************************************************************/ +/* */ +/* t1afm.c */ +/* */ +/* AFM support for Type 1 fonts (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t1afm.h" + +#else + +#include + +#endif + + +#include +#include + +#include /* for qsort() */ +#include /* for strcmp() */ +#include /* 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 + + + LOCAL_FUNC + void T1_Done_AFM( FT_Memory memory, + T1_AFM* afm ) + { + FREE( afm->kern_pairs ); + afm->num_pairs = 0; + } + + +#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 = 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 */ + static + 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 */ + LOCAL_FUNC + 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; + + 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 */ + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/src/type1/t1afm.h b/reactos/subsys/win32k/freetype/src/type1/t1afm.h new file mode 100644 index 00000000000..709154ec7b7 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1afm.h @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* t1afm.h */ +/* */ +/* AFM support for Type 1 fonts (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + 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; + + + LOCAL_DEF + FT_Error T1_Read_AFM( FT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void T1_Done_AFM( FT_Memory memory, + T1_AFM* afm ); + + LOCAL_DEF + void T1_Get_Kerning( T1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T1AFM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1driver.c b/reactos/subsys/win32k/freetype/src/type1/t1driver.c new file mode 100644 index 00000000000..49b5a563749 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1driver.c @@ -0,0 +1,381 @@ +/***************************************************************************/ +/* */ +/* t1driver.c */ +/* */ +/* Type 1 driver interface (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t1driver.h" +#include "t1gload.h" +#include "t1afm.h" + +#else + +#include +#include +#include + +#endif + + +#include +#include +#include + +#include /* 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 + + +#ifndef T1_CONFIG_OPTION_NO_AFM + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 */ + + + static + FT_Error get_t1_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 = strlen( gname ); + + + if ( len >= buffer_max ) + len = buffer_max - 1; + + MEM_Copy( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return T1_Err_Ok; + } + + + static + FT_Module_Interface T1_Get_Interface( FT_Module module, + const char* interface ) + { + FT_UNUSED( module ); + + if ( strcmp( interface, "glyph_name" ) == 0 ) + return (FT_Module_Interface)get_t1_glyph_name; + + return 0; + } + + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Char_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in fractional points. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Set_Char_Sizes( T1_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_UNUSED( char_width ); + FT_UNUSED( char_height ); + FT_UNUSED( horz_resolution ); + FT_UNUSED( vert_resolution ); + + size->valid = FALSE; + + return T1_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Pixel_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in integer pixels. */ + /* */ + /* */ + /* pixel_width :: The character width expressed in integer pixels. */ + /* */ + /* pixel_height :: The character height expressed in integer pixels. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Set_Pixel_Sizes( T1_Size size, + FT_Int pixel_width, + FT_Int pixel_height ) + { + FT_UNUSED( pixel_width ); + FT_UNUSED( pixel_height ); + + size->valid = FALSE; + + return T1_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* 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; + } + + + + const FT_Driver_Class t1_driver_class = + { + { + ft_module_font_driver | ft_module_driver_scalable, + sizeof( FT_DriverRec ), + + "type1", /* driver name */ + 0x10000L, /* driver version 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or above */ + + 0, /* module specific interface */ + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) T1_Get_Interface + }, + + sizeof( T1_FaceRec ), + sizeof( T1_SizeRec ), + sizeof( T1_GlyphSlotRec ), + + (FTDriver_initFace) T1_Init_Face, + (FTDriver_doneFace) T1_Done_Face, + (FTDriver_initSize) T1_Init_Size, + (FTDriver_doneSize) T1_Done_Size, + (FTDriver_initGlyphSlot)T1_Init_GlyphSlot, + (FTDriver_doneGlyphSlot)T1_Done_GlyphSlot, + + (FTDriver_setCharSizes) Set_Char_Sizes, + (FTDriver_setPixelSizes)Set_Pixel_Sizes, + (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 + + EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void ) + { + return &t1_driver_class; + } + +#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1driver.h b/reactos/subsys/win32k/freetype/src/type1/t1driver.h new file mode 100644 index 00000000000..5d615b5bafa --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1driver.h @@ -0,0 +1,30 @@ +/***************************************************************************/ +/* */ +/* t1driver.h */ +/* */ +/* High-level Type 1 driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + FT_EXPORT_VAR( const FT_Driver_Class ) t1_driver_class; + + +#endif /* T1DRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1gload.c b/reactos/subsys/win32k/freetype/src/type1/t1gload.c new file mode 100644 index 00000000000..37cfc8c5d76 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1gload.c @@ -0,0 +1,1823 @@ +/***************************************************************************/ +/* */ +/* t1gload.c */ +/* */ +/* Type 1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t1gload.h" + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include "t1hinter.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#include +#include +#include + +#include /* 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 + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + void T1_Reset_Builder( T1_Builder* builder, + FT_Bool reset_base ) + { + 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->pass = 0; + builder->hint_point = 0; + + if ( builder->loader ) + { + if ( reset_base ) + FT_GlyphLoader_Rewind( builder->loader ); + + FT_GlyphLoader_Prepare( builder->loader ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + /* funcs :: Glyph builder functions (or `methods'). */ + /* */ + LOCAL_FUNC + void T1_Init_Builder( T1_Builder* builder, + T1_Face face, + T1_Size size, + T1_GlyphSlot glyph, + const T1_Builder_Funcs* funcs ) + { + builder->funcs = *funcs; + builder->path_begun = 0; + builder->load_points = 1; + + builder->face = face; + builder->size = size; + builder->glyph = glyph; + builder->memory = face->root.memory; + + if ( glyph ) + { + FT_GlyphLoader* loader = FT_SLOT( glyph )->loader; + + + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; + } + + if ( size ) + { + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.metrics.y_scale; + } + + T1_Reset_Builder( builder, 1 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Builder */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + LOCAL_FUNC + void T1_Done_Builder( T1_Builder* builder ) + { + T1_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* funcs :: The hinting functions interface. */ + /* */ + LOCAL_FUNC + void T1_Init_Decoder( T1_Decoder* decoder, + const T1_Hinter_Funcs* funcs ) + { + decoder->hinter = *funcs; /* copy hinter interface */ + decoder->top = 0; + decoder->zone = 0; + + decoder->flex_state = 0; + decoder->num_flex_vectors = 0; + + /* Clear loader */ + MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* lookup_glyph_by_stdcharcode */ + /* */ + /* */ + /* Looks up a given glyph by its StandardEncoding charcode. Used */ + /* to implement the SEAC Type 1 operator. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + static + FT_Int lookup_glyph_by_stdcharcode( T1_Face face, + FT_Int charcode ) + { + FT_Int n; + const FT_String* glyph_name; + PSNames_Interface* psnames = (PSNames_Interface*)face->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 < face->type1.num_glyphs; n++ ) + { + FT_String* name = (FT_String*)face->type1.glyph_names[n]; + + + if ( name && strcmp( name, glyph_name ) == 0 ) + return n; + } + + return -1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_seac */ + /* */ + /* */ + /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + T1_Face face = decoder->builder.face; + T1_Font* type1 = &face->type1; + + + bchar_index = lookup_glyph_by_stdcharcode( face, bchar ); + achar_index = lookup_glyph_by_stdcharcode( face, achar ); + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return T1_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->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->current.subglyphs; + glyph->format = ft_glyph_format_composite; + + loader->current.num_subglyphs = 2; + goto Exit; + } + + /* First load `bchar' in builder */ + /* now load the unscaled outline */ + + if ( decoder->builder.loader ) + FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ + + error = T1_Parse_CharStrings( decoder, + type1->charstrings [bchar_index], + type1->charstrings_len[bchar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + 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_Parse_CharStrings( decoder, + type1->charstrings [achar_index], + type1->charstrings_len[achar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + return error; + + /* 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 = base->n_points - n_base_points; + dummy.points = base->points + n_base_points; + + FT_Outline_Translate( &dummy, adx - asb, ady ); + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_flex */ + /* */ + /* */ + /* Implements the `flex' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* decoder :: The current Type 1 decoder. */ + /* threshold :: The threshold. */ + /* end_x :: The horizontal position of the final flex point. */ + /* end_y :: The vertical position of the final flex point. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error t1operator_flex( T1_Decoder* decoder, + FT_Pos threshold, + FT_Pos end_x, + FT_Pos end_y ) + { + FT_Vector vec; + FT_Vector* flex = decoder->flex_vectors; + FT_Int n; + + FT_UNUSED( threshold ); + FT_UNUSED( end_x ); + FT_UNUSED( end_y ); + + + /* we don't even try to test the threshold in the non-hinting */ + /* builder, even if the flex operator is said to be a path */ + /* construction statement in the specification. This is better */ + /* left to the hinter. */ + + flex = decoder->flex_vectors; + vec = *flex++; + + for ( n = 0; n < 6; n++ ) + { + flex->x += vec.x; + flex->y += vec.y; + + vec = *flex++; + } + + flex = decoder->flex_vectors; + + return decoder->builder.funcs.rcurve_to( &decoder->builder, + flex[0].x, flex[0].y, + flex[1].x, flex[1].y, + flex[2].x, flex[2].y ) || + + decoder->builder.funcs.rcurve_to( &decoder->builder, + flex[3].x, flex[3].y, + flex[4].x, flex[4].y, + flex[5].x, flex[5].y ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given Type 1 charstrings program. */ + /* */ + /* */ + /* 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. */ + /* */ + /* num_subrs :: The number of sub-routines. */ + /* */ + /* subrs_base :: An array of sub-routines addresses. */ + /* */ + /* subrs_len :: An array of sub-routines lengths. */ + /* */ + /* */ + /* Free error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Parse_CharStrings( T1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ) + { + FT_Error error; + T1_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + T1_Builder* builder = &decoder->builder; + T1_Builder_Funcs* builds = &builder->funcs; + T1_Hinter_Funcs* hints = &decoder->hinter; + + static + const FT_Int 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 */ + }; + + + /* 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 = T1_Err_Ok; + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Int* top = decoder->top; + T1_Operator op = op_none; + FT_Long value = 0; + + + /* Start with the decompression of 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_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_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_Parse_CharStrings: unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = ( (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_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_Parse_CharStrings: invalid byte (%d)\n", + ip[-1] )); + goto Syntax_Error; + } + } + + /* push value if necessary */ + if ( op == op_none ) + { + if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) + { + FT_ERROR(( "T1_Parse_CharStrings: stack overflow!\n" )); + goto Syntax_Error; + } + + *top++ = value; + decoder->top = top; + } + + else if ( op == op_callothersubr ) /* check arguments differently */ + { + 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; + decoder->flex_vectors[0].x = 0; + decoder->flex_vectors[0].y = 0; + break; + + case 2: /* add flex vector */ + { + FT_Int index; + FT_Vector* flex; + + + if ( top[0] != 0 ) + goto Unexpected_OtherSubr; + + top -= 2; + if ( top < decoder->stack ) + goto Stack_Underflow; + + index = decoder->num_flex_vectors++; + if ( index >= 7 ) + { + FT_ERROR(( "T1_Parse_CharStrings: too many flex vectors!\n" )); + goto Syntax_Error; + } + + flex = decoder->flex_vectors + index; + flex->x += top[0]; + flex->y += top[1]; + } + break; + + case 0: /* end flex feature */ + if ( decoder->flex_state == 0 || + decoder->num_flex_vectors != 7 ) + { + FT_ERROR(( "T1_Parse_CharStrings: unexpected flex end\n" )); + goto Syntax_Error; + } + + if ( top[0] != 3 ) + goto Unexpected_OtherSubr; + + top -= 3; + if ( top < decoder->stack ) + goto Stack_Underflow; + + /* now consume the remaining `pop pop setcurrentpoint' */ + if ( ip + 6 > limit || + ip[0] != 12 || ip[1] != 17 || /* pop */ + ip[2] != 12 || ip[3] != 17 || /* pop */ + ip[4] != 12 || ip[5] != 33 ) /* setcurrentpoint */ + { + FT_ERROR(( "T1_Parse_CharStrings: invalid flex charstring\n" )); + goto Syntax_Error; + } + + decoder->flex_state = 0; + decoder->top = top; + + error = t1operator_flex( decoder, top[0], top[1], top[2] ); + break; + + case 3: /* change hints */ + if ( top[0] != 1 ) + goto Unexpected_OtherSubr; + + /* eat the following `pop' */ + if ( ip + 2 > limit ) + { + FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if ( ip[0] != 12 || ip[1] != 17 ) + { + FT_ERROR(( "T1_Parse_CharStrings:" )); + FT_ERROR(( " `pop' expected, found (%d %d)\n", ip[0], ip[1] )); + goto Syntax_Error; + } + + ip += 2; + + error = hints->change_hints( builder ); + break; + + default: + /* invalid OtherSubrs call */ + Unexpected_OtherSubr: + FT_ERROR(( "T1_Parse_CharStrings: unexpected OtherSubrs [%d %d]\n", + top[0], top[1] )); + goto Syntax_Error; + } + decoder->top = top; + } + else + { + FT_Int num_args = args_count[op]; + + + if ( top - decoder->stack < num_args ) + goto Stack_Underflow; + + top -= num_args; + + switch ( op ) + { + case op_endchar: + error = builds->end_char( builder ); + break; + + case op_hsbw: + error = builds->set_bearing_point( builder, top[0], 0, + top[1], 0 ); + 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: + error = builds->set_bearing_point( builder, top[0], top[1], + top[2], top[3] ); + break; + + case op_closepath: + error = builds->close_path( builder ); + break; + + case op_hlineto: + error = builds->rline_to( builder, top[0], 0 ); + break; + + case op_hmoveto: + error = builds->rmove_to( builder, top[0], 0 ); + break; + + case op_hvcurveto: + error = builds->rcurve_to( builder, top[0], 0, + top[1], top[2], + 0, top[3] ); + break; + + case op_rlineto: + error = builds->rline_to( builder, top[0], top[1] ); + break; + + case op_rmoveto: + /* ignore operator when in flex mode */ + if ( decoder->flex_state == 0 ) + error = builds->rmove_to( builder, top[0], top[1] ); + else + top += 2; + break; + + case op_rrcurveto: + error = builds->rcurve_to( builder, top[0], top[1], + top[2], top[3], + top[4], top[5] ); + break; + + case op_vhcurveto: + error = builds->rcurve_to( builder, 0, top[0], + top[1], top[2], + top[3], 0 ); + break; + + case op_vlineto: + error = builds->rline_to( builder, 0, top[0] ); + break; + + case op_vmoveto: + error = builds->rmove_to( builder, 0, top[0] ); + break; + + case op_dotsection: + error = hints->dot_section( builder ); + break; + + case op_hstem: + error = hints->stem( builder, top[0], top[1], 0 ); + break; + + case op_hstem3: + error = hints->stem3( builder, top[0], top[1], top[2], + top[3], top[4], top[5], 0 ); + break; + + case op_vstem: + error = hints->stem( builder, top[0], top[1], 1 ); + break; + + case op_vstem3: + error = hints->stem3( builder, top[0], top[1], top[2], + top[3], top[4], top[5], 1 ); + break; + + case op_div: + if ( top[1] ) + { + *top = top[0] / top[1]; + ++top; + } + else + { + FT_ERROR(( "T1_Parse_CHarStrings: division by 0\n" )); + goto Syntax_Error; + } + break; + + case op_callsubr: + { + FT_Int index = top[0]; + + + if ( index < 0 || index >= num_subrs ) + { + FT_ERROR(( "T1_Parse_CharStrings: invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "T1_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = subrs_base[index]; + zone->limit = zone->base + subrs_len[index]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "T1_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case op_pop: + FT_ERROR(( "T1_Parse_CharStrings: unexpected POP\n" )); + goto Syntax_Error; + + case op_return: + if ( zone <= decoder->zones ) + { + FT_ERROR(( "T1_Parse_CharStrings: unexpected return\n" )); + goto Syntax_Error; + } + + zone--; + ip = zone->cursor; + limit = zone->limit; + decoder->zone = zone; + break; + + case op_setcurrentpoint: + FT_ERROR(( "T1_Parse_CharStrings:" )); + FT_ERROR(( " unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + break; + + default: + FT_ERROR(( "T1_Parse_CharStrings: unhandled opcode %d\n", op )); + goto Syntax_Error; + } + + decoder->top = top; + } + } + + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Add_Points */ + /* */ + /* */ + /* Checks that there is enough room in the current load glyph outline */ + /* to accept `num_points' additional outline points. If not, this */ + /* function grows the load outline's arrays accordingly. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder object. */ + /* */ + /* num_points :: The number of points that will be added later. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function does NOT update the points count in the glyph */ + /* builder. This must be done by the caller itself, after this */ + /* function has been invoked. */ + /* */ + LOCAL_FUNC + FT_Error T1_Add_Points( T1_Builder* builder, + FT_Int num_points ) + { + return FT_GlyphLoader_Check_Points( builder->loader, num_points, 0 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Add_Contours */ + /* */ + /* */ + /* Checks that there is enough room in the current load glyph outline */ + /* to accept `num_contours' additional contours. If not, this */ + /* function grows the load outline's arrays accordingly. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder object. */ + /* */ + /* num_contours :: The number of contours that will be added later. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function does NOT update the contours count in the load glyph */ + /* This must be done by the caller itself, after this function is */ + /* invoked. */ + /* */ + LOCAL_FUNC + FT_Error T1_Add_Contours( T1_Builder* builder, + FT_Int num_contours ) + { + return FT_GlyphLoader_Check_Points( builder->loader, 0, num_contours ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** 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. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error maxadv_sbw( T1_Decoder* decoder, + FT_Pos sbx, + FT_Pos sby, + FT_Pos wx, + FT_Pos wy ) + { + FT_UNUSED( sbx ); + FT_UNUSED( sby ); + FT_UNUSED( wy ); + + if ( wx > decoder->builder.advance.x ) + decoder->builder.advance.x = wx; + + return -1; /* return an error code to exit the Type 1 parser */ + /* immediately. */ + } + + + static + FT_Int maxadv_error( void ) + { + /* we should never reach this code, unless with a buggy font */ + return -2; + } + + + /* the maxadv_gbuilder_interface is used when computing the maximum */ + /* advance width of all glyphs in a given font. We only process the */ + /* `sbw' operator here, and return an error for all others. */ + + /* Note that `seac' is processed by the T1_Decoder. */ + static + const T1_Builder_Funcs maxadv_builder_interface = + { + (T1_Builder_EndChar) maxadv_error, + (T1_Builder_Sbw) maxadv_sbw, + (T1_Builder_ClosePath)maxadv_error, + (T1_Builder_RLineTo) maxadv_error, + (T1_Builder_RMoveTo) maxadv_error, + (T1_Builder_RCurveTo) maxadv_error + }; + + + /* the maxadv_hinter_interface always return an error. */ + static + const T1_Hinter_Funcs maxadv_hinter_interface = + { + (T1_Hinter_DotSection) maxadv_error, + (T1_Hinter_ChangeHints)maxadv_error, + (T1_Hinter_Stem) maxadv_error, + (T1_Hinter_Stem3) maxadv_error, + }; + + + LOCAL_FUNC + 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; + + + *max_advance = 0; + + /* Initialize load decoder */ + T1_Init_Decoder( &decoder, &maxadv_hinter_interface ); + + T1_Init_Builder( &decoder.builder, face, 0, 0, + &maxadv_builder_interface ); + + /* 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_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + /* 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' *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error close_open_path( T1_Builder* builder ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Int num_points; + FT_Int first_point; + + + /* Some fonts, like Hershey, are made of `open paths' which are */ + /* now managed directly by FreeType. In this case, it is necessary */ + /* to close the path by duplicating its points in reverse order, */ + /* which is precisely the purpose of this function. */ + + /* first compute the number of points to duplicate */ + if ( cur->n_contours > 1 ) + first_point = cur->contours[cur->n_contours - 2] + 1; + else + first_point = 0; + + num_points = cur->n_points - first_point - 2; + if ( num_points > 0 ) + { + FT_Vector* source_point; + char* source_tags; + FT_Vector* point; + char* tags; + + + error = T1_Add_Points( builder, num_points ); + if ( error ) + return error; + + point = cur->points + cur->n_points; + tags = cur->tags + cur->n_points; + + source_point = point - 2; + source_tags = tags - 2; + + cur->n_points += num_points; + + if ( builder->load_points ) + do + { + *point++ = *source_point--; + *tags++ = *source_tags--; + num_points--; + + } while ( num_points > 0 ); + } + + builder->path_begun = 0; + return T1_Err_Ok; + } + + + static + FT_Error gload_closepath( T1_Builder* builder ) + { + FT_Outline* cur = builder->current; + + + /* XXXX: We must not include the last point in the path if it */ + /* is located on the first point. */ + if ( cur->n_points > 1 ) + { + FT_Int first = 0; + FT_Vector* p1 = cur->points + first; + FT_Vector* p2 = cur->points + cur->n_points - 1; + + + if ( cur->n_contours > 1 ) + { + first = cur->contours[cur->n_contours - 2] + 1; + p1 = cur->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + cur->n_points--; + } + + /* save current contour, if any */ + if ( cur->n_contours > 0 ) + cur->contours[cur->n_contours - 1] = cur->n_points - 1; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + /* hint last points if necessary -- this is not strictly required */ + /* there, but it helps for debugging, and doesn't affect performance */ + if ( builder->pass == 1 ) + T1_Hint_Points( builder ); +#endif + + builder->path_begun = 0; + return T1_Err_Ok; + } + + + static + FT_Error gload_endchar( T1_Builder* builder ) + { + FT_Error error; + + + /* close path if needed */ + if ( builder->path_begun ) + { + error = close_open_path( builder ); + if ( error ) + return error; + } + + error = gload_closepath( builder ); + + FT_GlyphLoader_Add( builder->loader ); + + return error; + } + + + static + FT_Error gload_sbw( T1_Builder* builder, + FT_Pos sbx, + FT_Pos sby, + FT_Pos wx, + FT_Pos wy ) + { + builder->left_bearing.x += sbx; + builder->left_bearing.y += sby; + builder->advance.x = wx; + builder->advance.y = wy; + + builder->last.x = sbx; + builder->last.y = sby; + + return 0; + } + + + static + FT_Error gload_rlineto( T1_Builder* builder, + FT_Pos dx, + FT_Pos dy ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Vector vec; + + + /* grow buffer if necessary */ + error = T1_Add_Points( builder, 1 ); + if ( error ) + return error; + + if ( builder->load_points ) + { + /* save point */ + vec.x = builder->last.x + dx; + vec.y = builder->last.y + dy; + + cur->points[cur->n_points] = vec; + cur->tags [cur->n_points] = FT_Curve_Tag_On; + + builder->last = vec; + } + cur->n_points++; + + builder->path_begun = 1; + + return T1_Err_Ok; + } + + + static + FT_Error gload_rmoveto( T1_Builder* builder, + FT_Pos dx, + FT_Pos dy ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Vector vec; + + + /* in the case where `path_begun' is set, we have an `rmoveto' */ + /* after some normal path definition. If the face's paint type */ + /* is set to 1, this means that we have an `open path', also */ + /* called a `stroke'. The FreeType raster doesn't support */ + /* opened paths, so we'll close it explicitely there. */ + + if ( builder->path_begun && builder->face->type1.paint_type == 1 ) + { + if ( builder->face->type1.paint_type == 1 ) + { + error = close_open_path( builder ); + if ( error ) + return error; + } + } + + /* grow buffer if necessary */ + error = T1_Add_Contours( builder, 1 ) || + T1_Add_Points ( builder, 1 ); + if ( error ) + return error; + + /* save current contour, if any */ + if ( cur->n_contours > 0 ) + cur->contours[cur->n_contours - 1] = cur->n_points - 1; + + if ( builder->load_points ) + { + /* save point */ + vec.x = builder->last.x + dx; + vec.y = builder->last.y + dy; + cur->points[cur->n_points] = vec; + cur->tags [cur->n_points] = FT_Curve_Tag_On; + + builder->last = vec; + } + + cur->n_contours++; + cur->n_points++; + + return T1_Err_Ok; + } + + + static + FT_Error gload_rrcurveto( T1_Builder* builder, + FT_Pos dx1, + FT_Pos dy1, + FT_Pos dx2, + FT_Pos dy2, + FT_Pos dx3, + FT_Pos dy3 ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Vector vec; + FT_Vector* points; + char* tags; + + + /* grow buffer if necessary */ + error = T1_Add_Points( builder, 3 ); + if ( error ) + return error; + + if ( builder->load_points ) + { + /* save point */ + points = cur->points + cur->n_points; + tags = cur->tags + cur->n_points; + + vec.x = builder->last.x + dx1; + vec.y = builder->last.y + dy1; + points[0] = vec; + tags[0] = FT_Curve_Tag_Cubic; + + vec.x += dx2; + vec.y += dy2; + points[1] = vec; + tags[1] = FT_Curve_Tag_Cubic; + + vec.x += dx3; + vec.y += dy3; + points[2] = vec; + tags[2] = FT_Curve_Tag_On; + + builder->last = vec; + } + + cur->n_points += 3; + builder->path_begun = 1; + + return T1_Err_Ok; + } + + + static + FT_Error gload_ignore( void ) + { + return 0; + } + + + static + const T1_Builder_Funcs gload_builder_interface = + { + gload_endchar, + gload_sbw, + gload_closepath, + gload_rlineto, + gload_rmoveto, + gload_rrcurveto + }; + + + static + const T1_Builder_Funcs gload_builder_interface_null = + { + (T1_Builder_EndChar) gload_ignore, + (T1_Builder_Sbw) gload_sbw, /* record left bearing */ + (T1_Builder_ClosePath)gload_ignore, + (T1_Builder_RLineTo) gload_ignore, + (T1_Builder_RMoveTo) gload_ignore, + (T1_Builder_RCurveTo) gload_ignore + }; + + + static + const T1_Hinter_Funcs gload_hinter_interface = + { + (T1_Hinter_DotSection) gload_ignore, /* dotsection */ + (T1_Hinter_ChangeHints)gload_ignore, /* changehints */ + (T1_Hinter_Stem) gload_ignore, /* hstem & vstem */ + (T1_Hinter_Stem3) gload_ignore, /* hstem3 & vestem3 */ + }; + + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + + /*************************************************************************/ + /* */ + /* Hinter overview: */ + /* */ + /* This is a two-pass hinter. On the first pass, the hints are all */ + /* recorded by the hinter, and no point is loaded in the outline. */ + /* */ + /* When the first pass is finished, all stems hints are grid-fitted */ + /* at once. */ + /* */ + /* Then, a second pass is performed to load the outline points as */ + /* well as hint/scale them correctly. */ + /* */ + /*************************************************************************/ + + + static + FT_Error t1_load_hinted_glyph( T1_Decoder* decoder, + FT_UInt glyph_index, + FT_Bool recurse ) + { + T1_Builder* builder = &decoder->builder; + T1_GlyphSlot glyph = builder->glyph; + T1_Font* type1 = &builder->face->type1; + FT_UInt old_points, old_contours; + FT_GlyphLoader* loader = decoder->builder.loader; + FT_Error error; + + + /* Pass 1 -- try to load first glyph, simply recording points */ + old_points = loader->base.outline.n_points; + old_contours = loader->base.outline.n_contours; + + FT_GlyphLoader_Prepare( decoder->builder.loader ); + + T1_Reset_Builder( builder, 0 ); + + builder->no_recurse = recurse; + builder->pass = 0; + glyph->hints->hori_stems.num_stems = 0; + glyph->hints->vert_stems.num_stems = 0; + + error = T1_Parse_CharStrings( decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + goto Exit; + + /* check for composite (i.e. `seac' operator) */ + if ( glyph->root.format == ft_glyph_format_composite ) + { + /* this is a composite glyph, we must then load the first one, */ + /* then load the second one on top of it and translate it by a */ + /* fixed amount. */ + FT_UInt n_base_points; + FT_SubGlyph* subglyph = loader->base.subglyphs; + T1_Size size = builder->size; + FT_Pos dx, dy; + FT_Vector left_bearing, advance; + + + /* clean glyph format */ + glyph->root.format = ft_glyph_format_none; + + /* First load `bchar' in builder */ + builder->no_recurse = 0; + error = t1_load_hinted_glyph( decoder, subglyph->index, 0 ); + if ( error ) + goto Exit; + + /* save the left bearing and width of the base character */ + /* as they will be erased by the next load */ + left_bearing = builder->left_bearing; + advance = builder->advance; + + /* Then load `achar' in builder */ + n_base_points = builder->base->n_points; + subglyph++; + error = t1_load_hinted_glyph( decoder, subglyph->index, 0 ); + if ( error ) + goto Exit; + + /* Finally, move the accent */ + dx = FT_MulFix( subglyph->arg1, size->root.metrics.x_scale ); + dy = FT_MulFix( subglyph->arg2, size->root.metrics.y_scale ); + dx = ( dx + 32 ) & -64; + dy = ( dy + 32 ) & -64; + { + FT_Outline dummy; + + + dummy.n_points = loader->base.outline.n_points - n_base_points; + dummy.points = loader->base.outline.points + n_base_points; + + FT_Outline_Translate( &dummy, dx, dy ); + } + + /* restore the left side bearing and */ + /* advance width of the base character */ + builder->left_bearing = left_bearing; + builder->advance = advance; + } + else + { + /* All right, pass 1 is finished, now grid-fit all stem hints */ + T1_Hint_Stems( &decoder->builder ); + + /* undo the end-char */ + builder->base->n_points = old_points; + builder->base->n_contours = old_contours; + + /* Pass 2 -- record and scale/hint the points */ + T1_Reset_Builder( builder, 0 ); + + builder->pass = 1; + builder->no_recurse = 0; + + error = T1_Parse_CharStrings( decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + } + + /* save new glyph tables */ + if ( recurse ) + T1_Done_Builder( builder ); + + Exit: + return error; + } + + +#endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */ + + + LOCAL_FUNC + 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; + + + 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; + + glyph->root.format = ft_glyph_format_outline; /* by default */ + + hinting = 0; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + hinting = ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0; + + if ( hinting ) + { + T1_Init_Decoder( &decoder, &t1_hinter_funcs ); + T1_Init_Builder( &decoder.builder, face, size, glyph, + &gload_builder_interface ); + + error = t1_load_hinted_glyph( &decoder, glyph_index, 1 ); + } + else + +#endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */ + + { + T1_Init_Decoder( &decoder, &gload_hinter_interface ); + + T1_Init_Builder( &decoder.builder, face, size, glyph, + &gload_builder_interface ); + + decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0; + + /* now load the unscaled outline */ + error = T1_Parse_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + + /* save new glyph tables */ + T1_Done_Builder( &decoder.builder ); + } + + /* 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 the left side bearing and the */ + /* advance width */ + if ( glyph->root.format == ft_glyph_format_composite ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.builder.advance.x; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, + &face->type1.font_matrix ); + + 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; + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.format = ft_glyph_format_outline; + + glyph->root.outline.flags = 0; + + if ( size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= ft_outline_high_precision; + + glyph->root.outline.flags |= ft_outline_reverse_fill; + + if ( hinting ) + { + /* adjust the advance width */ + /* XXX TODO: consider stem hints grid-fit */ + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, + glyph->x_scale ); + } + else 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 ); + } + + /* Then scale the metrics */ + metrics->width = FT_MulFix( metrics->width, x_scale ); + metrics->height = FT_MulFix( metrics->height, y_scale ); + + metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale ); + metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale ); + + metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); + metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); + + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + } + } + } + + return error; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1gload.h b/reactos/subsys/win32k/freetype/src/type1/t1gload.h new file mode 100644 index 00000000000..658a929d068 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1gload.h @@ -0,0 +1,326 @@ +/***************************************************************************/ +/* */ +/* t1gload.h */ +/* */ +/* Type 1 Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct T1_Builder_ T1_Builder; + + typedef FT_Error (*T1_Builder_EndChar)( T1_Builder* loader ); + + typedef FT_Error (*T1_Builder_Sbw)( T1_Builder* loader, + FT_Pos sbx, + FT_Pos sby, + FT_Pos wx, + FT_Pos wy ); + + typedef FT_Error (*T1_Builder_ClosePath)( T1_Builder* loader ); + + typedef FT_Error (*T1_Builder_RLineTo)( T1_Builder* loader, + FT_Pos dx, + FT_Pos dy ); + + typedef FT_Error (*T1_Builder_RMoveTo)( T1_Builder* loader, + FT_Pos dx, + FT_Pos dy ); + + typedef FT_Error (*T1_Builder_RCurveTo)( T1_Builder* loader, + FT_Pos dx1, + FT_Pos dy1, + FT_Pos dx2, + FT_Pos dy2, + FT_Pos dx3, + FT_Pos dy3 ); + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Builder_Funcs */ + /* */ + /* */ + /* A structure to store the address of various functions used by a */ + /* glyph builder to implement the outline's `path construction'. */ + /* */ + typedef struct T1_Builder_Funcs_ + { + T1_Builder_EndChar end_char; + T1_Builder_Sbw set_bearing_point; + T1_Builder_ClosePath close_path; + T1_Builder_RLineTo rline_to; + T1_Builder_RMoveTo rmove_to; + T1_Builder_RCurveTo rcurve_to; + + } T1_Builder_Funcs; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* loader :: The current glyph loader. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* base :: The base glyph 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 (for composite glyphs). */ + /* */ + /* pos_y :: The vertical translation (for composite glyphs). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* no_recurse :: */ + /* */ + /* bbox :: The glyph's bounding box. */ + /* */ + /* path_begun :: A flag which indicates that a new path has begun. */ + /* */ + /* load_points :: A flag which indicates, if not set, that no points */ + /* are loaded. */ + /* */ + /* pass :: The pass number for multi-pass hinters. */ + /* */ + /* hint_point :: The index of the next point to hint. */ + /* */ + /* funcs :: A table of builder functions used to perform the */ + /* outline's path construction. */ + /* */ + struct T1_Builder_ + { + FT_Memory memory; + T1_Face face; + T1_Size size; + T1_GlyphSlot glyph; + FT_GlyphLoader* loader; + + FT_Outline* current; /* the current glyph outline */ + FT_Outline* base; /* the composite glyph outline */ + + 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_Bool no_recurse; + + FT_BBox bbox; /* bounding box */ + FT_Bool path_begun; + FT_Bool load_points; + + FT_Int pass; + FT_Int hint_point; + + /* path construction function interface */ + T1_Builder_Funcs funcs; + }; + + + typedef FT_Error (*T1_Hinter_ChangeHints)( T1_Builder* builder ); + + typedef FT_Error (*T1_Hinter_DotSection)( T1_Builder* builder ); + + typedef FT_Error (*T1_Hinter_Stem)( T1_Builder* builder, + FT_Pos pos, + FT_Pos width, + FT_Bool vertical ); + + typedef FT_Error (*T1_Hinter_Stem3)( T1_Builder* builder, + FT_Pos pos0, + FT_Pos width0, + FT_Pos pos1, + FT_Pos width1, + FT_Pos pos2, + FT_Pos width2, + FT_Bool vertical ); + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Hinter_Funcs */ + /* */ + /* */ + /* A structure to store the address of various functions used by a */ + /* Type 1 hinter to perform outline hinting. */ + /* */ + typedef struct T1_Hinter_Func_ + { + T1_Hinter_ChangeHints change_hints; + T1_Hinter_DotSection dot_section; + T1_Hinter_Stem stem; + T1_Hinter_Stem3 stem3; + + } T1_Hinter_Funcs; + + + 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; + + + /* execution context charstring zone */ + typedef struct T1_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } T1_Decoder_Zone; + + + typedef struct T1_Decoder_ + { + T1_Builder builder; + T1_Hinter_Funcs hinter; + + FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS]; + FT_Int* top; + + T1_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1]; + T1_Decoder_Zone* zone; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + } T1_Decoder; + + + LOCAL_DEF + void T1_Init_Builder( T1_Builder* builder, + T1_Face face, + T1_Size size, + T1_GlyphSlot glyph, + const T1_Builder_Funcs* funcs ); + + LOCAL_DEF + void T1_Done_Builder( T1_Builder* builder ); + + LOCAL_DEF + void T1_Init_Decoder( T1_Decoder* decoder, + const T1_Hinter_Funcs* funcs ); + + LOCAL_DEF + FT_Error T1_Compute_Max_Advance( T1_Face face, + FT_Int* max_advance ); + + LOCAL_DEF + FT_Error T1_Parse_CharStrings( T1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ); + + LOCAL_DEF + FT_Error T1_Add_Points( T1_Builder* builder, + FT_Int num_points ); + + LOCAL_DEF + FT_Error T1_Add_Contours( T1_Builder* builder, + FT_Int num_contours ); + + LOCAL_DEF + FT_Error T1_Load_Glyph( T1_GlyphSlot glyph, + T1_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T1GLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1hinter.c b/reactos/subsys/win32k/freetype/src/type1/t1hinter.c new file mode 100644 index 00000000000..7ce746228aa --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1hinter.c @@ -0,0 +1,1347 @@ +/***************************************************************************/ +/* */ +/* t1hinter.c */ +/* */ +/* Type 1 hinter (body). */ +/* */ +/* Copyright 1996-2000 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 Hinter is in charge of fitting th scaled outline to the pixel */ + /* grid in order to considerably improve the quality of the Type 1 font */ + /* driver's output. */ + /* */ + /*************************************************************************/ + + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" +#include "t1hinter.h" + +#else + +#include +#include + +#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_t1hint + + +#undef ONE_PIXEL +#define ONE_PIXEL 64 + +#undef ROUND +#define ROUND( x ) ( ( x + ONE_PIXEL / 2 ) & -ONE_PIXEL ) + +#undef SCALE +#define SCALE( val ) FT_MulFix( val, scale ) + +/* various constants used to describe the alignment of a horizontal */ +/* stem with regards to the blue zones */ + +#define T1_ALIGN_NONE 0 +#define T1_ALIGN_BOTTOM 1 +#define T1_ALIGN_TOP 2 +#define T1_ALIGN_BOTH 3 + + + /* very simple bubble sort (not a lot of elements, mostly */ + /* pre-sorted, no need for quicksort) */ + + static + void t1_sort_blues( FT_Int* blues, + FT_Int count ) + { + FT_Int i, swap; + FT_Int* cur; + + + for ( i = 2; i < count; i += 2 ) + { + cur = blues + i; + do + { + if ( cur[-1] < cur[0] ) + break; + + swap = cur[-2]; cur[-2] = cur[0]; cur[0] = swap; + swap = cur[-1]; cur[-1] = cur[1]; cur[1] = swap; + cur -= 2; + + } while ( cur > blues ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_set_blue_zones */ + /* */ + /* */ + /* Sets a size object's blue zones during reset. This will compute */ + /* the `snap' zone corresponding to each blue zone. */ + /* */ + /* */ + /* size :: A handle to target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This functions does the following: */ + /* */ + /* 1. It extracts the bottom and top blue zones from the face object. */ + /* */ + /* 2. Each zone is then grown by `BlueFuzz', overlapping is */ + /* eliminated by adjusting the zone edges appropriately. */ + /* */ + /* 3. For each zone, we keep its original font units position, its */ + /* original scaled position, as well as its grown/adjusted edges. */ + /* */ + static + FT_Error t1_set_blue_zones( T1_Size size ) + { + T1_Face face = (T1_Face)size->root.face; + T1_Private* priv = &face->type1.private_dict; + FT_Int n; + FT_Int blues[24]; + FT_Int num_bottom; + FT_Int num_top; + FT_Int num_blues; + T1_Size_Hints* hints = size->hints; + T1_Snap_Zone* zone; + FT_Pos pix, orus; + FT_Pos min, max, threshold; + FT_Fixed scale; + FT_Bool is_bottom; + + + /***********************************************************************/ + /* */ + /* copy bottom and top blue zones in local arrays */ + /* */ + + /* First of all, check the sizes of the /BlueValues and /OtherBlues */ + /* tables. They all must contain an even number of arguments. */ + if ( priv->num_other_blues & 1 || + priv->num_blue_values & 1 ) + { + FT_ERROR(( "t1_set_blue_zones: odd number of blue values\n" )); + return T1_Err_Syntax_Error; + } + + /* copy the bottom blue zones from /OtherBlues */ + num_top = 0; + num_bottom = priv->num_other_blues; + + for ( n = 0; n < num_bottom; n++ ) + blues[n] = priv->other_blues[n]; + + /* add the first blue zone in /BlueValues to the table */ + num_top = priv->num_blue_values - 2; + if ( num_top >= 0 ) + { + blues[num_bottom ] = priv->blue_values[0]; + blues[num_bottom + 1] = priv->blue_values[1]; + + num_bottom += 2; + } + + /* sort the bottom blue zones */ + t1_sort_blues( blues, num_bottom ); + + hints->num_bottom_zones = num_bottom >> 1; + + /* now copy the /BlueValues to the top of the blues array */ + if ( num_top > 0 ) + { + for ( n = 0; n < num_top; n++ ) + blues[num_bottom + n] = priv->blue_values[n + 2]; + + /* sort the top blue zones */ + t1_sort_blues( blues + num_bottom, num_top ); + } + else + num_top = 0; + + num_blues = num_top + num_bottom; + hints->num_blue_zones = ( num_blues ) >> 1; + + /***********************************************************************/ + /* */ + /* build blue snap zones from the local blues arrays */ + /* */ + + scale = size->root.metrics.y_scale; + zone = hints->blue_zones; + threshold = ONE_PIXEL / 4; /* 0.25 pixels */ + + for ( n = 0; n < num_blues; n += 2, zone++ ) + { + is_bottom = n < num_bottom ? 1 : 0; + + orus = blues[n + is_bottom]; /* get alignement coordinate */ + pix = SCALE( orus ); /* scale it */ + + min = SCALE( blues[n ] - priv->blue_fuzz ); + max = SCALE( blues[n + 1] + priv->blue_fuzz ); + + if ( min > pix - threshold ) + min = pix - threshold; + if ( max < pix + threshold ) + max = pix + threshold; + + zone->orus = orus; + zone->pix = pix; + zone->min = min; + zone->max = max; + } + + /* adjust edges in case of overlap */ + zone = hints->blue_zones; + for ( n = 0; n < num_blues - 2; n += 2, zone++ ) + { + if ( n != num_bottom - 2 && + zone[0].max > zone[1].min ) + zone[0].max = zone[1].min = ( zone[0].pix + zone[1].pix ) / 2; + } + + /* compare the current pixel size with the BlueScale value */ + /* to know whether to supress overshoots */ + + hints->supress_overshoots = + size->root.metrics.y_ppem < FT_MulFix( 1000, priv->blue_scale ); + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* now print the new blue values in tracing mode */ + + FT_TRACE2(( "Blue Zones for size object at $%08lx:\n", (long)size )); + FT_TRACE2(( " orus pix min max\n" )); + FT_TRACE2(( "-------------------------------\n" )); + + zone = hints->blue_zones; + for ( n = 0; n < hints->num_blue_zones; n++ ) + { + FT_TRACE2(( " %3d %.2f %.2f %.2f\n", + zone->orus, + zone->pix / 64.0, + zone->min / 64.0, + zone->max / 64.0 )); + zone++; + } + FT_TRACE2(( "\nOvershoots are %s\n\n", + hints->supress_overshoots ? "supressed" : "active" )); + +#endif /* DEBUG_LEVEL_TRACE */ + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_set_snap_zones */ + /* */ + /* */ + /* This function set a size object's stem snap zones. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function performs the following: */ + /* */ + /* 1. It reads and scales the stem snap widths from the parent face. */ + /* */ + /* 2. A `snap zone' is computed for each snap width, by `growing' it */ + /* with a threshold of 1/2 pixel. Overlapping is avoided through */ + /* proper edge adjustment. */ + /* */ + /* 3. Each width whose zone contain the scaled standard set width is */ + /* removed from the table. */ + /* */ + /* 4. Finally, the standard set width is scaled, and its correponding */ + /* `snap zone' is inserted into the sorted snap zones table. */ + /* */ + static + FT_Error t1_set_snap_zones( T1_Size size ) + { + FT_Int n, direction, n_zones, num_zones; + T1_Snap_Zone* zone; + T1_Snap_Zone* base_zone; + FT_Short* orgs; + FT_Pos standard_width; + FT_Fixed scale; + + T1_Face face = (T1_Face)size->root.face; + T1_Private* priv = &face->type1.private_dict; + T1_Size_Hints* hints = size->hints; + + + /* start with horizontal snap zones */ + direction = 0; + standard_width = priv->standard_width[0]; + n_zones = priv->num_snap_widths; + base_zone = hints->snap_widths; + orgs = priv->snap_widths; + scale = size->root.metrics.x_scale; + + while ( direction < 2 ) + { + /*********************************************************************/ + /* */ + /* Read and scale stem snap widths table from the physical font */ + /* record. */ + /* */ + + FT_Pos prev, orus, pix, min, max, threshold; + + + threshold = ONE_PIXEL / 4; + zone = base_zone; + + if ( n_zones > 0 ) + { + orus = *orgs++; + pix = SCALE( orus ); + min = pix - threshold; + max = pix + threshold; + + zone->orus = orus; + zone->pix = pix; + zone->min = min; + prev = pix; + + for ( n = 1; n < n_zones; n++ ) + { + orus = *orgs++; + pix = SCALE( orus ); + + if ( pix - prev < 2 * threshold ) + { + min = max = ( pix + prev ) / 2; + } + else + min = pix - threshold; + + zone->max = max; + zone++; + zone->orus = orus; + zone->pix = pix; + zone->min = min; + + max = pix + threshold; + prev = pix; + } + zone->max = max; + } + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* print the scaled stem snap values in tracing mode */ + + FT_TRACE2(( "Set_Snap_Zones: first %s pass\n", + direction ? "vertical" : "horizontal" )); + + FT_TRACE2(( "Scaled original stem snap zones:\n" )); + FT_TRACE2(( " orus pix min max\n" )); + FT_TRACE2(( "-----------------------------\n" )); + + zone = base_zone; + for ( n = 0; n < n_zones; n++, zone++ ) + FT_TRACE2(( " %3d %.2f %.2f %.2f\n", + zone->orus, + zone->pix / 64.0, + zone->min / 64.0, + zone->max / 64.0 )); + FT_TRACE2(( "\n" )); + + FT_TRACE2(( "Standard width = %d\n", standard_width )); + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + /*********************************************************************/ + /* */ + /* Now, each snap width which is in the range of the standard set */ + /* width will be removed from the list. */ + /* */ + + if ( standard_width > 0 ) + { + T1_Snap_Zone* parent; + FT_Pos std_pix, std_min, std_max; + + + std_pix = SCALE( standard_width ); + + std_min = std_pix - threshold; + std_max = std_pix + threshold; + + num_zones = 0; + zone = base_zone; + parent = base_zone; + + for ( n = 0; n < n_zones; n++ ) + { + if ( zone->pix >= std_min && zone->pix <= std_max ) + { + /* this zone must be removed from the list */ + if ( std_min > zone->min ) + std_min = zone->min; + if ( std_max < zone->max ) + std_max = zone->max; + } + else + { + *parent++ = *zone; + num_zones++; + } + zone++; + } + + /*******************************************************************/ + /* */ + /* Now, insert the standard width zone */ + /* */ + + zone = base_zone + num_zones; + while ( zone > base_zone && zone[-1].pix > std_max ) + { + zone[0] = zone[-1]; + zone--; + } + + /* check border zones */ + if ( zone > base_zone && zone[-1].max > std_min ) + zone[-1].max = std_min; + + if ( zone < base_zone + num_zones && zone[1].min < std_max ) + zone[1].min = std_max; + + zone->orus = standard_width; + zone->pix = std_pix; + zone->min = std_min; + zone->max = std_max; + + num_zones++; + } + else + num_zones = n_zones; + + /* save total number of stem snaps now */ + if ( direction ) + hints->num_snap_heights = num_zones; + else + hints->num_snap_widths = num_zones; + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* print the scaled stem snap values in tracing mode */ + + FT_TRACE2(( "Set_Snap_Zones: second %s pass\n", + direction ? "vertical" : "horizontal" )); + + FT_TRACE2(( "Scaled clipped stem snap zones:\n" )); + FT_TRACE2(( " orus pix min max\n" )); + FT_TRACE2(( "-----------------------------\n" )); + + zone = base_zone; + for ( n = 0; n < num_zones; n++, zone++ ) + FT_TRACE2(( " %3d %.2f %.2f %.2f\n", + zone->orus, + zone->pix / 64.0, + zone->min / 64.0, + zone->max / 64.0 )); + FT_TRACE2(( "\n" )); + + FT_TRACE2(( "Standard width = %d\n", standard_width )); + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + /* continue with vertical snap zone */ + direction++; + standard_width = priv->standard_height[0]; + n_zones = priv->num_snap_heights; + base_zone = hints->snap_heights; + orgs = priv->snap_heights; + scale = size->root.metrics.y_scale; + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_New_Size_Hinter */ + /* */ + /* */ + /* Allocates a new hinter structure for a given size object. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType Error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_New_Size_Hinter( T1_Size size ) + { + FT_Memory memory = size->root.face->memory; + + + return MEM_Alloc( size->hints, sizeof ( *size->hints ) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Size_Hinter */ + /* */ + /* */ + /* Releases a given size object's hinter structure. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_FUNC + void T1_Done_Size_Hinter( T1_Size size ) + { + FT_Memory memory = size->root.face->memory; + + + FREE( size->hints ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Reset_Size_Hinter */ + /* */ + /* */ + /* Recomputes hinting information when a given size object has */ + /* changed its resolutions/char sizes/pixel sizes. */ + /* */ + /* */ + /* size :: A handle to the size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Reset_Size_Hinter( T1_Size size ) + { + return t1_set_blue_zones( size ) || t1_set_snap_zones( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_New_Glyph_Hinter */ + /* */ + /* */ + /* Allocates a new hinter structure for a given glyph slot. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph slot. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph ) + { + FT_Memory memory = glyph->root.face->memory; + + + return MEM_Alloc( glyph->hints, sizeof ( *glyph->hints ) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Glyph_Hinter */ + /* */ + /* */ + /* Releases a given glyph slot's hinter structure. */ + /* */ + /* */ + /* glyph :: A handle to the glyph slot. */ + /* */ + LOCAL_FUNC + void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph ) + { + FT_Memory memory = glyph->root.face->memory; + + + FREE( glyph->hints ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** **********/ + /********** HINTED GLYPH LOADER **********/ + /********** **********/ + /********** The following code is in charge of the first **********/ + /********** and second pass when loading a single outline **********/ + /********** **********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error t1_hinter_ignore( void ) + { + /* do nothing, used for `dotsection' which is unsupported for now */ + return 0; + } + + + static + FT_Error t1_hinter_stem( T1_Builder* builder, + FT_Pos pos, + FT_Int width, + FT_Bool vertical ) + { + T1_Stem_Table* stem_table; + T1_Stem_Hint* stems; + T1_Stem_Hint* cur_stem; + FT_Int min, max, n, num_stems; + FT_Bool new_stem; + T1_Glyph_Hints* hinter = builder->glyph->hints; + + + /* select the appropriate stem array */ + stem_table = vertical ? &hinter->vert_stems : &hinter->hori_stems; + stems = stem_table->stems; + num_stems = stem_table->num_stems; + + /* Compute minimum and maximum coord for the stem */ + min = pos + ( vertical + ? builder->left_bearing.x + : builder->left_bearing.y ); + + if ( width >= 0 ) + max = min + width; + else + { + /* a negative width indicates a `ghost' stem */ + if ( width == -21 ) + min += width; + + max = min; + } + + /* Now scan the array. If we find a stem with the same borders */ + /* simply activate it. */ + cur_stem = stems; + new_stem = 1; + + for ( n = 0; n < num_stems; n++, cur_stem++ ) + { + if ( cur_stem->min_edge.orus == min && + cur_stem->max_edge.orus == max ) + { + /* This stem is already in the table, simply activate it */ + if ( ( cur_stem->hint_flags & T1_HINT_FLAG_ACTIVE ) == 0 ) + { + cur_stem->hint_flags |= T1_HINT_FLAG_ACTIVE; + stem_table->num_active++; + } + new_stem = 0; + break; + } + } + + /* add a new stem to the array if necessary */ + if ( new_stem ) + { + if ( cur_stem >= stems + T1_HINTER_MAX_EDGES ) + { + FT_ERROR(( "t1_hinter_stem: too many stems in glyph charstring\n" )); + return T1_Err_Syntax_Error; + } + + /* on the first pass, we record the stem, otherwise, this is */ + /* a bug in the glyph loader! */ + if ( builder->pass == 0 ) + { + cur_stem->min_edge.orus = min; + cur_stem->max_edge.orus = max; + cur_stem->hint_flags = T1_HINT_FLAG_ACTIVE; + + stem_table->num_stems++; + stem_table->num_active++; + } + else + { + FT_ERROR(( "t1_hinter_stem:" )); + FT_ERROR(( " fatal glyph loader bug -- pass2-stem\n" )); + return T1_Err_Syntax_Error; + } + } + + return T1_Err_Ok; + } + + + static + FT_Error t1_hinter_stem3( T1_Builder* builder, + FT_Pos pos0, + FT_Int width0, + FT_Pos pos1, + FT_Int width1, + FT_Pos pos2, + FT_Int width2, + FT_Bool vertical ) + { + /* For now, simply call `stem' 3 times */ + return t1_hinter_stem( builder, pos0, width0, vertical ) || + t1_hinter_stem( builder, pos1, width1, vertical ) || + t1_hinter_stem( builder, pos2, width2, vertical ); + } + + + static + FT_Error t1_hinter_changehints( T1_Builder* builder ) + { + FT_Int dimension; + T1_Stem_Table* stem_table; + T1_Glyph_Hints* hinter = builder->glyph->hints; + + + /* If we are in the second pass of glyph hinting, we must */ + /* call the function T1_Hint_Points() on the builder in order */ + /* to force the fit the latest points to the pixel grid. */ + if ( builder->pass == 1 ) + T1_Hint_Points( builder ); + + /* Simply de-activate all hints in all arrays */ + stem_table = &hinter->hori_stems; + + for ( dimension = 2; dimension > 0; dimension-- ) + { + T1_Stem_Hint* cur = stem_table->stems; + T1_Stem_Hint* limit = cur + stem_table->num_stems; + + + for ( ; cur < limit; cur++ ) + cur->hint_flags &= ~T1_HINT_FLAG_ACTIVE; + + stem_table->num_active = 0; + stem_table = &hinter->vert_stems; + } + + return T1_Err_Ok; + } + + + const T1_Hinter_Funcs t1_hinter_funcs = + { + (T1_Hinter_ChangeHints)t1_hinter_changehints, + (T1_Hinter_DotSection) t1_hinter_ignore, + (T1_Hinter_Stem) t1_hinter_stem, + (T1_Hinter_Stem3) t1_hinter_stem3 + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** STEM HINTS MANAGEMENT *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the placement of each scaled stem hint. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* t1_sort_hints */ + /* */ + /* */ + /* Sorta the list of active stems in increasing order, through the */ + /* `sort' indexing table. */ + /* */ + /* */ + /* table :: A stem hints table. */ + /* */ + static + void t1_sort_hints( T1_Stem_Table* table ) + { + FT_Int num_stems = table->num_stems; + FT_Int num_active = 0; + FT_Int* sort = table->sort; + T1_Stem_Hint* stems = table->stems; + FT_Int n; + + + /* record active stems in sort table */ + for ( n = 0; n < num_stems; n++ ) + { + if ( stems[n].hint_flags & T1_HINT_FLAG_ACTIVE ) + sort[num_active++] = n; + } + + /* Now sort the indices. There are usually very few stems, */ + /* and they are pre-sorted in 90% cases, so we choose a */ + /* simple bubble sort (quicksort would be slower). */ + for ( n = 1; n < num_active; n++ ) + { + FT_Int p = n - 1; + T1_Stem_Hint* cur = stems + sort[n]; + + + do + { + FT_Int swap; + T1_Stem_Hint* prev = stems + sort[p]; + + + /* note that by definition, the active stems cannot overlap */ + /* so we simply compare their `min' to sort them (we could compare */ + /* their max values also; this wouldn't change anything). */ + if ( prev->min_edge.orus <= cur->min_edge.orus ) + break; + + /* swap elements */ + swap = sort[p ]; + sort[p ] = sort[p + 1]; + sort[p + 1] = swap; + p--; + + } while ( p >= 0 ); + } + + table->num_active = num_active; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hint_horizontal_stems */ + /* */ + /* */ + /* Computes the location of each scaled horizontal stem hint. This */ + /* takes care of the blue zones and the horizontal stem snap table. */ + /* */ + /* */ + /* table :: The horizontal stem hints table. */ + /* */ + /* hints :: The current size's hint structure. */ + /* */ + /* blueShift :: The value of the /BlueShift as taken from the face */ + /* object. */ + /* */ + /* scale :: The 16.16 scale used to convert outline units to */ + /* 26.6 pixels. */ + /* */ + /* */ + /* For now, all stems are hinted independently from each other. It */ + /* might be necessary, for better performance, to introduce the */ + /* notion of `controlled' hints describing things like counter-stems, */ + /* stem3, as well as overlapping stems control. */ + /* */ + static + void t1_hint_horizontal_stems( T1_Stem_Table* table, + T1_Size_Hints* hints, + FT_Pos blueShift, + FT_Fixed scale ) + { + T1_Stem_Hint* stem = table->stems; + T1_Stem_Hint* limit = stem + table->num_stems; + + + /* first of all, scale the blueShift */ + blueShift = SCALE( blueShift ); + + /* then scan the horizontal stem table */ + for ( ; stem < limit; stem++ ) + { + FT_Pos bottom_orus = stem->min_edge.orus; + FT_Pos top_orus = stem->max_edge.orus; + + FT_Pos top_pix = SCALE( top_orus ); + FT_Pos bottom_pix = SCALE( bottom_orus ); + FT_Pos width_pix = top_pix - bottom_pix; + + FT_Pos bottom = bottom_pix; + FT_Pos top = top_pix; + FT_Int align = T1_ALIGN_NONE; + + + /*********************************************************************/ + /* */ + /* Snap pixel width if in stem snap range */ + /* */ + + { + T1_Snap_Zone* zone = hints->snap_heights; + T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights; + FT_Pos best_dist = 32000; + T1_Snap_Zone* best_zone = 0; + + + for ( ; zone < zone_limit; zone++ ) + { + FT_Pos dist; + + + dist = width_pix - zone->min; + if ( dist < 0 ) + dist = -dist; + if ( dist < best_dist ) + { + best_zone = zone; + best_dist = dist; + } + } + + if ( best_zone ) + { + if ( width_pix > best_zone->pix ) + { + width_pix -= 0x20; + if ( width_pix < best_zone->pix ) + width_pix = best_zone->pix; + } + else + { + width_pix += 0x20; + if ( width_pix > best_zone->pix ) + width_pix = best_zone->pix; + } + } + } + + /*********************************************************************/ + /* */ + /* round width - minimum 1 pixel if this isn't a ghost stem */ + /* */ + + if ( width_pix > 0 ) + width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND( width_pix ); + + + /*********************************************************************/ + /* */ + /* Now check for bottom blue zones alignement */ + /* */ + + { + FT_Int num_blues = hints->num_bottom_zones; + T1_Snap_Zone* blue = hints->blue_zones; + T1_Snap_Zone* blue_limit = blue + num_blues; + + + for ( ; blue < blue_limit; blue++ ) + { + if ( bottom_pix < blue->min ) + break; + + if ( bottom_pix <= blue->max ) + { + align = T1_ALIGN_BOTTOM; + bottom = ROUND( blue->pix ); + + /* implement blue shift */ + if ( !hints->supress_overshoots ) + { + FT_Pos delta = blue->pix - bottom_pix; + + + delta = delta < blueShift ? 0 : ROUND( delta ); + bottom -= delta; + } + } + } + } + + /*********************************************************************/ + /* */ + /* check for top blue zones alignement */ + /* */ + + { + FT_Int num_blues = hints->num_blue_zones - + hints->num_bottom_zones; + + T1_Snap_Zone* blue = hints->blue_zones + + hints->num_bottom_zones; + + T1_Snap_Zone* blue_limit = blue + num_blues; + + + for ( ; blue < blue_limit; blue++ ) + { + if ( top_pix < blue->min ) + break; + + if ( top_pix <= blue->max ) + { + align |= T1_ALIGN_TOP; + top = ROUND( blue->pix ); + + /* implement blue shift */ + if ( !hints->supress_overshoots ) + { + FT_Pos delta = top - blue->pix; + + + delta = delta < blueShift ? 0 : ROUND( delta ); + top += delta; + } + } + } + } + + /*********************************************************************/ + /* */ + /* compute the hinted stem position, according to its alignment */ + /* */ + + switch ( align ) + { + case T1_ALIGN_BOTTOM: /* bottom zone alignment */ + bottom_pix = bottom; + top_pix = bottom + width_pix; + break; + + case T1_ALIGN_TOP: /* top zone alignment */ + top_pix = top; + bottom_pix = top - width_pix; + break; + + case T1_ALIGN_BOTH: /* bottom+top zone alignment */ + bottom_pix = bottom; + top_pix = top; + break; + + default: /* no alignment */ + /* XXX TODO: Add management of controlled stems */ + bottom = ( SCALE( bottom_orus + top_orus ) - width_pix ) / 2; + + bottom_pix = ROUND( bottom ); + top_pix = bottom_pix + width_pix; + } + + stem->min_edge.pix = bottom_pix; + stem->max_edge.pix = top_pix; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hint_vertical_stems */ + /* */ + /* */ + /* Computes the location of each scaled vertical stem hint. This */ + /* takes care of the vertical stem snap table. */ + /* */ + /* */ + /* table :: The vertical stem hints table. */ + /* hints :: The current size's hint structure. */ + /* scale :: The 16.16 scale used to convert outline units to */ + /* 26.6 pixels. */ + /* */ + /* */ + /* For now, all stems are hinted independently from each other. It */ + /* might be necessary, for better performance, to introduce the */ + /* notion of `controlled' hints describing things like counter-stems, */ + /* stem3 as well as overlapping stems control. */ + /* */ + static + void t1_hint_vertical_stems( T1_Stem_Table* table, + T1_Size_Hints* hints, + FT_Fixed scale ) + { + T1_Stem_Hint* stem = table->stems; + T1_Stem_Hint* limit = stem + table->num_stems; + + + for ( ; stem < limit; stem++ ) + { + FT_Pos stem_left = stem->min_edge.orus; + FT_Pos stem_right = stem->max_edge.orus; + FT_Pos width_pix, left; + + + width_pix = SCALE( stem_right - stem_left ); + + /* Snap pixel width if in stem snap range */ + { + T1_Snap_Zone* zone = hints->snap_heights; + T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights; + FT_Pos best_dist = 32000; + T1_Snap_Zone* best_zone = 0; + + + for ( ; zone < zone_limit; zone++ ) + { + FT_Pos dist; + + + dist = width_pix - zone->min; + if ( dist < 0 ) + dist = -dist; + if ( dist < best_dist ) + { + best_zone = zone; + best_dist = dist; + } + } + + if ( best_zone ) + { + if ( width_pix > best_zone->pix ) + { + width_pix -= 0x20; + if ( width_pix < best_zone->pix ) + width_pix = best_zone->pix; + } + else + { + width_pix += 0x20; + if ( width_pix > best_zone->pix ) + width_pix = best_zone->pix; + } + } + } + + /* round width - minimum 1 pixel if this isn't a ghost stem */ + if ( width_pix > 0 ) + width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL + : ROUND( width_pix ); + + /* now place the snapped and rounded stem */ + + /* XXX TODO: implement controlled stems for the overlapping */ + /* cases */ + + left = ( SCALE( stem_left + stem_right ) - width_pix ) / 2; + + stem->min_edge.pix = ROUND( left ); + stem->max_edge.pix = stem->min_edge.pix + width_pix; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hint_point */ + /* */ + /* */ + /* Grid-fit a coordinate with regards to a given stem hints table. */ + /* */ + /* */ + /* table :: The source stem hints table. */ + /* coord :: The original coordinate, expressed in font units. */ + /* scale :: The 16.16 scale used to convert font units into */ + /* 26.6 pixels. */ + /* */ + /* */ + /* The hinted/scaled value in 26.6 pixels. */ + /* */ + /* */ + /* For now, all stems are hinted independently from each other. It */ + /* might be necessary, for better performance, to introduce the */ + /* notion of `controlled' hints describing things like counter-stems, */ + /* stem3 as well as overlapping stems control. */ + /* */ + static + FT_Pos t1_hint_point( T1_Stem_Table* table, + FT_Pos coord, + FT_Fixed scale ) + { + FT_Int num_active = table->num_active; + FT_Int n; + T1_Stem_Hint* prev = 0; + T1_Stem_Hint* cur = 0; + T1_Edge* min; + T1_Edge* max; + FT_Pos delta; + + + /* only hint when there is at least one stem defined */ + if ( num_active <= 0 ) + return SCALE( coord ); + + /* scan the stem table to determine placement of coordinate */ + /* relative to the list of sorted and stems */ + for ( n = 0; n < num_active; n++, prev = cur ) + { + cur = table->stems + table->sort[n]; + + /* is it on the left of the current edge? */ + delta = cur->min_edge.orus - coord; + if ( delta == 0 ) + return cur->min_edge.pix; + + if ( delta > 0 ) + { + /* if this is the left of the first edge, simply shift */ + if ( !prev ) + return cur->min_edge.pix - SCALE( delta ); + + /* otherwise, interpolate between the maximum of the */ + /* previous stem, and the minimum of the current one */ + min = &prev->max_edge; + max = &cur->min_edge; + + goto Interpolate; + } + + /* is it within the current edge? */ + delta = cur->max_edge.orus - coord; + if ( delta == 0 ) + return cur->max_edge.pix; + + if ( delta > 0 ) + { + /* interpolate within the stem */ + min = &cur->min_edge; + max = &cur->max_edge; + + goto Interpolate; + } + } + + /* apparently, this coordinate is on the right of the last stem */ + delta = coord - cur->max_edge.orus; + return cur->max_edge.pix + SCALE( delta ); + + Interpolate: + return min->pix + FT_MulDiv( coord - min->orus, + max->pix - min->pix, + max->orus - min->orus ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Hint_Points */ + /* */ + /* */ + /* This function grid-fits several points in a given Type 1 builder */ + /* at once. */ + /* */ + /* */ + /* builder :: A handle to target Type 1 builder. */ + /* */ + LOCAL_FUNC + void T1_Hint_Points( T1_Builder* builder ) + { + FT_Int first = builder->hint_point; + FT_Int last = builder->current->n_points - 1; + + T1_Size size = builder->size; + FT_Fixed scale_x = size->root.metrics.x_scale; + FT_Fixed scale_y = size->root.metrics.y_scale; + + T1_Glyph_Hints* hints = builder->glyph->hints; + T1_Stem_Table* hori_stems = &hints->hori_stems; + T1_Stem_Table* vert_stems = &hints->vert_stems; + + FT_Vector* cur = builder->current->points + first; + FT_Vector* limit = cur + last - first + 1; + + + /* first of all, sort the active stem hints */ + t1_sort_hints( hori_stems ); + t1_sort_hints( vert_stems ); + + for ( ; cur < limit; cur++ ) + { + cur->x = t1_hint_point( vert_stems, cur->x, scale_x ); + cur->y = t1_hint_point( hori_stems, cur->y, scale_y ); + } + + builder->hint_point = builder->current->n_points; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Hint_Stems */ + /* */ + /* */ + /* This function is used to compute the location of each stem hint */ + /* between the first and second passes of the glyph loader on the */ + /* charstring. */ + /* */ + /* */ + /* builder :: A handle to the target builder. */ + /* */ + LOCAL_FUNC + void T1_Hint_Stems( T1_Builder* builder ) + { + T1_Glyph_Hints* hints = builder->glyph->hints; + T1_Private* priv = &builder->face->type1.private_dict; + + T1_Size size = builder->size; + FT_Fixed scale_x = size->root.metrics.x_scale; + FT_Fixed scale_y = size->root.metrics.y_scale; + + + t1_hint_horizontal_stems( &hints->hori_stems, + builder->size->hints, + priv->blue_shift, + scale_y ); + + t1_hint_vertical_stems( &hints->vert_stems, + builder->size->hints, + scale_x ); + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1hinter.h b/reactos/subsys/win32k/freetype/src/type1/t1hinter.h new file mode 100644 index 00000000000..a82882e097f --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1hinter.h @@ -0,0 +1,273 @@ +/***************************************************************************/ +/* */ +/* t1hinter.h */ +/* */ +/* Type 1 hinter (body). */ +/* */ +/* Copyright 1996-2000 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 T1HINTER_H +#define T1HINTER_H + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" +#include "t1gload.h" + +#else + +#include +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Snap_Zone */ + /* */ + /* */ + /* A `snap zone' is used to model either a blue zone or a stem width */ + /* at a given character size. It is made of a minimum and maximum */ + /* edge, defined in 26.6 pixels, as well as an `original' and */ + /* `scaled' position. */ + /* */ + /* The position corresponds to the stem width (for stem snap zones) */ + /* or to the blue position (for blue zones). */ + /* */ + /* */ + /* orus :: The original position in font units. */ + /* */ + /* pix :: The current position in sub-pixel units. */ + /* */ + /* min :: The minimum boundary in sub-pixel units. */ + /* */ + /* max :: The maximum boundary in sub-pixel units. */ + /* */ + typedef struct T1_Snap_Zone_ + { + FT_Pos orus; + FT_Pos pix; + FT_Pos min; + FT_Pos max; + + } T1_Snap_Zone; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Edge */ + /* */ + /* */ + /* A very simple structure used to model a stem edge. */ + /* */ + /* */ + /* orus :: The original edge position in font units. */ + /* */ + /* pix :: The scaled edge position in sub-pixel units. */ + /* */ + typedef struct T1_Edge_ + { + FT_Pos orus; + FT_Pos pix; + + } T1_Edge; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Stem_Hint */ + /* */ + /* */ + /* A simple structure used to model a stem hint. */ + /* */ + /* */ + /* min_edge :: The hint's minimum edge. */ + /* */ + /* max_edge :: The hint's maximum edge. */ + /* */ + /* hint_flags :: Some flags describing the stem properties. */ + /* */ + /* */ + /* The min and max edges of a ghost stem have the same position, even */ + /* if they are coded in a weird way in the charstrings. */ + /* */ + typedef struct T1_Stem_Hint_ + { + T1_Edge min_edge; + T1_Edge max_edge; + FT_Int hint_flags; + + } T1_Stem_Hint; + + +#define T1_HINT_FLAG_ACTIVE 1 /* indicates an active stem */ +#define T1_HINT_FLAG_MIN_BORDER 2 /* unused for now */ +#define T1_HINT_FLAG_MAX_BORDER 4 /* unused for now */ + + /* hinter's configuration constants */ +#define T1_HINTER_MAX_BLUES 24 /* maximum number of blue zones */ +#define T1_HINTER_MAX_SNAPS 16 /* maximum number of stem snap zones */ +#define T1_HINTER_MAX_EDGES 64 /* maximum number of stem hints */ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Size_Hints */ + /* */ + /* */ + /* A structure used to model the hinting information related to a size */ + /* object. */ + /* */ + /* */ + /* supress_overshoots :: A boolean flag to tell whether overshoot */ + /* supression should occur. */ + /* */ + /* num_blue_zones :: The total number of blue zones (top+bottom). */ + /* */ + /* num_bottom_zones :: The number of bottom zones. */ + /* */ + /* blue_zones :: The blue zones table. Bottom zones are */ + /* stored first in the table, followed by all */ + /* top zones. */ + /* */ + /* num_snap_widths :: The number of horizontal stem snap zones. */ + /* */ + /* snap_widths :: An array of horizontal stem snap zones. */ + /* */ + /* num_snap_heights :: The number of vertical stem snap zones. */ + /* */ + /* snap_heights :: An array of vertical stem snap zones. */ + /* */ + struct T1_Size_Hints_ + { + FT_Bool supress_overshoots; + + FT_Int num_blue_zones; + FT_Int num_bottom_zones; + T1_Snap_Zone blue_zones[T1_HINTER_MAX_BLUES]; + + FT_Int num_snap_widths; + T1_Snap_Zone snap_widths[T1_HINTER_MAX_SNAPS]; + + FT_Int num_snap_heights; + T1_Snap_Zone snap_heights[T1_HINTER_MAX_SNAPS]; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Stem_Table */ + /* */ + /* */ + /* A simple structure used to model a set of stem hints in a single */ + /* direction during the loading of a given glyph outline. Not all */ + /* stem hints are active at a time. Moreover, stems must be sorted */ + /* regularly. */ + /* */ + /* */ + /* num_stems :: The total number of stems in the table. */ + /* */ + /* num_active :: The number of active stems in the table. */ + /* */ + /* stems :: A table of all stems. */ + /* */ + /* sort :: A table of indices into the stems table, used to */ + /* keep a sorted list of the active stems. */ + /* */ + typedef struct T1_Stem_Table_ + { + FT_Int num_stems; + FT_Int num_active; + + T1_Stem_Hint stems[T1_HINTER_MAX_EDGES]; + FT_Int sort [T1_HINTER_MAX_EDGES]; + + } T1_Stem_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Glyph_Hints */ + /* */ + /* */ + /* A structure used to model the stem hints of a given glyph outline */ + /* during glyph loading. */ + /* */ + /* */ + /* hori_stems :: The horizontal stem hints table. */ + /* vert_stems :: The vertical stem hints table. */ + /* */ + struct T1_Glyph_Hints_ + { + T1_Stem_Table hori_stems; + T1_Stem_Table vert_stems; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hinter_funcs */ + /* */ + /* */ + /* A table containing the address of various functions used during */ + /* the loading of an hinted scaled outline. */ + /* */ + extern const T1_Hinter_Funcs t1_hinter_funcs; + + + LOCAL_DEF + FT_Error T1_New_Size_Hinter( T1_Size size ); + + LOCAL_DEF + void T1_Done_Size_Hinter( T1_Size size ); + + LOCAL_DEF + FT_Error T1_Reset_Size_Hinter( T1_Size size ); + + LOCAL_DEF + FT_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph ); + + LOCAL_DEF + void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph ); + + + LOCAL_DEF + void T1_Hint_Points( T1_Builder* builder ); + + LOCAL_DEF + void T1_Hint_Stems( T1_Builder* builder ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T1HINTER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1load.c b/reactos/subsys/win32k/freetype/src/type1/t1load.c new file mode 100644 index 00000000000..00a56a2463d --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1load.c @@ -0,0 +1,1594 @@ +/***************************************************************************/ +/* */ +/* t1load.c */ +/* */ +/* Type 1 font loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1tokens.h" +#include "t1parse.h" + +#else + +#include +#include + +#endif + + +#include + +#include /* for strncpy(), strncmp(), 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_t1load + + + typedef FT_Error (*T1_Parse_Func)( T1_Parser* parser ); + + + /*************************************************************************/ + /* */ + /* */ + /* Init_T1_Parser */ + /* */ + /* */ + /* Initializes a given parser object to build a given T1_Face. */ + /* */ + /* */ + /* parser :: A handle to the newly built parser object. */ + /* */ + /* */ + /* face :: A handle to the target Type 1 face object. */ + /* */ + /* tokenizer :: A handle to the target Type 1 token manager. */ + /* */ + LOCAL_FUNC + void Init_T1_Parser( T1_Parser* parser, + T1_Face face, + T1_Tokenizer tokenizer ) + { + parser->error = 0; + parser->face = face; + parser->tokenizer = tokenizer; + parser->top = parser->stack; + parser->limit = parser->stack + T1_MAX_STACK_DEPTH; + + parser->state_index = 0; + parser->state_stack[0] = dict_none; + + parser->encoding_type = t1_encoding_none; + parser->encoding_names = 0; + parser->encoding_offsets = 0; + parser->encoding_lengths = 0; + + parser->dump_tokens = 0; + face->type1.private_dict.lenIV = 4; /* XXX : is it sure? */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Next_T1_Token */ + /* */ + /* */ + /* Grabs the next significant token from a parser's input stream. */ + /* This function ignores a number of tokens, and translates */ + /* alternate forms into their common ones. */ + /* */ + /* */ + /* parser :: A handle to the source parser. */ + /* */ + /* */ + /* token :: The extracted token descriptor. */ + /* */ + /* */ + /* FreeTyoe error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Next_T1_Token( T1_Parser* parser, + T1_Token* token ) + { + FT_Error error; + T1_Tokenizer tokzer = parser->tokenizer; + + + L1: + error = Read_Token( tokzer ); + if ( error ) + return error; + + /* we now must ignore a number of tokens like `dup', `executeonly', */ + /* `readonly', etc. */ + *token = tokzer->token; + if ( token->kind == tok_keyword ) + switch( token->kind2 ) + { + case key_dup: + case key_execonly: + case key_readonly: + case key_noaccess: + case key_userdict: + /* do nothing - loop */ + goto L1; + + /* we also translate some other keywords from their alternative */ + /* to their `normal' form */ + + case key_NP_alternate: + token->kind2 = key_NP; + break; + + case key_RD_alternate: + token->kind2 = key_RD; + break; + + case key_ND_alternate: + token->kind2 = key_ND; + break; + + default: + ; + } + +#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE ) + + /* Dump the token when requested. This feature is only available */ + /* in the `error' and `trace' debug levels. */ + if ( parser->dump_tokens ) + { + FT_String temp_string[128]; + FT_Int len; + + + len = token->len; + if ( len > 127 ) + len = 127; + strncpy( temp_string, + (FT_String*)tokzer->base + token->start, + len ); + temp_string[len] = '\0'; + FT_ERROR(( "%s\n", temp_string )); + } + +#endif /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE */ + + return T1_Err_Ok; + } + + + static + FT_Error Expect_Keyword( T1_Parser* parser, + T1_TokenType keyword ) + { + T1_Token token; + FT_Error error; + + + error = Next_T1_Token( parser, &token ); + if ( error ) + goto Exit; + + if ( token.kind != tok_keyword || + token.kind2 != keyword ) + { + error = T1_Err_Syntax_Error; + FT_ERROR(( "Expect_Keyword: keyword `%s' expected.\n", + t1_keywords[keyword - key_first_] )); + } + + Exit: + return error; + } + + + static + FT_Error Expect_Keyword2( T1_Parser* parser, + T1_TokenType keyword1, + T1_TokenType keyword2 ) + { + T1_Token token; + FT_Error error; + + + error = Next_T1_Token( parser, &token ); + if ( error ) + goto Exit; + + if ( token.kind != tok_keyword || + ( token.kind2 != keyword1 && + token.kind2 != keyword2 ) ) + { + error = T1_Err_Syntax_Error; + FT_ERROR(( "Expect_Keyword2: keyword `%s' or `%s' expected.\n", + t1_keywords[keyword1 - key_first_], + t1_keywords[keyword2 - key_first_] )); + } + + Exit: + return error; + } + + + static + void Parse_Encoding( T1_Parser* parser ) + { + T1_Token* token = parser->top+1; + FT_Memory memory = parser->face->root.memory; + T1_Encoding* encode = &parser->face->type1.encoding; + FT_Error error = 0; + + + if ( token->kind == tok_keyword && + ( token->kind2 == key_StandardEncoding || + token->kind2 == key_ExpertEncoding ) ) + { + encode->num_chars = 256; + encode->code_first = 32; + encode->code_last = 255; + + if ( ALLOC_ARRAY( encode->char_index, 256, FT_Short ) ) + goto Exit; + + encode->char_name = 0; /* no need to store glyph names */ + + /* Now copy the encoding */ + switch ( token->kind2 ) + { + case key_ExpertEncoding: + parser->encoding_type = t1_encoding_expert; + break; + + default: + parser->encoding_type = t1_encoding_standard; + break; + } + } + else + { + FT_ERROR(( "Parse_Encoding: invalid encoding type\n" )); + error = T1_Err_Syntax_Error; + } + + Exit: + parser->error = error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* IMPLEMENTATION OF THE `DEF' KEYWORD DEPENDING ON */ + /* CURRENT DICTIONARY STATE */ + /* */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_Font */ + /* */ + /* */ + /* This function performs a `def' if in the Font dictionary. Its */ + /* purpose is to build the T1_Face attributes directly from the */ + /* stream. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_Font( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_Face face = parser->face; + T1_Font* type1 = &face->type1; + + + switch ( top[0].kind2 ) + { + case imm_FontName: + /* in some cases, the /FontName is an immediate like */ + /* /TimesNewRoman. In this case, we simply copy the */ + /* token string (without the /). */ + if ( top[1].kind == tok_immediate ) + { + FT_Memory memory = parser->tokenizer->memory; + FT_Error error; + FT_Int len = top[1].len; + + + if ( ALLOC( type1->font_name, len + 1 ) ) + { + parser->error = error; + return error; + } + + MEM_Copy( type1->font_name, + parser->tokenizer->base + top[1].start, + len ); + type1->font_name[len] = '\0'; + } + else + type1->font_name = CopyString( parser ); + break; + + case imm_Encoding: + Parse_Encoding( parser ); + break; + + case imm_PaintType: + type1->paint_type = (FT_Byte)CopyInteger( parser ); + break; + + case imm_FontType: + type1->font_type = (FT_Byte)CopyInteger( parser ); + break; + + case imm_FontMatrix: + CopyMatrix( parser, &type1->font_matrix ); + break; + + case imm_FontBBox: + CopyBBox( parser, &type1->font_bbox ); + break; + + case imm_UniqueID: + type1->private_dict.unique_id = CopyInteger( parser ); + break; + + case imm_StrokeWidth: + type1->stroke_width = CopyInteger( parser ); + break; + + case imm_FontID: + type1->font_id = CopyInteger( parser ); + break; + + default: + /* ignore all other things */ + parser->error = T1_Err_Ok; + } + + return parser->error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_FontInfo */ + /* */ + /* */ + /* This function performs a `def' if in the FontInfo dictionary. Its */ + /* purpose is to build the T1_FontInfo structure directly from the */ + /* stream. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeTyoe error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_FontInfo( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_FontInfo* info = &parser->face->type1.font_info; + + + switch ( top[0].kind2 ) + { + case imm_version: + info->version = CopyString( parser ); + break; + + case imm_Notice: + info->notice = CopyString( parser ); + break; + + case imm_FullName: + info->full_name = CopyString( parser ); + break; + + case imm_FamilyName: + info->family_name = CopyString( parser ); + break; + + case imm_Weight: + info->weight = CopyString( parser ); + break; + + case imm_ItalicAngle: + info->italic_angle = CopyInteger( parser ); + break; + + case imm_isFixedPitch: + info->is_fixed_pitch = CopyBoolean( parser ); + break; + + case imm_UnderlinePosition: + info->underline_position = (FT_Short)CopyInteger( parser ); + break; + + case imm_UnderlineThickness: + info->underline_thickness = (FT_Short)CopyInteger( parser ); + break; + + default: + /* ignore all other things */ + parser->error = T1_Err_Ok; + } + + return parser->error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_Private */ + /* */ + /* */ + /* This function performs a `def' if in the Private dictionary. Its */ + /* purpose is to build the T1_Private structure directly from the */ + /* stream. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeTyoe error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_Private( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_Private* priv = &parser->face->type1.private_dict; + + + switch ( top[0].kind2 ) + { + /* Ignore the definitions of RD, NP, ND, and their alternate forms */ + case imm_RD: + case imm_RD_alternate: + case imm_ND: + case imm_ND_alternate: + case imm_NP: + case imm_NP_alternate: + parser->error = T1_Err_Ok; + break; + + case imm_BlueValues: + CopyArray( parser, &priv->num_blue_values, + priv->blue_values, 14 ); + break; + + case imm_OtherBlues: + CopyArray( parser, &priv->num_other_blues, + priv->other_blues, 10 ); + break; + + case imm_FamilyBlues: + CopyArray( parser, &priv->num_family_blues, + priv->family_blues, 14 ); + break; + + case imm_FamilyOtherBlues: + CopyArray( parser, &priv->num_family_other_blues, + priv->family_other_blues, 10 ); + break; + + case imm_BlueScale: + priv->blue_scale = CopyFloat( parser, 0x10000L ); + break; + + case imm_BlueShift: + priv->blue_shift = CopyInteger( parser ); + break; + + case imm_BlueFuzz: + priv->blue_fuzz = CopyInteger( parser ); + break; + + case imm_StdHW: + CopyArray( parser, 0, (FT_Short*)&priv->standard_width, 1 ); + break; + + case imm_StdVW: + CopyArray( parser, 0, (FT_Short*)&priv->standard_height, 1 ); + break; + + case imm_StemSnapH: + CopyArray( parser, &priv->num_snap_widths, + priv->snap_widths, 12 ); + break; + + case imm_StemSnapV: + CopyArray( parser, &priv->num_snap_heights, + priv->snap_heights, 12 ); + break; + + case imm_ForceBold: + priv->force_bold = CopyBoolean( parser ); + break; + + case imm_LanguageGroup: + priv->language_group = CopyInteger( parser ); + break; + + case imm_password: + priv->password = CopyInteger( parser ); + break; + + case imm_UniqueID: + priv->unique_id = CopyInteger( parser ); + break; + + case imm_lenIV: + priv->lenIV = CopyInteger( parser ); + break; + + case imm_MinFeature: + CopyArray( parser, 0, priv->min_feature, 2 ); + break; + + default: + /* ignore all other things */ + parser->error = T1_Err_Ok; + } + + return parser->error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_Error */ + /* */ + /* */ + /* This function returns a simple syntax error when invoked. It is */ + /* used for the `def' keyword if in the `encoding', `subrs', */ + /* `othersubrs', and `charstrings' dictionary states. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_Error( T1_Parser* parser ) + { + FT_ERROR(( "Do_Def_Error:" )); + FT_ERROR(( " `def' keyword encountered in bad dictionary/array\n" )); + + parser->error = T1_Err_Syntax_Error; + + return parser->error; + } + + + static + FT_Error Do_Def_Ignore( T1_Parser* parser ) + { + FT_UNUSED( parser ); + return T1_Err_Ok; + } + + + static + T1_Parse_Func def_funcs[dict_max] = + { + Do_Def_Error, + Do_Def_Font, + Do_Def_FontInfo, + Do_Def_Ignore, + Do_Def_Private, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + }; + + + /*************************************************************************/ + /* */ + /* */ + /* IMPLEMENTATION OF THE `PUT' KEYWORD DEPENDING ON */ + /* CURRENT DICTIONARY STATE */ + /* */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Put_Encoding */ + /* */ + /* */ + /* This function performs a `put' if in the Encoding array. The */ + /* glyph name is copied into the T1 recorder, and the charcode and */ + /* glyph name pointer are written into the face object encoding. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_Put_Encoding( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Encoding* encode = &face->type1.encoding; + FT_Int index; + + + /* record and check the character code */ + if ( top[0].kind != tok_number ) + { + FT_TRACE4(( "Do_Put_Encoding: number expected\n" )); + goto Syntax_Error; + } + index = (FT_Int)CopyInteger( parser ); + if ( parser->error ) + return parser->error; + + if ( index < 0 || index >= encode->num_chars ) + { + FT_TRACE4(( "Do_Put_Encoding: invalid character code\n" )); + goto Syntax_Error; + } + + /* record the immediate name */ + if ( top[1].kind != tok_immediate ) + { + FT_TRACE4(( "Do_Put_Encoding: immediate name expected\n" )); + goto Syntax_Error; + } + + /* if the glyph name is `.notdef', store a NULL char name; */ + /* otherwise, record the glyph name */ + if ( top[1].kind == imm_notdef ) + { + parser->table.elements[index] = 0; + parser->table.lengths [index] = 0; + } + else + { + FT_String temp_name[128]; + T1_Token* token = top + 1; + FT_Int len = token->len - 1; + + + /* copy immediate name */ + if ( len > 127 ) + len = 127; + MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len ); + temp_name[len] = '\0'; + + error = T1_Add_Table( &parser->table, index, + (FT_Byte*)temp_name, len + 1 ); + + /* adjust code_first and code_last */ + if ( index < encode->code_first ) encode->code_first = index; + if ( index > encode->code_last ) encode->code_last = index; + } + return error; + + Syntax_Error: + /* ignore the error, and simply clear the stack */ + FT_TRACE4(( "Do_Put_Encoding: invalid syntax encountered\n" )); + parser->top = parser->stack; + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* IMPLEMENTATION OF THE "RD" KEYWORD DEPENDING ON */ + /* CURRENT DICTIONARY STATE */ + /* */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Do_RD_Subrs */ + /* */ + /* */ + /* This function performs an `RD' if in the Subrs dictionary. It */ + /* simply records the array of bytecodes/charstrings corresponding to */ + /* the sub-routine. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_RD_Subrs( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Tokenizer tokzer = parser->tokenizer; + FT_Int index, count; + + + /* record and check the character code */ + if ( top[0].kind != tok_number || + top[1].kind != tok_number ) + { + FT_ERROR(( "Do_RD_Subrs: number expected\n" )); + goto Syntax_Error; + } + index = (FT_Int)CopyInteger( parser ); + error = parser->error; + if ( error ) + goto Exit; + + count = (FT_Int)CopyInteger( parser ); + error = parser->error; + if ( error ) + goto Exit; + + if ( index < 0 || index >= face->type1.num_subrs ) + { + FT_ERROR(( "Do_RD_Subrs: invalid character code\n" )); + goto Syntax_Error; + } + + /* decrypt charstring and skip it */ + { + FT_Byte* base = tokzer->base + tokzer->cursor; + + + tokzer->cursor += count; + + /* 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 ) + { + t1_decrypt( base, count, 4330 ); + + base += face->type1.private_dict.lenIV; + count -= face->type1.private_dict.lenIV; + } + + error = T1_Add_Table( &parser->table, index, base, count ); + } + + /* consume the closing NP or `put' */ + error = Expect_Keyword2( parser, key_NP, key_put ); + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_RD_CharStrings */ + /* */ + /* */ + /* This function performs an `RD' if in the CharStrings dictionary. */ + /* It simply records the array of bytecodes/charstrings corresponding */ + /* to the glyph program string. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_RD_Charstrings( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Tokenizer tokzer = parser->tokenizer; + FT_Int index, count; + + + /* check the character name argument */ + if ( top[0].kind != tok_immediate ) + { + FT_ERROR(( "Do_RD_Charstrings: immediate character name expected\n" )); + goto Syntax_Error; + } + + /* check the count argument */ + if ( top[1].kind != tok_number ) + { + FT_ERROR(( "Do_RD_Charstrings: number expected\n" )); + goto Syntax_Error; + } + + parser->args++; + count = (FT_Int)CopyInteger( parser ); + error = parser->error; + if ( error ) + goto Exit; + + /* record the glyph name and get the corresponding glyph index */ + if ( top[0].kind2 == imm_notdef ) + index = 0; + else + { + FT_String temp_name[128]; + T1_Token* token = top; + FT_Int len = token->len - 1; + + + /* copy immediate name */ + if ( len > 127 ) + len = 127; + MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len ); + temp_name[len] = '\0'; + + index = parser->cur_name++; + error = T1_Add_Table( &parser->table, index * 2, + (FT_Byte*)temp_name, len + 1 ); + if ( error ) + goto Exit; + } + + /* decrypt and record charstring, then skip them */ + { + FT_Byte* base = tokzer->base + tokzer->cursor; + + + tokzer->cursor += count; /* skip */ + + if ( face->type1.private_dict.lenIV >= 0 ) + { + t1_decrypt( base, count, 4330 ); + + base += face->type1.private_dict.lenIV; + count -= face->type1.private_dict.lenIV; + } + + error = T1_Add_Table( &parser->table, index * 2 + 1, base, count ); + } + + /* consume the closing `ND' */ + if ( !error ) + error = Expect_Keyword( parser, key_ND ); + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + static + FT_Error Expect_Dict_Arguments( T1_Parser* parser, + FT_Int num_args, + T1_TokenType immediate, + T1_DictState new_state, + FT_Int* count ) + { + /* check that we have enough arguments in the stack, including */ + /* the `dict' keyword */ + if ( parser->top - parser->stack < num_args ) + { + FT_ERROR(( "Expect_Dict_Arguments: expecting at least %d arguments", + num_args )); + goto Syntax_Error; + } + + /* check that we have the correct immediate, if needed */ + if ( num_args == 2 ) + { + if ( parser->top[-2].kind != tok_immediate || + parser->top[-2].kind2 != immediate ) + { + FT_ERROR(( "Expect_Dict_Arguments: expecting `/%s' dictionary\n", + t1_immediates[immediate - imm_first_] )); + goto Syntax_Error; + } + } + + parser->args = parser->top-1; + + /* check that the count argument is a number */ + if ( parser->args->kind != tok_number ) + { + FT_ERROR(( "Expect_Dict_Arguments:" )); + FT_ERROR(( " expecting numerical count argument for `dict'\n" )); + goto Syntax_Error; + } + + if ( count ) + { + *count = CopyInteger( parser ); + if ( parser->error ) + return parser->error; + } + + /* save the dictionary state */ + parser->state_stack[++parser->state_index] = new_state; + + /* consume the `begin' keyword and clear the stack */ + parser->top -= num_args; + return Expect_Keyword( parser, key_begin ); + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + static + FT_Error Expect_Array_Arguments( T1_Parser* parser ) + { + T1_Token* top = parser->top; + FT_Error error = T1_Err_Ok; + T1_DictState new_state; + FT_Int count; + T1_Face face = parser->face; + FT_Memory memory = face->root.memory; + + + /* Check arguments format */ + if ( top - parser->stack < 2 ) + { + FT_ERROR(( "Expect_Array_Arguments: two arguments expected\n" )); + error = T1_Err_Stack_Underflow; + goto Exit; + } + + parser->top -= 2; + top -= 2; + parser->args = top + 1; + + if ( top[0].kind != tok_immediate ) + { + FT_ERROR(( "Expect_Array_Arguments:" )); + FT_ERROR(( " first argument must be an immediate name\n" )); + goto Syntax_Error; + } + + if ( top[1].kind != tok_number ) + { + FT_ERROR(( "Expect_Array_Arguments:" )); + FT_ERROR(( " second argument must be a number\n" )); + goto Syntax_Error; + } + + count = (FT_Int)CopyInteger( parser ); + + /* Is this an array we know about? */ + switch ( top[0].kind2 ) + { + case imm_Encoding: + { + T1_Encoding* encode = &face->type1.encoding; + + + new_state = dict_encoding; + + encode->code_first = count; + encode->code_last = 0; + encode->num_chars = count; + + /* Allocate the table of character indices. The table of */ + /* character names is allocated through init_t1_recorder(). */ + if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) ) + return error; + + error = T1_New_Table( &parser->table, count, memory ); + if ( error ) + goto Exit; + + parser->encoding_type = t1_encoding_array; + } + break; + + case imm_Subrs: + new_state = dict_subrs; + face->type1.num_subrs = count; + + error = T1_New_Table( &parser->table, count, memory ); + if ( error ) + goto Exit; + break; + + case imm_CharStrings: + new_state = dict_charstrings; + break; + + default: + new_state = dict_unknown_array; + } + + parser->state_stack[++parser->state_index] = new_state; + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + static + FT_Error Finalize_Parsing( T1_Parser* parser ) + { + T1_Face face = parser->face; + T1_Font* type1 = &face->type1; + FT_Memory memory = face->root.memory; + T1_Table* strings = &parser->table; + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; + + FT_Int num_glyphs; + FT_Int n; + FT_Error error; + + + num_glyphs = type1->num_glyphs = parser->cur_name; + + /* allocate glyph names and charstrings arrays */ + if ( ALLOC_ARRAY( type1->glyph_names, num_glyphs, FT_String* ) || + ALLOC_ARRAY( type1->charstrings, num_glyphs, FT_Byte* ) || + ALLOC_ARRAY( type1->charstrings_len, num_glyphs, FT_Int* ) ) + return error; + + /* copy glyph names and charstrings offsets and lengths */ + type1->charstrings_block = strings->block; + for ( n = 0; n < num_glyphs; n++ ) + { + type1->glyph_names[n] = (FT_String*)strings->elements[2 * n]; + type1->charstrings[n] = strings->elements[2 * n + 1]; + type1->charstrings_len[n] = strings->lengths [2 * n + 1]; + } + + /* now free the old tables */ + FREE( strings->elements ); + FREE( strings->lengths ); + + if ( !psnames ) + { + FT_ERROR(( "Finalize_Parsing: `PSNames' module missing!\n" )); + return T1_Err_Unimplemented_Feature; + } + + /* compute encoding if required */ + if ( parser->encoding_type == t1_encoding_none ) + { + FT_ERROR(( "Finalize_Parsing: no encoding specified in font file\n" )); + return T1_Err_Syntax_Error; + } + + { + FT_Int n; + T1_Encoding* encode = &type1->encoding; + + + encode->code_first = encode->num_chars - 1; + encode->code_last = 0; + + for ( n = 0; n < encode->num_chars; n++ ) + { + FT_String** names; + FT_Int index; + FT_Int m; + + + switch ( parser->encoding_type ) + { + case t1_encoding_standard: + index = psnames->adobe_std_encoding[n]; + names = 0; + break; + + case t1_encoding_expert: + index = psnames->adobe_expert_encoding[n]; + names = 0; + break; + + default: + index = n; + names = (FT_String**)parser->encoding_offsets; + } + + encode->char_index[n] = 0; + + if ( index ) + { + FT_String* name; + + + if ( names ) + name = names[index]; + else + name = (FT_String*)psnames->adobe_std_strings(index); + + if ( name ) + { + FT_Int len = strlen( name ); + + + /* lookup glyph index from name */ + for ( m = 0; m < num_glyphs; m++ ) + { + if ( strncmp( type1->glyph_names[m], name, len ) == 0 ) + { + encode->char_index[n] = m; + break; + } + } + + if ( n < encode->code_first ) encode->code_first = n; + if ( n > encode->code_last ) encode->code_last = n; + } + } + } + + parser->encoding_type = t1_encoding_none; + + FREE( parser->encoding_names ); + FREE( parser->encoding_lengths ); + FREE( parser->encoding_offsets ); + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Parse_T1_FontProgram */ + /* */ + /* */ + /* Parses a given Type 1 font file and builds its face object. */ + /* */ + /* */ + /* parser :: A handle to the target parser object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The parser contains a handle to the target face object. */ + /* */ + LOCAL_FUNC + FT_Error Parse_T1_FontProgram( T1_Parser* parser ) + { + FT_Error error; + T1_Font* type1 = &parser->face->type1; + + + for (;;) + { + T1_Token token; + T1_Token* top; + T1_DictState dict_state; + FT_Int dict_index; + + + error = Next_T1_Token( parser, &token ); + top = parser->top; + dict_index = parser->state_index; + dict_state = parser->state_stack[dict_index]; + + switch ( token.kind ) + { + /* a keyword has been detected */ + case tok_keyword: + switch ( token.kind2 ) + { + case key_dict: + switch ( dict_state ) + { + case dict_none: + /* All right, we are beginning the font dictionary. */ + /* Check that we only have one number argument, then */ + /* consume the `begin' and change to `dict_font' */ + /* state. */ + error = Expect_Dict_Arguments( parser, 1, tok_error, + dict_font, 0 ); + if ( error ) + goto Exit; + + /* clear stack from all the previous content. This */ + /* could be some stupid Postscript code. */ + parser->top = parser->stack; + break; + + case dict_font: + /* This must be the /FontInfo dictionary, so check */ + /* that we have at least two arguments, that they */ + /* are `/FontInfo' and a number, then change the */ + /* dictionary state. */ + error = Expect_Dict_Arguments( parser, 2, imm_FontInfo, + dict_fontinfo, 0 ); + if ( error ) + goto Exit; + break; + + case dict_none2: + error = Expect_Dict_Arguments( parser, 2, imm_Private, + dict_private, 0 ); + if ( error ) + goto Exit; + break; + + case dict_private: + { + T1_Face face = parser->face; + FT_Int count; + + + error = Expect_Dict_Arguments( parser, 2, imm_CharStrings, + dict_charstrings, &count ); + if ( error ) + goto Exit; + + type1->num_glyphs = count; + error = T1_New_Table( &parser->table, count * 2, + face->root.memory ); + if ( error ) + goto Exit; + + /* record `.notdef' as the first glyph in the font */ + error = T1_Add_Table( &parser->table, 0, + (FT_Byte*)".notdef", 8 ); + parser->cur_name = 1; + /* XXX: DO SOMETHING HERE */ + } + break; + + default: + /* All other uses are invalid */ + FT_ERROR(( "Parse_T1_FontProgram:" )); + FT_ERROR(( " invalid use of `dict' keyword\n" )); + goto Syntax_Error; + } + break; + + case key_array: + /* Are we in an array yet? If so, raise an error */ + switch ( dict_state ) + { + case dict_encoding: + case dict_subrs: + case dict_othersubrs: + case dict_charstrings: + case dict_unknown_array: + FT_ERROR(( "Parse_T1_FontProgram: nested array definitions\n" )); + goto Syntax_Error; + + default: + ; + } + error = Expect_Array_Arguments( parser ); + if ( error ) + goto Exit; + break; + + case key_ND: + case key_NP: + case key_def: + /* Are we in an array? If so, finalize it. */ + switch ( dict_state ) + { + case dict_encoding: /* finish encoding array */ + /* copy table names to the face object */ + T1_Done_Table( &parser->table ); + + parser->encoding_names = parser->table.block; + parser->encoding_lengths = parser->table.lengths; + parser->encoding_offsets = parser->table.elements; + + parser->state_index--; + break; + + case dict_subrs: + /* copy recorder sub-routines */ + T1_Done_Table( &parser->table ); + + parser->subrs = parser->table.block; + type1->subrs = parser->table.elements; + type1->subrs_len = parser->table.lengths; + type1->subrs_block = parser->table.block; + + parser->state_index--; + break; + + case dict_charstrings: + case dict_othersubrs: + case dict_unknown_array: + FT_ERROR(( "Parse_T1_FontProgram: unsupported array\n" )); + goto Syntax_Error; + break; + + default: /* normal `def' processing */ + /* Check that we have sufficient operands in the stack */ + if ( top >= parser->stack + 2 ) + { + /* Now check that the first operand is an immediate. */ + /* If so, call the appropriate `def' routine based */ + /* on the current parser state. */ + if ( top[-2].kind == tok_immediate ) + { + parser->top -= 2; + parser->args = parser->top + 1; + error = def_funcs[dict_state](parser); + } + else + { + /* This is an error, but some fonts contain */ + /* stupid Postscript code. We simply ignore */ + /* an invalid `def' by clearing the stack. */ +#if 0 + FT_ERROR(( "Parse_T1_FontProgram: immediate expected\n" )); + goto Syntax_Error; +#else + parser->top = parser->stack; +#endif + } + } + else + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + } + break; + + case key_index: + if ( top <= parser->stack ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + /* simply ignore? */ + parser->top --; + break; + + case key_put: + /* Check that we have sufficient operands in stack */ + if ( top < parser->stack + 2 ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + parser->top -= 2; + parser->args = parser->top; + + switch ( dict_state ) + { + case dict_encoding: + error = Do_Put_Encoding( parser ); + if ( error ) + goto Exit; + break; + + case dict_unknown_array: /* ignore the `put' */ + break; + + default: +#if 0 + FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" )); + goto Syntax_Error; +#else + /* invalid context; simply ignore the `put' and */ + /* clear the stack (stupid Postscript code) */ + FT_TRACE4(( "Parse_T1_FontProgram: invalid context ignored.\n" )); + parser->top = parser->stack; +#endif + } + break; + + case key_RD: + /* Check that we have sufficient operands in stack */ + if ( top < parser->stack + 2 ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + parser->top -= 2; + parser->args = parser->top; + switch ( dict_state ) + { + case dict_subrs: + error = Do_RD_Subrs( parser ); + if ( error ) + goto Exit; + break; + + case dict_charstrings: + error = Do_RD_Charstrings( parser ); + if ( error ) + goto Exit; + break; + + default: + FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" )); + goto Syntax_Error; + } + break; + + case key_end: + /* Were we in a dictionary or in an array? */ + if ( dict_index <= 0 ) + { + FT_ERROR(( "Parse_T1_FontProgram: no dictionary defined\n" )); + goto Syntax_Error; + } + + switch ( dict_state ) + { + /* jump to the private dictionary if we are closing the */ + /* `/Font' dictionary */ + case dict_font: + goto Open_Private; + + /* exit the parser when closing the CharStrings dictionary */ + case dict_charstrings: + return Finalize_Parsing( parser ); + + default: + /* Pop the current dictionary state and return to previous */ + /* one. Consume the `def'. */ + + /* Because some buggy fonts (BitStream) have incorrect */ + /* syntax, we never escape from the private dictionary */ + if ( dict_state != dict_private ) + parser->state_index--; + + /* many fonts use `NP' instead of `def' or `put', so */ + /* we simply ignore the next token */ +#if 0 + error = Expect_Keyword2( parser, key_def, key_put ); + if ( error ) + goto Exit; +#else + (void)Expect_Keyword2( parser, key_def, key_put ); +#endif + } + break; + + case key_for: + /* check that we have four arguments and simply */ + /* ignore them */ + if ( top - parser->stack < 4 ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + parser->top -= 4; + break; + + case key_currentdict: + Open_Private: + parser->state_index = 0; + parser->state_stack[0] = dict_none2; + error = Open_PrivateDict( parser->tokenizer ); + if ( error ) + goto Exit; + break; + + case key_true: + case key_false: + case key_StandardEncoding: + case key_ExpertEncoding: + goto Push_Element; + + default: + FT_ERROR(( "Parse_T1_FontProgram:" )); + FT_ERROR(( " invalid keyword in context\n" )); + error = T1_Err_Syntax_Error; + } + break; + + /* check for the presence of `/BlendAxisTypes' -- we cannot deal */ + /* with multiple master fonts, so we must return a correct error */ + /* code to allow another driver to load them */ + case tok_immediate: + if ( token.kind2 == imm_BlendAxisTypes ) + { + error = FT_Err_Unknown_File_Format; + goto Exit; + } + /* fallthrough */ + + /* A number was detected */ + case tok_string: + case tok_program: + case tok_array: + case tok_hexarray: + case tok_any: + case tok_number: /* push number on stack */ + + Push_Element: + if ( top >= parser->limit ) + { + error = T1_Err_Stack_Overflow; + goto Exit; + } + else + *parser->top++ = token; + break; + + /* anything else is an error per se the spec, but we */ + /* frequently encounter stupid postscript code in fonts, */ + /* so just ignore them */ + default: + error = T1_Err_Ok; /* ignore token */ + } + + if ( error ) + return error; + } + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1load.h b/reactos/subsys/win32k/freetype/src/type1/t1load.h new file mode 100644 index 00000000000..d278374f0f8 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1load.h @@ -0,0 +1,57 @@ +/***************************************************************************/ +/* */ +/* t1load.h */ +/* */ +/* Type 1 font loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "t1parse.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + LOCAL_DEF + void Init_T1_Parser( T1_Parser* parser, + T1_Face face, + T1_Tokenizer tokenizer ); + + + LOCAL_DEF + FT_Error Parse_T1_FontProgram( T1_Parser* parser ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1LOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1objs.c b/reactos/subsys/win32k/freetype/src/type1/t1objs.c new file mode 100644 index 00000000000..1e6f9ca2a31 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1objs.c @@ -0,0 +1,544 @@ +/***************************************************************************/ +/* */ +/* t1objs.c */ +/* */ +/* Type 1 objects manager (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1gload.h" +#include "t1load.h" +#include "t1afm.h" + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include "t1hinter.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* SIZE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Size */ + /* */ + /* */ + /* The Type 1 size object destructor. Used to discard a given size */ + /* object. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_FUNC + void T1_Done_Size( T1_Size size ) + { + if ( size ) + { + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + T1_Done_Size_Hinter( size ); +#endif + + size->valid = 0; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Size */ + /* */ + /* */ + /* The size object initializer. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeTrue error code. 0 means success. */ + /* */ + LOCAL_DEF + FT_Error T1_Init_Size( T1_Size size ) + { + FT_Error error; + + + size->valid = 0; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + error = T1_New_Size_Hinter( size ); + + return error; +#else + + FT_UNUSED( error ); + + return T1_Err_Ok; + +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Reset_Size */ + /* */ + /* */ + /* Resets an instance to a new pointsize/transform. This function is */ + /* in charge of resetting the blue zones,a s well as the stem snap */ + /* tables for a given size. */ + /* */ + /* */ + /* size :: The target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Reset_Size( T1_Size size ) + { + /* recompute ascender, descender, etc. */ + T1_Face face = (T1_Face)size->root.face; + FT_Size_Metrics* metrics = &size->root.metrics; + + + if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) + return FT_Err_Invalid_Argument; + + /* 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; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + return T1_Reset_Size_Hinter( size ); +#else + return 0; +#endif + } + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Face */ + /* */ + /* */ + /* The face object destructor. */ + /* */ + /* */ + /* face :: A typeless pointer to the face object to destroy. */ + /* */ + LOCAL_FUNC + void T1_Done_Face( T1_Face face ) + { + FT_Memory memory; + T1_Font* type1 = &face->type1; + + + if ( face ) + { + memory = face->root.memory; + + /* 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->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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Face */ + /* */ + /* */ + /* The face object constructor. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: The face record to build. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Init_Face( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + T1_Tokenizer tokenizer; + FT_Error error; + PSNames_Interface* psnames; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + FT_UNUSED( face ); + + + 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; + } + + /* open the tokenizer, this will also check the font format */ + error = New_Tokenizer( stream, &tokenizer ); + if ( error ) + goto Fail; + + /* if we just wanted to check the format, leave successfully now */ + if ( face_index < 0 ) + goto Leave; + + /* check the face index */ + if ( face_index != 0 ) + { + FT_ERROR(( "T1_Init_Face: invalid face index\n" )); + error = T1_Err_Invalid_Argument; + goto Leave; + } + + /* Now, load the font program into the face object */ + { + T1_Parser parser; + + + Init_T1_Parser( &parser, face, tokenizer ); + error = Parse_T1_FontProgram( &parser ); + if ( error ) + goto Leave; + + /* Init the face object fields */ + /* Now set up root face fields */ + { + FT_Face root = (FT_Face)&face->root; + T1_Font* type1 = &face->type1; + + + root->num_glyphs = 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 ( type1->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 = type1->font_info.family_name; + if ( root->family_name ) + { + char* full = 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 (type1->font_name) + { + root->family_name = type1->font_name; + root->style_name = "Regular"; + } + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox = type1->font_bbox; + root->units_per_EM = 1000; + root->ascender = (FT_Short)type1->font_bbox.yMax; + root->descender = -(FT_Short)type1->font_bbox.yMin; + root->height = ( ( root->ascender + root->descender) * 12 ) + / 10; + + /* now compute the maximum advance width */ + + root->max_advance_width = type1->private_dict.standard_width[0]; + + /* compute max advance width for proportional fonts */ + if ( !type1->font_info.is_fixed_pitch ) + { + 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 = max_advance; + else + error = 0; /* clear error */ + } + + root->max_advance_height = root->height; + + root->underline_position = type1->font_info.underline_position; + root->underline_thickness = type1->font_info.underline_thickness; + + root->max_points = 0; + root->max_contours = 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]; + } + + Leave: + Done_Tokenizer( tokenizer ); + + Fail: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_GlyphSlot */ + /* */ + /* */ + /* The glyph slot object destructor. */ + /* */ + /* */ + /* glyph :: The glyph slot handle to destroy. */ + /* */ + LOCAL_FUNC + void T1_Done_GlyphSlot( T1_GlyphSlot glyph ) + { +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + T1_Done_Glyph_Hinter( glyph ); + +#else + + FT_UNUSED( glyph ); + +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_GlyphSlot */ + /* */ + /* */ + /* The glyph slot object constructor. */ + /* */ + /* */ + /* glyph :: The glyph slot handle to initialize. */ + /* */ + LOCAL_FUNC + FT_Error T1_Init_GlyphSlot( T1_GlyphSlot glyph ) + { + FT_Error error = FT_Err_Ok; + + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + error = T1_New_Glyph_Hinter( glyph ); + +#else + + FT_UNUSED( glyph ); + +#endif + + return error; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1objs.h b/reactos/subsys/win32k/freetype/src/type1/t1objs.h new file mode 100644 index 00000000000..47b0a37be1c --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1objs.h @@ -0,0 +1,172 @@ +/***************************************************************************/ +/* */ +/* t1objs.h */ +/* */ +/* Type 1 objects manager (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Driver */ + /* */ + /* */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct T1_DriverRec_* T1_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Size */ + /* */ + /* */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct T1_SizeRec_* T1_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_GlyphSlot */ + /* */ + /* */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct T1_GlyphSlotRec_* T1_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_CharMap */ + /* */ + /* */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* */ + /* 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 */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_SizeRec */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_GlyphSlotRec */ + /* */ + /* */ + /* 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; + + + LOCAL_DEF + FT_Error T1_Init_Face( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void T1_Done_Face( T1_Face face ); + + LOCAL_DEF + FT_Error T1_Init_Size( T1_Size size ); + + LOCAL_DEF + void T1_Done_Size( T1_Size size ); + + LOCAL_DEF + FT_Error T1_Reset_Size( T1_Size size ); + + LOCAL_DEF + FT_Error T1_Init_GlyphSlot( T1_GlyphSlot slot ); + + LOCAL_DEF + void T1_Done_GlyphSlot( T1_GlyphSlot slot ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1OBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1parse.c b/reactos/subsys/win32k/freetype/src/type1/t1parse.c new file mode 100644 index 00000000000..8b7ca252457 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1parse.c @@ -0,0 +1,761 @@ +/***************************************************************************/ +/* */ +/* t1parse.c */ +/* */ +/* Type 1 parser (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1parse.h" + +#else + +#include + +#endif + + +#include /* for sscanf() */ +#include /* for strncpy() */ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_New_Table */ + /* */ + /* */ + /* Initializes a T1_Table structure. */ + /* */ + /* */ + /* table :: The address of the target table. */ + /* */ + /* */ + /* count :: The table size (i.e. maximum number of elements). */ + /* memory :: The memory object to use for all subsequent */ + /* reallocations. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_New_Table( T1_Table* table, + FT_Int count, + FT_Memory memory ) + { + FT_Error error; + + + table->memory = memory; + + if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) ) + return error; + + if ( ALLOC_ARRAY( table->lengths, count, FT_Byte* ) ) + { + FREE( table->elements ); + return error; + } + + table->max_elems = count; + table->num_elems = 0; + + table->block = 0; + table->capacity = 0; + table->cursor = 0; + + return error; + } + + + static + FT_Error reallocate_t1_table( T1_Table* table, + FT_Int new_size ) + { + FT_Memory memory = table->memory; + FT_Byte* old_base = table->block; + FT_Error error; + + + /* reallocate the base block */ + if ( REALLOC( table->block, table->capacity, new_size ) ) + return error; + table->capacity = new_size; + + /* shift all offsets if necessary */ + if ( old_base ) + { + FT_Long delta = table->block - old_base; + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + if ( delta ) + for ( ; offset < limit; offset ++ ) + if (offset[0]) + offset[0] += delta; + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Add_Table */ + /* */ + /* */ + /* Adds an object to a T1_Table, possibly growing its memory block. */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. An error is returned if a */ + /* reallocation failed. */ + /* */ + LOCAL_FUNC + FT_Error T1_Add_Table( T1_Table* table, + FT_Int index, + void* object, + FT_Int length ) + { + if ( index < 0 || index > table->max_elems ) + { + FT_ERROR(( "T1_Add_Table: invalid index\n" )); + return T1_Err_Syntax_Error; + } + + /* grow the base block if needed */ + if ( table->cursor + length > table->capacity ) + { + FT_Error error; + FT_Int new_size = table->capacity; + + + while ( new_size < table->cursor + length ) + new_size += 1024; + + error = reallocate_t1_table( table, new_size ); + if ( error ) + return error; + } + + /* 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 T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Table */ + /* */ + /* */ + /* Finalize a T1_Table (reallocate it to its current cursor). */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* 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. */ + /* */ + LOCAL_FUNC + void T1_Done_Table( T1_Table* table ) + { + FT_Memory memory = table->memory; + FT_Error error; + FT_Byte* old_base; + + + /* should never fail, as rec.cursor <= rec.size */ + old_base = table->block; + if ( !old_base ) + return; + + (void)REALLOC( table->block, table->capacity, table->cursor ); + table->capacity = table->cursor; + + if ( old_base != table->block ) + { + FT_Long delta = table->block - old_base; + FT_Byte** element = table->elements; + FT_Byte** limit = element + table->max_elems; + + + for ( ; element < limit; element++ ) + if ( element[0] ) + element[0] += delta; + } + } + + + LOCAL_FUNC + FT_String* CopyString( T1_Parser* parser ) + { + FT_String* string = NULL; + T1_Token* token = parser->args++; + FT_Memory memory = parser->tokenizer->memory; + FT_Error error; + + + if ( token->kind == tok_string ) + { + FT_Int len = token->len - 2; + + + if ( ALLOC( string, len + 1 ) ) + { + parser->error = error; + return 0; + } + + MEM_Copy( string, parser->tokenizer->base + token->start + 1, len ); + string[len] = '\0'; + + parser->error = T1_Err_Ok; + } + else + { + FT_ERROR(( "T1_CopyString: syntax error, string token expected!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + return string; + } + + + static + FT_Error parse_int( FT_Byte* base, + FT_Byte* limit, + FT_Long* result ) + { + FT_Bool sign = 0; + FT_Long sum = 0; + + + if ( base >= limit ) + goto Fail; + + /* check sign */ + if ( *base == '+' ) + base++; + + else if ( *base == '-' ) + { + sign++; + base++; + } + + /* parse digits */ + if ( base >= limit ) + goto Fail; + + do + { + sum = ( 10 * sum + ( *base++ - '0' ) ); + + } while ( base < limit ); + + if ( sign ) + sum = -sum; + + *result = sum; + return T1_Err_Ok; + + Fail: + FT_ERROR(( "parse_int: integer expected\n" )); + *result = 0; + return T1_Err_Syntax_Error; + } + + + static + FT_Error parse_float( FT_Byte* base, + FT_Byte* limit, + FT_Long scale, + FT_Long* result ) + { +#if 1 + + /* XXX: We are simply much too lazy to code this function */ + /* properly for now. We will do that when the rest of */ + /* the driver works properly. */ + char temp[32]; + int len = limit - base; + double value; + + + if ( len > 31 ) + goto Fail; + + strncpy( temp, (char*)base, len ); + temp[len] = '\0'; + if ( sscanf( temp, "%lf", &value ) != 1 ) + goto Fail; + + *result = (FT_Long)( scale * value ); + return 0; + +#else + + FT_Byte* cur; + FT_Bool sign = 0; /* sign */ + FT_Long number_int = 0; /* integer part */ + FT_Long number_frac = 0; /* fractional part */ + FT_Long exponent = 0; /* exponent value */ + FT_Int num_frac = 0; /* number of fractional digits */ + + + /* check sign */ + if ( *base == '+' ) + base++; + + else if ( *base == '-' ) + { + sign++; + base++; + } + + /* find integer part */ + cur = base; + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( c == '.' || c == 'e' || c == 'E' ) + break; + + cur++; + } + + if ( cur > base ) + { + error = parse_integer( base, cur, &number_int ); + if ( error ) + goto Fail; + } + + /* read fractional part, if any */ + if ( *cur == '.' ) + { + cur++; + base = cur; + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( c == 'e' || c == 'E' ) + break; + cur++; + } + + num_frac = cur - base; + + if ( cur > base ) + { + error = parse_integer( base, cur, &number_frac ); + if ( error ) + goto Fail; + base = cur; + } + } + + /* read exponent, if any */ + if ( *cur == 'e' || *cur == 'E' ) + { + cur++; + base = cur; + error = parse_integer( base, limit, &exponent ); + if ( error ) + goto Fail; + + /* now check that exponent is within `correct bounds' */ + /* i.e. between -6 and 6 */ + if ( exponent < -6 || exponent > 6 ) + goto Fail; + } + + /* now adjust integer value and exponent for fractional part */ + while ( num_frac > 0 ) + { + number_int *= 10; + exponent--; + num_frac--; + } + + number_int += num_frac; + + /* skip point if any, read fractional part */ + if ( cur + 1 < limit ) + { + if (*cur.. + } + + /* now compute scaled float value */ + /* XXX: incomplete! */ + +#endif /* 1 */ + + Fail: + FT_ERROR(( "parse_float: syntax error!\n" )); + return T1_Err_Syntax_Error; + } + + + static + FT_Error parse_integer( FT_Byte* base, + FT_Byte* limit, + FT_Long* result ) + { + FT_Byte* cur; + + + /* the lexical analyser accepts floats as well as integers */ + /* now; check that we really have an int in this token */ + cur = base; + while ( cur < limit ) + { + FT_Byte c = *cur++; + + + if ( c == '.' || c == 'e' || c == 'E' ) + goto Float_Number; + } + + /* now read the number's value */ + return parse_int( base, limit, result ); + + Float_Number: + /* we really have a float there; simply call parse_float in this */ + /* case with a scale of `10' to perform round */ + { + FT_Error error; + + + error = parse_float( base, limit, 10, result ); + if ( !error ) + { + if ( *result >= 0 ) + *result = ( *result + 5 ) / 10; /* round value */ + else + *result = -( ( 5 - *result ) / 10 ); + } + return error; + } + } + + + LOCAL_FUNC + FT_Long CopyInteger( T1_Parser* parser ) + { + FT_Long sum = 0; + T1_Token* token = parser->args++; + + + if ( token->kind == tok_number ) + { + FT_Byte* base = parser->tokenizer->base + token->start; + FT_Byte* limit = base + token->len; + + + /* now read the number's value */ + parser->error = parse_integer( base, limit, &sum ); + return sum; + } + + FT_ERROR(( "CopyInteger: number expected\n" )); + parser->args--; + parser->error = T1_Err_Syntax_Error; + return 0; + } + + + LOCAL_FUNC + FT_Bool CopyBoolean( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + FT_Bool result = 0; + T1_Token* token = parser->args++; + + + if ( token->kind == tok_keyword ) + { + if ( token->kind2 == key_false ) + result = 0; + + else if ( token->kind2 == key_true ) + result = !0; + + else + goto Fail; + } + else + { + Fail: + FT_ERROR(( "CopyBoolean:" )); + FT_ERROR(( " syntax error; `false' or `true' expected\n" )); + error = T1_Err_Syntax_Error; + } + parser->error = error; + return result; + } + + + LOCAL_FUNC + FT_Long CopyFloat( T1_Parser* parser, + FT_Int scale ) + { + FT_Error error; + FT_Long sum = 0; + T1_Token* token = parser->args++; + + + if ( token->kind == tok_number ) + { + FT_Byte* base = parser->tokenizer->base + token->start; + FT_Byte* limit = base + token->len; + + + error = parser->error = parse_float( base, limit, scale, &sum ); + if ( error ) + goto Fail; + + return sum; + } + + Fail: + FT_ERROR(( "CopyFloat: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + return 0; + } + + + LOCAL_FUNC + void CopyBBox( T1_Parser* parser, + FT_BBox* bbox ) + { + T1_Token* token = parser->args++; + FT_Int n; + FT_Error error; + + + if ( token->kind == tok_program || + token->kind == tok_array ) + { + /* get rid of `['/`]', or `{'/`}' */ + FT_Byte* base = parser->tokenizer->base + token->start + 1; + FT_Byte* limit = base + token->len - 2; + FT_Byte* cur; + FT_Byte* start; + + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < 4; n++ ) + { + FT_Long* result; + + + /* skip whitespace */ + while ( cur < limit && *cur == ' ' ) + cur++; + + /* skip numbers */ + start = cur; + while ( cur < limit && *cur != ' ' ) + cur++; + + /* compute result address */ + switch ( n ) + { + case 0: + result = &bbox->xMin; + break; + case 1: + result = &bbox->yMin; + break; + case 2: + result = &bbox->xMax; + break; + default: + result = &bbox->yMax; + } + + error = parse_integer( start, cur, result ); + if ( error ) + goto Fail; + } + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "CopyBBox: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + + LOCAL_FUNC + void CopyMatrix( T1_Parser* parser, + FT_Matrix* matrix ) + { + T1_Token* token = parser->args++; + FT_Error error; + + + if ( token->kind == tok_array ) + { + /* get rid of `[' and `]' */ + FT_Byte* base = parser->tokenizer->base + token->start + 1; + FT_Byte* limit = base + token->len - 2; + FT_Byte* cur; + FT_Byte* start; + FT_Int n; + + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < 4; n++ ) + { + FT_Long* result; + + + /* skip whitespace */ + while ( cur < limit && *cur == ' ' ) + cur++; + + /* skip numbers */ + start = cur; + while ( cur < limit && *cur != ' ') + cur++; + + /* compute result address */ + switch ( n ) + { + case 0: + result = &matrix->xx; + break; + case 1: + result = &matrix->yx; + break; + case 2: + result = &matrix->xy; + break; + default: + result = &matrix->yy; + } + + error = parse_float( start, cur, 65536000L, result ); + if ( error ) + goto Fail; + } + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "CopyMatrix: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + + LOCAL_FUNC + void CopyArray( T1_Parser* parser, + FT_Byte* num_elements, + FT_Short* elements, + FT_Int max_elements ) + { + T1_Token* token = parser->args++; + FT_Error error; + + + if ( token->kind == tok_array || + token->kind == tok_program ) /* in the case of MinFeature */ + { + /* get rid of `['/`]', or `{'/`}' */ + FT_Byte* base = parser->tokenizer->base + token->start + 1; + FT_Byte* limit = base + token->len - 2; + FT_Byte* cur; + FT_Byte* start; + FT_Int n; + + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < max_elements; n++ ) + { + FT_Long result; + + + /* test end of string */ + if ( cur >= limit ) + break; + + /* skip whitespace */ + while ( cur < limit && *cur == ' ' ) + cur++; + + /* end of list? */ + if ( cur >= limit ) + break; + + /* skip numbers */ + start = cur; + while ( cur < limit && *cur != ' ' ) + cur++; + + error = parse_integer( start, cur, &result ); + if ( error ) + goto Fail; + + *elements++ = (FT_Short)result; + } + + if ( num_elements ) + *num_elements = (FT_Byte)n; + + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "CopyArray: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1parse.h b/reactos/subsys/win32k/freetype/src/type1/t1parse.h new file mode 100644 index 00000000000..2c42b8cec4b --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1parse.h @@ -0,0 +1,261 @@ +/***************************************************************************/ +/* */ +/* t1parse.h */ +/* */ +/* Type 1 parser (specification). */ +/* */ +/* Copyright 1996-2000 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 Type1 parser component is in charge of simply parsing the font */ + /* input stream and convert simple tokens and elements into integers, */ + /* floats, matrices, strings, etc. */ + /* */ + /* It is used by the Type1 loader. */ + /* */ + /*************************************************************************/ + + +#ifndef T1PARSE_H +#define T1PARSE_H + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1tokens.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* T1_DictState */ + /* */ + /* */ + /* An enumeration used to describe the Type 1 parser's state, i.e. */ + /* which dictionary (or array) it is scanning and processing at the */ + /* current moment. */ + /* */ + typedef enum T1_DictState_ + { + dict_none = 0, + dict_font, /* parsing the font dictionary */ + dict_fontinfo, /* parsing the font info dictionary */ + dict_none2, /* beginning to parse the encrypted section */ + dict_private, /* parsing the private dictionary */ + dict_encoding, /* parsing the encoding array */ + dict_subrs, /* parsing the subrs array */ + dict_othersubrs, /* parsing the othersubrs array (?) */ + dict_charstrings, /* parsing the charstrings dictionary */ + dict_unknown_array, /* parsing/ignoring an unknown array */ + dict_unknown_dict, /* parsing/ignoring an unknown dictionary */ + + dict_max /* do not remove from list */ + + } T1_DictState; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Table */ + /* */ + /* */ + /* A T1_Table is a simple object used to store an array of objects in */ + /* a single memory block. */ + /* */ + /* */ + /* 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). */ + /* */ + typedef struct T1_Table_ + { + FT_Byte* block; /* current memory block */ + FT_Int cursor; /* current cursor in memory block */ + FT_Int capacity; /* current size of memory block */ + + 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; + + } T1_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Parser */ + /* */ + /* */ + /* A Type 1 parser. This object is in charge of parsing Type 1 ASCII */ + /* streams and builds dictionaries for a T1_Face object. */ + /* */ + /* */ + /* error :: The current error code. 0 means success. */ + /* */ + /* face :: The target T1_Face object being built. */ + /* */ + /* tokenizer :: The tokenizer (lexical analyser) used for */ + /* processing the input stream. */ + /* */ + /* dump_tokens :: XXX */ + /* */ + /* stack :: The current token stack. Note that we don't */ + /* use intermediate Postscript objects here! */ + /* */ + /* top :: The current top of token stack. */ + /* */ + /* limit :: The current upper bound of the token stack. */ + /* Used for overflow checks. */ + /* */ + /* args :: The arguments of a given operator. Used and */ + /* increased by the various CopyXXX() functions. */ + /* */ + /* state_index :: The index of the top of the dictionary state */ + /* stack. */ + /* */ + /* state_stack :: The dictionary states stack. */ + /* */ + /* table :: A T1_Table object used to record various kinds */ + /* of dictionaries or arrays (like `/Encoding', */ + /* `/Subrs', `/CharStrings'). */ + /* */ + /* cur_name :: XXX */ + /* */ + /* encoding_type :: XXX */ + /* */ + /* encoding_names :: XXX */ + /* */ + /* encoding_lengths :: XXX */ + /* */ + /* encoding_offsets :: XXX */ + /* */ + /* subrs :: XXX */ + /* */ + /* charstrings :: XXX */ + /* */ + typedef struct T1_Parser_ + { + FT_Error error; + T1_Face face; + + T1_Tokenizer tokenizer; + FT_Bool dump_tokens; + + T1_Token stack[T1_MAX_STACK_DEPTH]; + T1_Token* top; + T1_Token* limit; + T1_Token* args; + + FT_Int state_index; + T1_DictState state_stack[T1_MAX_DICT_DEPTH]; + + T1_Table table; + + FT_Int cur_name; + + T1_EncodingType encoding_type; + FT_Byte* encoding_names; + FT_Int* encoding_lengths; + FT_Byte** encoding_offsets; + + FT_Byte* subrs; + FT_Byte* charstrings; + + } T1_Parser; + + + LOCAL_DEF + FT_Error T1_New_Table( T1_Table* table, + FT_Int count, + FT_Memory memory ); + + LOCAL_DEF + FT_Error T1_Add_Table( T1_Table* table, + FT_Int index, + void* object, + FT_Int length ); + + LOCAL_DEF + void T1_Done_Table( T1_Table* table ); + + + LOCAL_DEF + FT_String* CopyString( T1_Parser* parser ); + + LOCAL_DEF + FT_Long CopyInteger( T1_Parser* parser ); + + LOCAL_DEF + FT_Bool CopyBoolean( T1_Parser* parser ); + + LOCAL_DEF + FT_Long CopyFloat( T1_Parser* parser, + FT_Int scale ); + + LOCAL_DEF + void CopyBBox( T1_Parser* parser, + FT_BBox* bbox ); + + LOCAL_DEF + void CopyMatrix( T1_Parser* parser, + FT_Matrix* matrix ); + + LOCAL_DEF + void CopyArray( T1_Parser* parser, + FT_Byte* num_elements, + FT_Short* elements, + FT_Int max_elements ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1PARSE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1tokens.c b/reactos/subsys/win32k/freetype/src/type1/t1tokens.c new file mode 100644 index 00000000000..2953322c990 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1tokens.c @@ -0,0 +1,1101 @@ +/***************************************************************************/ +/* */ +/* t1parse.c */ +/* */ +/* Type 1 parser (body). */ +/* */ +/* Copyright 1996-2000 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 tokenizer is in charge of loading and reading a Type1 font file */ + /* (either in PFB or PFA format), and extracting successive tokens and */ + /* keywords from its two streams (i.e. the font program, and the private */ + /* dictionary). */ + /* */ + /* Eexec decryption is performed automatically when entering the private */ + /* dictionary, or when retrieving char strings. */ + /* */ + /*************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1tokens.h" +#include "t1load.h" + +#else + +#include +#include + +#endif + + +#include /* for strncmp() */ + + +#undef READ_BUFFER_INCREMENT +#define READ_BUFFER_INCREMENT 0x400 + + + /*************************************************************************/ + /* */ + /* 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 + + + /* An array of Type1 keywords supported by this engine. This table */ + /* places the keyword in lexicographical order. It should always */ + /* correspond to the enums `key_xxx'! */ + /* */ + const char* t1_keywords[key_max - key_first_] = + { + "-|", "ExpertEncoding", "ND", "NP", "RD", "StandardEncoding", "array", + "begin", "closefile", "currentdict", "currentfile", "def", "dict", "dup", + "eexec", "end", "executeonly", "false", "for", "index", "noaccess", + "put", "readonly", "true", "userdict", "|", "|-" + }; + + + const char* t1_immediates[imm_max - imm_first_] = + { + "-|", ".notdef", "BlendAxisTypes", "BlueFuzz", "BlueScale", "BlueShift", + "BlueValues", "CharStrings", "Encoding", "FamilyBlues", "FamilyName", + "FamilyOtherBlues", "FID", "FontBBox", "FontID", "FontInfo", "FontMatrix", + "FontName", "FontType", "ForceBold", "FullName", "ItalicAngle", + "LanguageGroup", "Metrics", "MinFeature", "ND", "NP", "Notice", + "OtherBlues", "OtherSubrs", "PaintType", "Private", "RD", "RndStemUp", + "StdHW", "StdVW", "StemSnapH", "StemSnapV", "StrokeWidth", "Subrs", + "UnderlinePosition", "UnderlineThickness", "UniqueID", "Weight", + "isFixedPitch", "lenIV", "password", "version", "|", "|-" + }; + + + /* lexicographic comparison of two strings */ + static + int lexico_strcmp( const char* str1, + int str1_len, + const char* str2 ) + { + int c2 = 0; + + + for ( ; str1_len > 0; str1_len-- ) + { + int c1, diff; + + + c1 = *str1++; + c2 = *str2++; + + diff = c1 - c2; + if ( diff ) + return diff; + }; + + return -*str2; + } + + + /* find a given token/name, performing binary search */ + static + int Find_Name( char* base, + int length, + const char** table, + int table_len ) + { + int left, right; + + + left = 0; + right = table_len - 1; + + while ( right - left > 1 ) + { + int middle = left + ( ( right - left ) >> 1 ); + int cmp; + + + cmp = lexico_strcmp( base, length, table[middle] ); + if ( !cmp ) + return middle; + + if ( cmp < 0 ) + right = middle; + else + left = middle; + } + + if ( !lexico_strcmp( base, length, table[left ] ) ) + return left; + if ( !lexico_strcmp( base, length, table[right] ) ) + return right; + + return -1; + } + + + /* read the small PFB section header */ + static + FT_Error Read_PFB_Tag( FT_Stream stream, + FT_UShort* atag, + FT_ULong* asize ) + { + FT_UShort tag; + FT_ULong size; + FT_Error error; + + + FT_TRACE2(( "Read_PFB_Tag: reading\n" )); + + if ( ACCESS_Frame( 6L ) ) + return error; + + tag = GET_UShort(); + size = GET_ULong(); + + FORGET_Frame(); + + *atag = tag; + *asize = ( ( size & 0xFF ) << 24 ) | + ( ( ( size >> 8 ) & 0xFF ) << 16 ) | + ( ( ( size >> 16 ) & 0xFF ) << 8 ) | + ( ( ( size >> 24 ) & 0xFF ) ); + + FT_TRACE2(( " tag = %04x\n", tag )); + FT_TRACE4(( " asze = %08x\n", size )); + FT_TRACE2(( " size = %08x\n", *asize )); + + return T1_Err_Ok; + } + + + static + FT_Error grow( T1_Tokenizer tokzer ) + { + FT_Error error; + FT_Long left_bytes; + FT_Memory memory = tokzer->memory; + + + left_bytes = tokzer->max - tokzer->limit; + + if ( left_bytes > 0 ) + { + FT_Stream stream = tokzer->stream; + + + if ( left_bytes > READ_BUFFER_INCREMENT ) + left_bytes = READ_BUFFER_INCREMENT; + + FT_TRACE2(( "Growing tokenizer buffer by %d bytes\n", left_bytes )); + + if ( !REALLOC( tokzer->base, tokzer->limit, + tokzer->limit + left_bytes ) && + !FILE_Read( tokzer->base + tokzer->limit, left_bytes ) ) + tokzer->limit += left_bytes; + } + else + { + FT_ERROR(( "Unexpected end of Type1 fragment!\n" )); + error = T1_Err_Invalid_File_Format; + } + + tokzer->error = error; + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_decrypt */ + /* */ + /* */ + /* Performs the Type 1 charstring decryption process. */ + /* */ + /* */ + /* buffer :: The base address of the data to decrypt. */ + /* length :: The number of bytes to decrypt (beginning from the base */ + /* address. */ + /* seed :: The encryption seed (4330 for charstrings). */ + /* */ + LOCAL_FUNC + void t1_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ) + { + while ( length > 0 ) + { + FT_Byte plain; + + + plain = ( *buffer ^ ( seed >> 8 ) ); + seed = ( *buffer + seed ) * 52845 + 22719; + *buffer++ = plain; + length--; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* New_Tokenizer */ + /* */ + /* */ + /* Creates a new tokenizer from a given input stream. This function */ + /* automatically recognizes `pfa' or `pfb' files. The function */ + /* Read_Token() can then be used to extract successive tokens from */ + /* the stream. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* tokenizer :: A handle to a new tokenizer object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function copies the stream handle within the object. Callers */ + /* should not discard `stream'. This is done by the Done_Tokenizer() */ + /* function. */ + /* */ + LOCAL_FUNC + FT_Error New_Tokenizer( FT_Stream stream, + T1_Tokenizer* tokenizer ) + { + FT_Memory memory = stream->memory; + T1_Tokenizer tokzer; + FT_Error error; + FT_UShort tag; + FT_ULong size; + + FT_Byte* tok_base; + FT_ULong tok_limit; + FT_ULong tok_max; + + + *tokenizer = 0; + + /* allocate object */ + if ( FILE_Seek( 0L ) || + ALLOC( tokzer, sizeof ( *tokzer ) ) ) + return error; + + tokzer->stream = stream; + tokzer->memory = stream->memory; + + tokzer->in_pfb = 0; + tokzer->in_private = 0; + + tok_base = 0; + tok_limit = 0; + tok_max = stream->size; + + error = Read_PFB_Tag( stream, &tag, &size ); + if ( error ) + goto Fail; + + if ( tag != 0x8001 ) + { + /* assume that it is a PFA file -- an error will be produced later */ + /* if a character with value > 127 is encountered */ + + /* rewind to start of file */ + if ( FILE_Seek( 0L ) ) + goto Fail; + + size = stream->size; + } + else + tokzer->in_pfb = 1; + + /* if it is a memory-based resource, set up pointer */ + if ( !stream->read ) + { + tok_base = (FT_Byte*)stream->base + stream->pos; + tok_limit = size; + tok_max = size; + + /* check that the `size' field is valid */ + if ( FILE_Skip( size ) ) + goto Fail; + } + else if ( tag == 0x8001 ) + { + /* read segment in memory */ + if ( ALLOC( tok_base, size ) ) + goto Fail; + + if ( FILE_Read( tok_base, size ) ) + { + FREE( tok_base ); + goto Fail; + } + + tok_limit = size; + tok_max = size; + } + + tokzer->base = tok_base; + tokzer->limit = tok_limit; + tokzer->max = tok_max; + tokzer->cursor = 0; + + *tokenizer = tokzer; + + /* now check font format; we must see `%!PS-AdobeFont-1' */ + /* or `%!FontType' */ + { + if ( 16 > tokzer->limit ) + grow( tokzer ); + + if ( tokzer->limit <= 16 || + ( strncmp( (const char*)tokzer->base, "%!PS-AdobeFont-1", 16 ) && + strncmp( (const char*)tokzer->base, "%!FontType", 10 ) ) ) + { + FT_TRACE2(( "[not a Type1 font]\n" )); + error = FT_Err_Unknown_File_Format; + goto Fail; + } + } + return T1_Err_Ok; + + Fail: + FREE( tokzer->base ); + FREE( tokzer ); + return error; + } + + + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Done_Tokenizer */ + /* */ + /* */ + /* Closes a given tokenizer. This function will also close the */ + /* stream embedded in the object. */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Done_Tokenizer( T1_Tokenizer tokenizer ) + { + FT_Memory memory = tokenizer->memory; + + + /* clear read buffer if needed (disk-based resources) */ + if ( tokenizer->in_private || !tokenizer->stream->base ) + FREE( tokenizer->base ); + + FREE( tokenizer ); + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Open_PrivateDict */ + /* */ + /* */ + /* This function must be called to set the tokenizer to the private */ + /* section of the Type1 file. It recognizes automatically the */ + /* the kind of eexec encryption used (ascii or binary). */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* lenIV :: The value of the `lenIV' variable. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Open_PrivateDict( T1_Tokenizer tokenizer ) + { + T1_Tokenizer tokzer = tokenizer; + FT_Stream stream = tokzer->stream; + FT_Memory memory = tokzer->memory; + FT_Error error = 0; + + FT_UShort tag; + FT_ULong size; + + FT_Byte* private_dict; + + /* are we already in the private dictionary ? */ + if ( tokzer->in_private ) + return 0; + + if ( tokzer->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_ULong private_dict_size = 0; + + + for (;;) + { + error = Read_PFB_Tag( stream, &tag, &size ); + if ( error || tag != 0x8002 ) + break; + + private_dict_size += size; + + if ( FILE_Skip( size ) ) + goto Fail; + } + + /* check that we have a private dictionary there */ + /* and allocate private dictionary buffer */ + if ( private_dict_size == 0 ) + { + FT_ERROR(( "Open_PrivateDict:" )); + FT_ERROR(( " invalid private dictionary section\n" )); + error = T1_Err_Invalid_File_Format; + goto Fail; + } + + if ( ALLOC( private_dict, private_dict_size ) ) + goto Fail; + + /* read all sections into buffer */ + if ( FILE_Seek( start_pos ) ) + goto Fail_Private; + + private_dict_size = 0; + for (;;) + { + error = Read_PFB_Tag( stream, &tag, &size ); + if ( error || tag != 0x8002 ) + { + error = 0; + break; + } + + if ( FILE_Read( private_dict + private_dict_size, size ) ) + goto Fail_Private; + + private_dict_size += size; + } + + /* we must free the field `tokzer.base' if we are in a disk-based */ + /* PFB file. */ + if ( stream->read ) + FREE( tokzer->base ); + + tokzer->base = private_dict; + tokzer->cursor = 0; + tokzer->limit = private_dict_size; + tokzer->max = private_dict_size; + } + else + { + char* base; + + + /* we are in a PFA file; read each token until we find `eexec' */ + while ( tokzer->token.kind2 != key_eexec ) + { + error = Read_Token( tokzer ); + if ( error ) + goto Fail; + } + + /* now determine whether the private dictionary is encoded in binary */ + /* or hexadecimal ASCII format. */ + + /* 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. */ + while ( tokzer->cursor + 5 > tokzer->limit ) + { + error = grow( tokzer ); + if ( error ) + goto Fail; + } + + /* skip whitespace/line feed after `eexec' */ + base = (char*)tokzer->base + tokzer->cursor + 1; + if ( ( hexa_value( base[0] ) | hexa_value( base[1] ) | + hexa_value( base[2] ) | hexa_value( base[3] ) ) < 0 ) + { + /* binary encoding -- `simply' read the stream */ + + /* if it is a memory-based resource, we need to allocate a new */ + /* storage buffer for the private dictionary, as it must be */ + /* decrypted later */ + if ( stream->base ) + { + size = stream->size - tokzer->cursor - 1; /* remaining bytes */ + + if ( ALLOC( private_dict, size ) ) /* alloc private dict buffer */ + goto Fail; + + /* copy eexec-encrypted bytes */ + MEM_Copy( private_dict, tokzer->base + tokzer->cursor + 1, size ); + + /* reset pointers - forget about file mapping */ + tokzer->base = private_dict; + tokzer->limit = size; + tokzer->max = size; + tokzer->cursor = 0; + } + /* On the opposite, for disk based resources, we simply grow */ + /* the current buffer until its completion, and decrypt the */ + /* bytes within it. In all cases, the `base' buffer will be */ + /* discarded on DoneTokenizer if we are in the private dict. */ + else + { + /* grow the read buffer to the full file */ + while ( tokzer->limit < tokzer->max ) + { + error = grow( tokenizer ); + if ( error ) + goto Fail; + } + + /* set up cursor to first encrypted byte */ + tokzer->cursor++; + } + } + else + { + /* ASCII hexadecimal encoding. This sucks... */ + FT_Byte* write; + FT_Byte* cur; + FT_Byte* limit; + FT_Int count; + + + /* allocate a buffer, read each one byte at a time */ + count = stream->size - tokzer->cursor; + size = count / 2; + + if ( ALLOC( private_dict, size ) ) /* alloc private dict buffer */ + goto Fail; + + write = private_dict; + cur = tokzer->base + tokzer->cursor; + limit = tokzer->base + tokzer->limit; + + /* read each bytes */ + while ( count > 0 ) + { + /* ensure that we can read the next 2 bytes! */ + while ( cur + 2 > limit ) + { + int cursor = cur - tokzer->base; + + + error = grow( tokzer ); + if ( error ) + goto Fail_Private; + cur = tokzer->base + cursor; + limit = tokzer->base + tokzer->limit; + } + + /* check for new line */ + if ( cur[0] == '\r' || cur[0] == '\n' ) + { + cur++; + count--; + } + else + { + int hex1 = hexa_value(cur[0]); + + + /* exit if we have a non-hexadecimal digit which isn't */ + /* a new-line character */ + if ( hex1 < 0 ) + break; + + /* otherwise, store byte */ + *write++ = ( hex1 << 4 ) | hexa_value( cur[1] ); + cur += 2; + count -= 2; + } + } + + /* get rid of old buffer in the case of disk-based resources */ + if ( !stream->base ) + FREE( tokzer->base ); + + /* set up pointers */ + tokzer->base = private_dict; + tokzer->limit = size; + tokzer->max = size; + tokzer->cursor = 0; + } + } + + /* finally, decrypt the private dictionary - and skip the lenIV bytes */ + t1_decrypt( tokzer->base, tokzer->limit, 55665 ); + tokzer->cursor += 4; + + Fail: + return error; + + Fail_Private: + FREE( private_dict ); + goto Fail; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Read_Token */ + /* */ + /* */ + /* Reads a new token from the current input stream. This function */ + /* extracts a token from the font program until Open_PrivateDict() */ + /* has been called. After this, it returns tokens from the */ + /* (eexec-encrypted) private dictionary. */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Use the function Read_CharStrings() to read the binary charstrings */ + /* from the private dict. */ + /* */ + LOCAL_FUNC + FT_Error Read_Token( T1_Tokenizer tokenizer ) + { + T1_Tokenizer tok = tokenizer; + FT_Long cur, limit; + FT_Byte* base; + char c, starter, ender; + FT_Bool token_started; + + T1_TokenType kind; + + + tok->error = T1_Err_Ok; + tok->token.kind = tok_any; + + base = tok->base; + limit = tok->limit; + cur = tok->cursor; + + token_started = 0; + + for (;;) + { + if ( cur >= limit ) + { + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + c = (char)base[cur++]; + + /* check that we have an ASCII character */ + if ( (FT_Byte)c > 127 ) + { + FT_ERROR(( "Read_Token:" )); + FT_ERROR(( " unexpected binary data in Type1 fragment!\n" )); + tok->error = T1_Err_Invalid_File_Format; + goto Exit; + } + + switch ( c ) + { + case '\r': + case '\n': + case ' ' : + case '\t': /* skip initial whitespace => skip to next */ + if ( token_started ) + { + /* possibly a name, keyword, wathever */ + tok->token.kind = tok_any; + tok->token.len = cur-tok->token.start - 1; + goto Exit; + } + /* otherwise, skip everything */ + break; + + case '%': /* this is a comment -- skip everything */ + for (;;) + { + FT_Int left = limit - cur; + + + while ( left > 0 ) + { + c = (char)base[cur++]; + if ( c == '\r' || c == '\n' ) + goto Next; + left--; + } + + if ( grow( tokenizer ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + case '(': /* a Postscript string */ + kind = tok_string; + ender = ')'; + + L1: + if ( !token_started ) + { + token_started = 1; + tok->token.start = cur - 1; + } + + { + FT_Int nest_level = 1; + + + starter = c; + for (;;) + { + FT_Int left = limit - cur; + + + while ( left > 0 ) + { + c = (char)base[cur++]; + + if ( c == starter ) + nest_level++; + + else if ( c == ender ) + { + nest_level--; + if ( nest_level <= 0 ) + { + tok->token.kind = kind; + tok->token.len = cur - tok->token.start; + goto Exit; + } + } + left--; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + } + + case '[': /* a Postscript array */ + if ( token_started ) + goto Any_Token; + + kind = tok_array; + ender = ']'; + goto L1; + break; + + case '{': /* a Postscript program */ + if ( token_started ) + goto Any_Token; + + kind = tok_program; + ender = '}'; + goto L1; + break; + + case '<': /* a Postscript hex byte array? */ + if ( token_started ) + goto Any_Token; + + kind = tok_hexarray; + ender = '>'; + goto L1; + break; + + case '0': /* any number */ + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if ( token_started ) + goto Next; + + tok->token.kind = tok_number; + token_started = 1; + tok->token.start = cur - 1; + + L2: + for (;;) + { + FT_Int left = limit-cur; + + + while ( left > 0 ) + { + c = (char)base[cur++]; + + switch ( c ) + { + case '[': /* ] */ + case '{': /* } */ + case '(': /* ) */ + case '<': + case '/': + goto Any_Token; + + case ' ': + case '\r': + case '\t': + case '\n': + tok->token.len = cur - tok->token.start - 1; + goto Exit; + + default: + ; + } + left--; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + case '.': /* maybe a number */ + case '-': + case '+': + if ( token_started ) + goto Next; + + token_started = 1; + tok->token.start = cur - 1; + + for (;;) + { + FT_Int left = limit - cur; + + + if ( left > 0 ) + { + /* test for any following digit, interpreted as number */ + c = (char)base[cur]; + tok->token.kind = ( c >= '0' && c <= '9' ? tok_number : tok_any ); + goto L2; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + case '/': /* maybe an immediate name */ + if ( !token_started ) + { + token_started = 1; + tok->token.start = cur - 1; + + for (;;) + { + FT_Int left = limit - cur; + + + if ( left > 0 ) + { + /* test for single '/', interpreted as garbage */ + c = (char)base[cur]; + tok->token.kind = ( c == ' ' || c == '\t' || + c == '\r' || c == '\n' ) ? tok_any + : tok_immediate; + goto L2; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + } + else + { + Any_Token: /* possibly a name or wathever */ + cur--; + tok->token.len = cur - tok->token.start; + goto Exit; + } + + default: + if ( !token_started ) + { + token_started = 1; + tok->token.start = cur - 1; + } + } + + Next: + ; + } + + Exit: + tok->cursor = cur; + + if ( !tok->error ) + { + /* now, tries to match keywords and immediate names */ + FT_Int index; + + + switch ( tok->token.kind ) + { + case tok_immediate: /* immediate name */ + index = Find_Name( (char*)( tok->base + tok->token.start + 1 ), + tok->token.len - 1, + t1_immediates, + imm_max - imm_first_ ); + tok->token.kind2 = ( index >= 0 ) + ? (T1_TokenType)( imm_first_ + index ) + : tok_error; + break; + + case tok_any: /* test for keyword */ + index = Find_Name( (char*)( tok->base + tok->token.start ), + tok->token.len, + t1_keywords, + key_max - key_first_ ); + if ( index >= 0 ) + { + tok->token.kind = tok_keyword; + tok->token.kind2 = (T1_TokenType)( key_first_ + index ); + } + else + tok->token.kind2 = tok_error; + break; + + default: + tok->token.kind2 = tok_error; + } + } + return tokenizer->error; + } + + +#if 0 + + /*************************************************************************/ + /* */ + /* */ + /* Read_CharStrings */ + /* */ + /* */ + /* Reads a charstrings element from the current input stream. These */ + /* are binary bytes that encode each individual glyph outline. */ + /* */ + /* The caller is responsible for skipping the `lenIV' bytes at the */ + /* start of the record. */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* num_chars :: The number of binary bytes to read. */ + /* */ + /* */ + /* buffer :: The target array of bytes. These are */ + /* eexec-decrypted. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Use the function Read_CharStrings() to read binary charstrings */ + /* from the private dict. */ + /* */ + LOCAL_FUNC + FT_Error Read_CharStrings( T1_Tokenizer tokenizer, + FT_Int num_chars, + FT_Byte* buffer ) + { + for (;;) + { + FT_Int left = tokenizer->limit - tokenizer->cursor; + + + if ( left >= num_chars ) + { + MEM_Copy( buffer, tokenizer->base + tokenizer->cursor, num_chars ); + t1_decrypt( buffer, num_chars, 4330 ); + tokenizer->cursor += num_chars; + return T1_Err_Ok; + } + + if ( grow( tokenizer ) ) + return tokenizer->error; + } + } + +#endif /* 0 */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/t1tokens.h b/reactos/subsys/win32k/freetype/src/type1/t1tokens.h new file mode 100644 index 00000000000..119c54ba19e --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/t1tokens.h @@ -0,0 +1,258 @@ +/***************************************************************************/ +/* */ +/* t1tokens.h */ +/* */ +/* Type 1 tokenizer (specification). */ +/* */ +/* Copyright 1996-2000 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 T1TOKENS_H +#define T1TOKENS_H + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* enum value of first keyword */ +#define key_first_ 100 + + /* enum value of first immediate name */ +#define imm_first_ 200 + + + typedef enum T1_TokenType_ + { + tok_error = 0, + + tok_eof, /* end of file */ + + /* simple token types */ + + tok_keyword, /* keyword */ + tok_number, /* number (integer or real) */ + tok_string, /* postscript string */ + tok_program, /* postscript program */ + tok_immediate, /* any immediate name */ + tok_array, /* matrix, array, etc.. */ + tok_hexarray, /* array of hexadecimal nibbles */ + tok_any, /* anything else */ + + /* Postscript keywords -- placed in lexicographical order */ + + key_RD_alternate = key_first_, /* `-|' = alternate form of RD */ + key_ExpertEncoding, + key_ND, + key_NP, + key_RD, + key_StandardEncoding, + key_array, + key_begin, + key_closefile, + key_currentdict, + key_currentfile, + key_def, + key_dict, + key_dup, + key_eexec, + key_end, + key_execonly, + key_false, + key_for, + key_index, + key_noaccess, + key_put, + key_readonly, + key_true, + key_userdict, + key_NP_alternate, /* `|' = alternate form of NP */ + key_ND_alternate, /* `|-' = alternate form of ND */ + + key_max, /* always keep this value there */ + + /* Postscript immediate names -- other names will be ignored, except */ + /* in charstrings */ + + imm_RD_alternate = imm_first_, /* `-|' = alternate form of RD */ + imm_notdef, /* `/.notdef' immediate */ + imm_BlendAxisTypes, + imm_BlueFuzz, + imm_BlueScale, + imm_BlueShift, + imm_BlueValues, + imm_CharStrings, + imm_Encoding, + imm_FamilyBlues, + imm_FamilyName, + imm_FamilyOtherBlues, + imm_FID, + imm_FontBBox, + imm_FontID, + imm_FontInfo, + imm_FontMatrix, + imm_FontName, + imm_FontType, + imm_ForceBold, + imm_FullName, + imm_ItalicAngle, + imm_LanguageGroup, + imm_Metrics, + imm_MinFeature, + imm_ND, + imm_NP, + imm_Notice, + imm_OtherBlues, + imm_OtherSubrs, + imm_PaintType, + imm_Private, + imm_RD, + imm_RndStemUp, + imm_StdHW, + imm_StdVW, + imm_StemSnapH, + imm_StemSnapV, + imm_StrokeWidth, + imm_Subrs, + imm_UnderlinePosition, + imm_UnderlineThickness, + imm_UniqueID, + imm_Weight, + + imm_isFixedPitch, + imm_lenIV, + imm_password, + imm_version, + + imm_NP_alternate, /* `|' = alternate form of NP */ + imm_ND_alternate, /* `|-' = alternate form of ND */ + + imm_max /* always keep this value here */ + + } T1_TokenType; + + + /* these arrays are visible for debugging purposes */ + extern const char* t1_keywords[]; + extern const char* t1_immediates[]; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Token */ + /* */ + /* */ + /* A structure used to describe a token in the current input stream. */ + /* Note that the Type1 driver doesn't try to interpret tokens until */ + /* it really needs to. */ + /* */ + /* */ + /* kind :: The token type. Describes the token to the loader. */ + /* */ + /* kind2 :: Detailed token type. */ + /* */ + /* start :: The index of the first character of token in the input */ + /* stream. */ + /* */ + /* len :: The length of the token in characters. */ + /* */ + typedef struct T1_Token_ + { + T1_TokenType kind; /* simple type */ + T1_TokenType kind2; /* detailed type */ + FT_Int start; /* index of first token character */ + FT_Int len; /* length of token in chars */ + + } T1_Token; + + + typedef struct T1_TokenParser_ + { + FT_Memory memory; + FT_Stream stream; + + FT_Bool in_pfb; /* true if PFB file, PFA otherwise */ + FT_Bool in_private; /* true if in private dictionary */ + + FT_Byte* base; /* base address of current read buffer */ + FT_Long cursor; /* current position in read buffer */ + FT_Long limit; /* limit of current read buffer */ + FT_Long max; /* maximum size of read buffer */ + + FT_Error error; /* last error */ + T1_Token token; /* last token read */ + + } T1_TokenParser; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Tokenizer */ + /* */ + /* */ + /* A handle to an object used to extract tokens from the input. The */ + /* object is able to perform PFA/PFB recognition, eexec decryption of */ + /* the private dictionary, as well as eexec decryption of the */ + /* charstrings. */ + /* */ + typedef T1_TokenParser* T1_Tokenizer; + + + LOCAL_DEF + FT_Error New_Tokenizer( FT_Stream stream, + T1_Tokenizer* tokenizer ); + + LOCAL_DEF + FT_Error Done_Tokenizer( T1_Tokenizer tokenizer ); + + LOCAL_DEF + FT_Error Open_PrivateDict( T1_Tokenizer tokenizer ); + + LOCAL_DEF + FT_Error Read_Token( T1_Tokenizer tokenizer ); + + +#if 0 + LOCAL_DEF + FT_Error Read_CharStrings( T1_Tokenizer tokenizer, + FT_Int num_chars, + FT_Byte* buffer ); +#endif /* 0 */ + + LOCAL_DEF + void t1_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1TOKENS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1/type1.c b/reactos/subsys/win32k/freetype/src/type1/type1.c new file mode 100644 index 00000000000..d2058d620fe --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1/type1.c @@ -0,0 +1,59 @@ +/***************************************************************************/ +/* */ +/* type1.c */ +/* */ +/* FreeType Type 1 driver component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "t1driver.c" +#include "t1objs.c" +#include "t1load.c" +#include "t1gload.c" +#include "t1tokens.c" +#include "t1parse.c" + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include "t1hinter.c" +#endif + +#ifndef T1_CONFIG_OPTION_NO_AFM +#include "t1afm.c" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include +#include +#include +#include + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + +#ifndef T1_CONFIG_OPTION_NO_AFM +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/Readme.txt b/reactos/subsys/win32k/freetype/src/type1z/Readme.txt new file mode 100644 index 00000000000..6502fb9d9f3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/Readme.txt @@ -0,0 +1,10 @@ +This directory contains an experimental Type 1 driver that will ultimately +replace the "official" one in "src/type1". + +This driver doesn't provide a mini Postscript interpreter, but uses +pattern matching in order to load data from fonts. It works better and +faster than the official driver, but will replace it only when we finish +the auto-hinting module.. + +You don't need to compile it to support Type 1 fonts, the driver should +co-exist peacefully with the rest of the engine however.. diff --git a/reactos/subsys/win32k/freetype/src/type1z/module.mk b/reactos/subsys/win32k/freetype/src/type1z/module.mk new file mode 100644 index 00000000000..545887d8247 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_type1_driver + +add_type1_driver: + $(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)type1 $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/type1z/rules.mk b/reactos/subsys/win32k/freetype/src/type1z/rules.mk new file mode 100644 index 00000000000..3411fd171c9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/rules.mk @@ -0,0 +1,72 @@ +# +# FreeType 2 Type1z driver configuration rules +# + + +# Copyright 1996-2000 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. + + +# Type1z driver directory +# +T1Z_DIR := $(SRC_)type1z +T1Z_DIR_ := $(T1Z_DIR)$(SEP) + + +# compilation flags for the driver +# +T1Z_COMPILE := $(FT_COMPILE) + + +# Type1 driver sources (i.e., C files) +# +T1Z_DRV_SRC := $(T1Z_DIR_)z1parse.c \ + $(T1Z_DIR_)z1load.c \ + $(T1Z_DIR_)z1driver.c \ + $(T1Z_DIR_)z1afm.c \ + $(T1Z_DIR_)z1gload.c \ + $(T1Z_DIR_)z1objs.c + +# Type1 driver headers +# +T1Z_DRV_H := $(T1Z_DRV_SRC:%.c=%.h) \ + $(T1Z_DIR_)z1tokens.h + + +# Type1z driver object(s) +# +# T1Z_DRV_OBJ_M is used during `multi' builds +# T1Z_DRV_OBJ_S is used during `single' builds +# +T1Z_DRV_OBJ_M := $(T1Z_DRV_SRC:$(T1Z_DIR_)%.c=$(OBJ_)%.$O) +T1Z_DRV_OBJ_S := $(OBJ_)type1z.$O + +# Type1z driver source file for single build +# +T1Z_DRV_SRC_S := $(T1Z_DIR_)type1z.c + + +# Type1z driver - single object +# +$(T1Z_DRV_OBJ_S): $(T1Z_DRV_SRC_S) $(T1Z_DRV_SRC) $(FREETYPE_H) $(T1Z_DRV_H) + $(T1Z_COMPILE) $T$@ $(T1Z_DRV_SRC_S) + + +# Type1z driver - multiple objects +# +$(OBJ_)%.$O: $(T1Z_DIR_)%.c $(FREETYPE_H) $(T1Z_DRV_H) + $(T1Z_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(T1Z_DRV_OBJ_S) +DRV_OBJS_M += $(T1Z_DRV_OBJ_M) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/type1z/type1z.c b/reactos/subsys/win32k/freetype/src/type1z/type1z.c new file mode 100644 index 00000000000..17e89ac1570 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/type1z.c @@ -0,0 +1,49 @@ +/***************************************************************************/ +/* */ +/* type1z.c */ +/* */ +/* FreeType experimental Type 1 driver component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "z1parse.c" +#include "z1load.c" +#include "z1objs.c" +#include "z1driver.c" +#include "z1gload.c" + +#ifndef Z1_CONFIG_OPTION_NO_AFM +#include "z1afm.c" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include +#include +#include + +#ifndef Z1_CONFIG_OPTION_NO_AFM +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/z1afm.c b/reactos/subsys/win32k/freetype/src/type1z/z1afm.c new file mode 100644 index 00000000000..b329cd347f3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1afm.c @@ -0,0 +1,293 @@ +/***************************************************************************/ +/* */ +/* z1afm.c */ +/* */ +/* AFM support for Type 1 fonts (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "z1afm.h" + +#else + +#include + +#endif + + +#include +#include + +#include /* for qsort() */ +#include /* for strcmp() */ +#include /* 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_z1afm + + + LOCAL_FUNC + void Z1_Done_AFM( FT_Memory memory, + Z1_AFM* afm ) + { + FREE( afm->kern_pairs ); + afm->num_pairs = 0; + } + + +#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 = 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 */ + static + int compare_kern_pairs( const void* a, + const void* b ) + { + Z1_Kern_Pair* pair1 = (Z1_Kern_Pair*)a; + Z1_Kern_Pair* pair2 = (Z1_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 */ + LOCAL_FUNC + FT_Error Z1_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; + Z1_Kern_Pair* pair; + T1_Font* type1 = &((T1_Face)t1_face)->type1; + Z1_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, Z1_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; + + 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 ( Z1_Kern_Pair ), + compare_kern_pairs ); + + Exit: + if ( error ) + FREE( afm ); + + FORGET_Frame(); + + return error; + } + + + /* find the kerning for a given glyph pair */ + LOCAL_FUNC + void Z1_Get_Kerning( Z1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + Z1_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/reactos/subsys/win32k/freetype/src/type1z/z1afm.h b/reactos/subsys/win32k/freetype/src/type1z/z1afm.h new file mode 100644 index 00000000000..bfacce71358 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1afm.h @@ -0,0 +1,79 @@ +/***************************************************************************/ +/* */ +/* z1afm.h */ +/* */ +/* AFM support for Type 1 fonts (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1AFM_H +#define Z1AFM_H + + +#ifdef FT_FLAT_COMPILE + +#include "z1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct Z1_Kern_Pair_ + { + FT_UInt glyph1; + FT_UInt glyph2; + FT_Vector kerning; + + } Z1_Kern_Pair; + + + typedef struct Z1_AFM_ + { + FT_Int num_pairs; + Z1_Kern_Pair* kern_pairs; + + } Z1_AFM; + + + LOCAL_DEF + FT_Error Z1_Read_AFM( FT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void Z1_Done_AFM( FT_Memory memory, + Z1_AFM* afm ); + + LOCAL_DEF + void Z1_Get_Kerning( Z1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* Z1AFM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/z1driver.c b/reactos/subsys/win32k/freetype/src/type1z/z1driver.c new file mode 100644 index 00000000000..aea2c10f1f7 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1driver.c @@ -0,0 +1,340 @@ +/***************************************************************************/ +/* */ +/* z1driver.c */ +/* */ +/* Experimental Type 1 driver interface (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "z1driver.h" +#include "z1gload.h" +#include "z1load.h" +#include "z1afm.h" + +#else + +#include +#include +#include +#include + +#endif + + +#include +#include +#include + +#include /* 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_z1driver + + + static + FT_Error get_z1_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 = strlen( gname ); + + + if (len >= buffer_max) + len = buffer_max - 1; + + MEM_Copy( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Interface */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* driver :: A handle to a driver object. */ + /* */ + /* */ + /* interface :: A string designing the interface. Examples are */ + /* `sfnt', `post_names', `charmaps', etc. */ + /* */ + /* */ + /* 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)get_z1_glyph_name; + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + if ( strcmp( (const char*)interface, "get_mm" ) == 0 ) + return (FT_Module_Interface)Z1_Get_Multi_Master; + + if ( strcmp( (const char*)interface, "set_mm_design") == 0 ) + return (FT_Module_Interface)Z1_Set_MM_Design; + + if ( strcmp( (const char*)interface, "set_mm_blend") == 0 ) + return (FT_Module_Interface)Z1_Set_MM_Blend; +#endif + return 0; + } + + +#ifndef Z1_CONFIG_OPTION_NO_AFM + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ) + { + Z1_AFM* afm; + + + kerning->x = 0; + kerning->y = 0; + + afm = (Z1_AFM*)face->afm_data; + if ( afm ) + Z1_Get_Kerning( afm, left_glyph, right_glyph, kerning ); + + return T1_Err_Ok; + } + + +#endif /* T1_CONFIG_OPTION_NO_AFM */ + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* 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; + } + + + 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)Z1_Init_Driver, + (FT_Module_Destructor) Z1_Done_Driver, + (FT_Module_Requester) Get_Interface, + }, + + sizeof( T1_FaceRec ), + sizeof( Z1_SizeRec ), + sizeof( Z1_GlyphSlotRec ), + + (FTDriver_initFace) Z1_Init_Face, + (FTDriver_doneFace) Z1_Done_Face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) 0, + (FTDriver_setPixelSizes)0, + (FTDriver_loadGlyph) Z1_Load_Glyph, + (FTDriver_getCharIndex) Get_Char_Index, + +#ifdef Z1_CONFIG_OPTION_NO_AFM + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, +#else + (FTDriver_getKerning) Get_Kerning, + (FTDriver_attachFile) Z1_Read_AFM, +#endif + (FTDriver_getAdvances) 0 + }; + + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void ) + { + return &t1z_driver_class; + } + +#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/z1driver.h b/reactos/subsys/win32k/freetype/src/type1z/z1driver.h new file mode 100644 index 00000000000..08bd544d566 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1driver.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* z1driver.h */ +/* */ +/* High-level experimental Type 1 driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1DRIVER_H +#define Z1DRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Driver_Class ) t1_driver_class; + +#endif /* Z1DRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/z1gload.c b/reactos/subsys/win32k/freetype/src/type1z/z1gload.c new file mode 100644 index 00000000000..0b25d2ecc75 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1gload.c @@ -0,0 +1,1482 @@ +/***************************************************************************/ +/* */ +/* z1gload.c */ +/* */ +/* Experimental Type 1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "z1gload.h" + +#else + +#include + +#endif + + +#include +#include +#include + +#include /* 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_z1gload + + + typedef enum Z1_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 */ + + } Z1_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 */ + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + LOCAL_FUNC + void Z1_Init_Builder( Z1_Builder* builder, + T1_Face face, + Z1_Size size, + Z1_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.loader; + + + builder->loader = loader; + builder->current = &loader->current.outline; + builder->base = &loader->base.outline; + + FT_GlyphLoader_Rewind( loader ); + } + + if ( size ) + { + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Builder */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + LOCAL_FUNC + void Z1_Done_Builder( Z1_Builder* builder ) + { + Z1_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + LOCAL_FUNC + void Z1_Init_Decoder( Z1_Decoder* decoder ) + { + decoder->top = 0; + decoder->zone = 0; + decoder->flex_state = 0; + decoder->num_flex_vectors = 0; + decoder->blend = 0; + + /* Clear loader */ + MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) ); + } + + + /* check that there is enough space for `count' more points */ + static + FT_Error check_points( Z1_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( Z1_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; + point->y = y; + *control = 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( Z1_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 space for a new contour, then add it */ + static + FT_Error add_contour( Z1_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return FT_Err_Ok; + } + + /* reallocate contours array if necessary */ + error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = 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( Z1_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + FT_Error error; + + + builder->path_begun = 1; + error = add_contour( builder ); + if ( error ) + return error; + } + return add_point1( builder, x, y ); + } + + + /* close the current contour */ + static + void close_contour( Z1_Builder* builder ) + { + FT_Outline* outline = builder->current; + + + /* XXX: 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; + + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* lookup_glyph_by_stdcharcode */ + /* */ + /* */ + /* Looks up a given glyph by its StandardEncoding charcode. Used */ + /* to implement the SEAC Type 1 operator. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + static + FT_Int lookup_glyph_by_stdcharcode( T1_Face face, + FT_Int charcode ) + { + FT_Int n; + const FT_String* glyph_name; + PSNames_Interface* psnames = (PSNames_Interface*)face->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 < face->type1.num_glyphs; n++ ) + { + FT_String* name = (FT_String*)face->type1.glyph_names[n]; + + + if ( name && strcmp( name,glyph_name ) == 0 ) + return n; + } + + return -1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_seac */ + /* */ + /* */ + /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error t1operator_seac( Z1_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; + T1_Face face = decoder->builder.face; + T1_Font* type1 = &face->type1; + + + bchar_index = lookup_glyph_by_stdcharcode( face, bchar ); + achar_index = lookup_glyph_by_stdcharcode( face, achar ); + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return T1_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->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 = Z1_Parse_CharStrings( decoder, + type1->charstrings [bchar_index], + type1->charstrings_len[bchar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + 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 = Z1_Parse_CharStrings( decoder, + type1->charstrings [achar_index], + type1->charstrings_len[achar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + return error; + + /* 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 = base->n_points - n_base_points; + dummy.points = base->points + n_base_points; + FT_Outline_Translate( &dummy, adx - asb, ady ); + } + + Exit: + return error; + } + + +#define USE_ARGS( n ) do \ + { \ + top -= n; \ + if ( top < decoder->stack ) \ + goto Stack_Underflow; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given Type 1 charstrings program. */ + /* */ + /* */ + /* 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. */ + /* */ + /* num_subrs :: The number of sub-routines. */ + /* */ + /* subrs_base :: An array of sub-routines addresses. */ + /* */ + /* subrs_len :: An array of sub-routines lengths. */ + /* */ + /* */ + /* Free error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ) + { + FT_Error error; + Z1_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + Z1_Builder* builder = &decoder->builder; + FT_Outline* outline; + FT_Pos x, y; + + + /* 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 = T1_Err_Ok; + outline = builder->current; + + x = builder->pos_x; + y = builder->pos_y; + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Int* top = decoder->top; + Z1_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(( "Z1_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(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + break; + + case 255: /* four bytes integer */ + if ( ip + 4 > limit ) + { + FT_ERROR(( "Z1_Parse_CharStrings: unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = ( (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(( "Z1_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(( "Z1_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(( "Z1_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(( "Z1_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(( "Z1_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(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if ( ip[0] != 12 || ip[1] != 17 ) + { + FT_ERROR(( "Z1_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_Int* delta; + FT_Int* values; + + + if ( !blend ) + { + FT_ERROR(( "Z1_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(( "Z1_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 x = values[0]; + + + for ( mm = 1; mm < blend->num_designs; mm++ ) + x += FT_MulFix( *delta++, blend->weight_vector[mm] ); + + *values++ = x; + } + /* note that `top' will be incremented later by calls to `pop' */ + break; + } + + default: + Unexpected_OtherSubr: + FT_ERROR(( "Z1_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 T1_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 T1_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 T1_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]; + 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]; + 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]; + break; + + case op_div: + FT_TRACE4(( " div" )); + + if ( top[1] ) + { + *top = top[0] / top[1]; + ++top; + } + else + { + FT_ERROR(( "Z1_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 >= num_subrs ) + { + FT_ERROR(( "Z1_Parse_CharStrings: invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "Z1_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = subrs_base[index]; + zone->limit = zone->base + subrs_len[index]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "Z1_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" )); + + /* theorically, the arguments are already on the stack */ + top++; + break; + + case op_return: + FT_TRACE4(( " return" )); + + if ( zone <= decoder->zones ) + { + FT_ERROR(( "Z1_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(( "Z1_Parse_CharStrings:" )); + FT_ERROR(( " unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + + default: + FT_ERROR(( "Z1_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 T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + + 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. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error Z1_Compute_Max_Advance( T1_Face face, + FT_Int* max_advance ) + { + FT_Error error; + Z1_Decoder decoder; + FT_Int glyph_index; + T1_Font* type1 = &face->type1; + + + *max_advance = 0; + + /* Initialize load decoder */ + Z1_Init_Decoder( &decoder ); + Z1_Init_Builder( &decoder.builder, face, 0, 0 ); + + decoder.blend = face->blend; + 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 < type1->num_glyphs; glyph_index++ ) + { + /* now get load the unscaled outline */ + error = Z1_Parse_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + /* 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' *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph, + Z1_Size size, + FT_Int glyph_index, + FT_Int load_flags ) + { + FT_Error error; + Z1_Decoder decoder; + T1_Face face = (T1_Face)glyph->root.face; + FT_Bool hinting; + T1_Font* type1 = &face->type1; + + + 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 = ( load_flags & FT_LOAD_NO_SCALE ) == 0 && + ( load_flags & FT_LOAD_NO_HINTING ) == 0; + + glyph->root.format = ft_glyph_format_outline; + + Z1_Init_Decoder( &decoder ); + Z1_Init_Builder( &decoder.builder, face, size, glyph ); + + decoder.blend = ((T1_Face)glyph->root.face)->blend; + decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0; + + /* now load the unscaled outline */ + error = Z1_Parse_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + + /* save new glyph tables */ + Z1_Done_Builder( &decoder.builder ); + + /* 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 ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.builder.advance.x; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.format = ft_glyph_format_outline; + + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= ft_outline_high_precision; + +#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 ); + } + + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, + &face->type1.font_matrix ); + + /* 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/reactos/subsys/win32k/freetype/src/type1z/z1gload.h b/reactos/subsys/win32k/freetype/src/type1z/z1gload.h new file mode 100644 index 00000000000..5bb6dc0a25a --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1gload.h @@ -0,0 +1,187 @@ +/***************************************************************************/ +/* */ +/* z1gload.h */ +/* */ +/* Experimental Type 1 Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1GLOAD_H +#define Z1GLOAD_H + + +#ifdef FT_FLAT_COMPILE + +#include "z1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* loader :: The current glyph loader. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* base :: The base glyph 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 (for composite glyphs). */ + /* */ + /* pos_y :: The vertical translation (for composite glyphs). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* no_recurse :: */ + /* */ + /* bbox :: The glyph's bounding box. */ + /* */ + /* path_begun :: A flag which indicates that a new path has begun. */ + /* */ + /* load_points :: A flag which indicates, if not set, that no points */ + /* are loaded. */ + /* */ + /* error :: The current error code. */ + /* */ + /* metrics_only :: A flag whether to compute metrics only. */ + /* */ + typedef struct Z1_Builder_ + { + FT_Memory memory; + T1_Face face; + Z1_GlyphSlot glyph; + FT_GlyphLoader* loader; + + FT_Outline* current; /* the current glyph outline */ + FT_Outline* base; /* the composite glyph outline */ + + 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; + + } Z1_Builder; + + + /* execution context charstring zone */ + typedef struct Z1_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } Z1_Decoder_Zone; + + + typedef struct Z1_Decoder_ + { + Z1_Builder builder; + + FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS]; + FT_Int* top; + + Z1_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1]; + Z1_Decoder_Zone* zone; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + T1_Blend* blend; /* for multiple masters */ + + } Z1_Decoder; + + + LOCAL_DEF + void Z1_Init_Builder( Z1_Builder* builder, + T1_Face face, + Z1_Size size, + Z1_GlyphSlot glyph ); + + LOCAL_DEF + void Z1_Done_Builder( Z1_Builder* builder ); + + LOCAL_DEF + void Z1_Init_Decoder( Z1_Decoder* decoder ); + + LOCAL_DEF + FT_Error Z1_Compute_Max_Advance( T1_Face face, + FT_Int* max_advance ); + + LOCAL_DEF + FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ); + + LOCAL_DEF + FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph, + Z1_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* Z1GLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/z1load.c b/reactos/subsys/win32k/freetype/src/type1z/z1load.c new file mode 100644 index 00000000000..46478d1a85f --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1load.c @@ -0,0 +1,1725 @@ +/***************************************************************************/ +/* */ +/* z1load.c */ +/* */ +/* Experimental Type 1 font loader (body). */ +/* */ +/* Copyright 1996-2000 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 ... */ + /* */ + /* where 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 +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1load.h" + +#else + +#include + +#endif + + +#include /* for strncmp(), strcmp() */ +#include /* 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_z1load + + +#ifndef Z1_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; + } + + + LOCAL_FUNC + FT_Error Z1_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; + } + + + LOCAL_FUNC + FT_Error Z1_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 = FT_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 = FT_Err_Ok; + } + return error; + } + + + LOCAL_FUNC + FT_Error Z1_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 < 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 = Z1_Set_MM_Blend( face, num_coords, final_blends ); + } + + return error; + } + + + LOCAL_FUNC + void Z1_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, + Z1_Loader* loader ) + { + Z1_Token_Rec 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 */ + Z1_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++ ) + { + Z1_Token_Rec* token = axis_tokens + n; + FT_Byte* name; + FT_Int len; + + /* skip first slash, if any */ + if (token->start[0] == '/') + token->start++; + + len = 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.error = error; + } + + + static + void parse_blend_design_positions( T1_Face face, + Z1_Loader* loader ) + { + Z1_Token_Rec design_tokens[ T1_MAX_MM_DESIGNS ]; + FT_Int num_designs; + FT_Int num_axis; + Z1_Parser* parser = &loader->parser; + + FT_Error error = 0; + T1_Blend* blend; + + + /* get the array of design tokens - compute number of designs */ + Z1_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->cursor; + FT_Byte* old_limit = parser->limit; + FT_UInt n; + + + blend = face->blend; + num_axis = 0; /* make compiler happy */ + + for ( n = 0; n < (FT_UInt)num_designs; n++ ) + { + Z1_Token_Rec axis_tokens[ T1_MAX_MM_DESIGNS ]; + Z1_Token_Rec* token; + FT_Int axis, n_axis; + + + /* read axis/coordinates tokens */ + token = design_tokens + n; + parser->cursor = token->start - 1; + parser->limit = token->limit + 1; + Z1_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++ ) + { + Z1_Token_Rec* token2 = axis_tokens + axis; + + + parser->cursor = token2->start; + parser->limit = token2->limit; + blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 ); + } + } + + loader->parser.cursor = old_cursor; + loader->parser.limit = old_limit; + } + + Exit: + loader->parser.error = error; + } + + + static + void parse_blend_design_map( T1_Face face, + Z1_Loader* loader ) + { + FT_Error error = 0; + Z1_Parser* parser = &loader->parser; + T1_Blend* blend; + Z1_Token_Rec 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; + + + Z1_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->cursor; + old_limit = parser->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; + Z1_Token_Rec* token; + FT_Int p, num_points; + + + token = axis_tokens + n; + parser->cursor = token->start; + parser->limit = token->limit; + + /* count the number of map points */ + { + FT_Byte* p = token->start; + FT_Byte* limit = token->limit; + + + num_points = 0; + for ( ; p < limit; p++ ) + if ( p[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] = Z1_ToInt( parser ); + map->blend_points [p] = Z1_ToFixed( parser, 0 ); + } + } + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + parser->error = error; + } + + + static + void parse_weight_vector( T1_Face face, + Z1_Loader* loader ) + { + FT_Error error = 0; + Z1_Parser* parser = &loader->parser; + T1_Blend* blend = face->blend; + Z1_Token_Rec 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; + } + + Z1_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->cursor; + old_limit = parser->limit; + + parser->cursor = master.start; + parser->limit = master.limit; + + for ( n = 0; n < blend->num_designs; n++ ) + { + blend->default_weight_vector[n] = + blend->weight_vector[n] = Z1_ToFixed( parser, 0 ); + } + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + parser->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, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + + FT_UNUSED( face ); + + + parser->cursor = parser->limit; + parser->error = 0; + } + +#endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 1 SYMBOL PARSING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* First of all, define the token field static variables. This is a set */ + /* of Z1_Field_Rec variables used later. */ + /* */ + /*************************************************************************/ + +#define Z1_NEW_STRING( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_STRING( T1TYPE, _field ); + +#define Z1_NEW_BOOL( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_BOOL( T1TYPE, _field ); + +#define Z1_NEW_NUM( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM( T1TYPE, _field ); + +#define Z1_NEW_FIXED( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED( T1TYPE, _field, _power ); + +#define Z1_NEW_NUM_TABLE( _name, _field, _max, _count ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max ); + +#define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max ); + +#define Z1_NEW_NUM_TABLE2( _name, _field, _max ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max ); + +#define Z1_NEW_FIXED_TABLE2( _name, _field, _max ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max ); + + +#define Z1_FONTINFO_STRING( n, f ) Z1_NEW_STRING( n, f ) +#define Z1_FONTINFO_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_FONTINFO_BOOL( n, f ) Z1_NEW_BOOL( n, f ) +#define Z1_PRIVATE_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_PRIVATE_FIXED( n, f ) Z1_NEW_FIXED( n, f ) +#define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_NEW_NUM_TABLE( n, f, m, c ) +#define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_NEW_NUM_TABLE2( n, f, m ) +#define Z1_TOPDICT_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_NEW_FIXED_TABLE2( n, f, m ) + + + /* including this file defines all field variables */ +#ifdef FT_FLAT_COMPILE + +#include "z1tokens.h" + +#else + +#include + +#endif + + + /*************************************************************************/ + /* */ + /* Second, define the keyword variables. This is a set of Z1_KeyWord */ + /* structures used to model the way each keyword is `loaded'. */ + /* */ + /*************************************************************************/ + + typedef void (*Z1_Parse_Func)( T1_Face face, + Z1_Loader* loader ); + + + typedef enum Z1_KeyWord_Type_ + { + t1_keyword_callback = 0, + t1_keyword_field, + t1_keyword_field_table + + } Z1_KeyWord_Type; + + + typedef enum Z1_KeyWord_Location_ + { + t1_keyword_type1 = 0, + t1_keyword_font_info, + t1_keyword_private + + } Z1_KeyWord_Location; + + + typedef struct Z1_KeyWord_ + { + const char* name; + Z1_KeyWord_Type type; + Z1_KeyWord_Location location; + Z1_Parse_Func parsing; + const Z1_Field_Rec* field; + + } Z1_KeyWord; + + +#define Z1_KEYWORD_CALLBACK( name, callback ) \ + { \ + name, t1_keyword_callback, t1_keyword_type1, callback, 0 \ + } + +#define Z1_KEYWORD_TYPE1( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f \ + } + +#define Z1_KEYWORD_FONTINFO( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f \ + } + +#define Z1_KEYWORD_PRIVATE( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f \ + } + +#define Z1_KEYWORD_FONTINFO_TABLE( name, f ) \ + { \ + name, t1_keyword_field_table, t1_keyword_font_info, 0, \ + &t1_field_ ## f \ + } + +#define Z1_KEYWORD_PRIVATE_TABLE( name, f ) \ + { \ + name, t1_keyword_field_table, t1_keyword_private, 0, \ + &t1_field_ ## f \ + } + + +#undef Z1_FONTINFO_STRING +#undef Z1_FONTINFO_NUM +#undef Z1_FONTINFO_BOOL +#undef Z1_PRIVATE_NUM +#undef Z1_PRIVATE_FIXED +#undef Z1_PRIVATE_NUM_TABLE +#undef Z1_PRIVATE_NUM_TABLE2 +#undef Z1_TOPDICT_NUM +#undef Z1_TOPDICT_NUM_FIXED2 + +#define Z1_FONTINFO_STRING( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_FONTINFO_NUM( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_FONTINFO_BOOL( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_PRIVATE_NUM( n, f ) Z1_KEYWORD_PRIVATE( n, f ), +#define Z1_PRIVATE_FIXED( n, f ) Z1_KEYWORD_PRIVATE( n, f ), +#define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_KEYWORD_PRIVATE_TABLE( n, f ), +#define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_KEYWORD_PRIVATE_TABLE( n, f ), +#define Z1_TOPDICT_NUM( n, f ) Z1_KEYWORD_TYPE1( n, f ), +#define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_KEYWORD_TYPE1( n, f ), + + + static + FT_Error t1_load_keyword( T1_Face face, + Z1_Loader* loader, + Z1_KeyWord* keyword ) + { + 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 ( keyword->type == t1_keyword_callback ) + { + keyword->parsing( face, loader ); + error = loader->parser.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 ( keyword->location ) + { + case t1_keyword_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_keyword_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 ( keyword->type == t1_keyword_field_table ) + error = Z1_Load_Field_Table( &loader->parser, keyword->field, + objects, max_objects, 0 ); + else + error = Z1_Load_Field( &loader->parser, keyword->field, + objects, max_objects, 0 ); + + Exit: + return error; + } + + + static + int is_space( char c ) + { + return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ); + } + + + static + int is_alpha( char c ) + { + return ( isalnum( c ) || + ( c == '.' ) || + ( c == '_' ) ); + } + + + static + void skip_whitespace( Z1_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + + + while ( cur < parser->limit && is_space( *cur ) ) + cur++; + + parser->cursor = cur; + } + + + static + void skip_blackspace( Z1_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + + while ( cur < parser->limit && !is_space( *cur ) ) + cur++; + + parser->cursor = cur; + } + + + static + int read_binary_data( Z1_Parser* parser, + FT_Int* size, + FT_Byte** base ) + { + FT_Byte* cur; + FT_Byte* limit = parser->limit; + + + /* the binary data has the following format */ + /* */ + /* `size' [white*] RD white ....... ND */ + /* */ + + skip_whitespace( parser ); + cur = parser->cursor; + + if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 ) + { + *size = Z1_ToInt( parser ); + + skip_whitespace( parser ); + skip_blackspace( parser ); /* `RD' or `-|' or something else */ + + /* there is only one whitespace char after the */ + /* `RD' or `-|' token */ + *base = parser->cursor + 1; + + parser->cursor += *size+1; + return 1; + } + + FT_ERROR(( "read_binary_data: invalid size field\n" )); + parser->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, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Error error; + FT_Memory memory = parser->memory; + FT_Int len; + FT_Byte* cur; + FT_Byte* cur2; + FT_Byte* limit; + + + skip_whitespace( parser ); + + cur = parser->cursor; + limit = parser->limit; + + if ( cur >= limit - 1 || *cur != '/' ) + return; + + cur++; + cur2 = cur; + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + + len = cur2 - cur; + if ( len > 0 ) + { + if ( ALLOC( face->type1.font_name, len + 1 ) ) + { + parser->error = error; + return; + } + + MEM_Copy( face->type1.font_name, cur, len ); + face->type1.font_name[len] = '\0'; + } + parser->cursor = cur2; + } + + + static + void parse_font_bbox( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Short temp[4]; + FT_BBox* bbox = &face->type1.font_bbox; + + + (void)Z1_ToCoordArray( parser, 4, temp ); + bbox->xMin = temp[0]; + bbox->yMin = temp[1]; + bbox->xMax = temp[2]; + bbox->yMax = temp[3]; + } + + + static + void parse_font_matrix( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Matrix* matrix = &face->type1.font_matrix; + FT_Fixed temp[4]; + + + (void)Z1_ToFixedArray( parser, 4, temp, 3 ); + matrix->xx = temp[0]; + matrix->yx = temp[1]; + matrix->xy = temp[2]; + matrix->yy = temp[3]; + } + + + static + void parse_encoding( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + /* skip whitespace */ + while ( is_space( *cur ) ) + { + cur++; + if ( cur >= limit ) + { + FT_ERROR(( "parse_encoding: out of bounds!\n" )); + parser->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; + Z1_Table* char_table = &loader->encoding_table; + FT_Memory memory = parser->memory; + FT_Error error; + + + /* read the number of entries in the encoding, should be 256 */ + count = Z1_ToInt( parser ); + if ( parser->error ) + return; + + /* we use a Z1_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 = Z1_New_Table( char_table, count, memory ) ) != 0 ) + { + parser->error = error; + return; + } + + /* 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->cursor; + limit = parser->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->cursor = cur; + charcode = Z1_ToInt( parser ); + cur = parser->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 = cur2 - cur - 1; + + parser->error = Z1_Add_Table( char_table, charcode, + cur + 1, len + 1 ); + char_table->elements[charcode][len] = '\0'; + if ( parser->error ) + return; + + cur = cur2; + } + } + else + cur++; + } + + face->type1.encoding_type = t1_encoding_array; + parser->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->error = T1_Err_Invalid_File_Format; + } + } + } + + + static + void parse_subrs( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + Z1_Table* table = &loader->subrs; + FT_Memory memory = parser->memory; + FT_Error error; + FT_Int n; + + + loader->num_subrs = Z1_ToInt( parser ); + if ( parser->error ) + return; + + /* position the parser right before the `dup' of the first subr */ + skip_whitespace( parser ); + skip_blackspace( parser ); /* `array' */ + skip_whitespace( parser ); + + /* initialize subrs array */ + error = Z1_New_Table( 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->cursor, "dup", 3 ) != 0 ) + break; + + index = Z1_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. */ + skip_whitespace( parser ); + skip_blackspace( parser ); /* `NP' or `I' or `noaccess' */ + skip_whitespace( parser ); + + if ( strncmp( (char*)parser->cursor, "put", 3 ) == 0 ) + { + skip_blackspace( parser ); /* skip `put' */ + skip_whitespace( 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 ) + { + Z1_Decrypt( base, size, 4330 ); + size -= face->type1.private_dict.lenIV; + base += face->type1.private_dict.lenIV; + } + + error = Z1_Add_Table( table, index, base, size ); + if ( error ) + goto Fail; + } + return; + + Fail: + parser->error = error; + } + + + static + void parse_charstrings( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + Z1_Table* code_table = &loader->charstrings; + Z1_Table* name_table = &loader->glyph_names; + FT_Memory memory = parser->memory; + FT_Error error; + + FT_Byte* cur; + FT_Byte* limit = parser->limit; + FT_Int n; + + + loader->num_glyphs = Z1_ToInt( parser ); + if ( parser->error ) + return; + + /* initialize tables */ + error = Z1_New_Table( code_table, loader->num_glyphs, memory ) || + Z1_New_Table( name_table, loader->num_glyphs, 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' */ + /* */ + skip_whitespace( parser ); + + cur = parser->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 != '/' ) + skip_blackspace( parser ); + else + { + FT_Byte* cur2 = cur + 1; + FT_Int len; + + + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + len = cur2 - cur - 1; + + error = Z1_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'; + + parser->cursor = cur2; + if ( !read_binary_data( parser, &size, &base ) ) + return; + + if ( face->type1.private_dict.lenIV >= 0 ) + { + Z1_Decrypt( base, size, 4330 ); + size -= face->type1.private_dict.lenIV; + base += face->type1.private_dict.lenIV; + } + + error = Z1_Add_Table( code_table, n, base, size ); + if ( error ) + goto Fail; + + n++; + if ( n >= loader->num_glyphs ) + break; + } + } + loader->num_glyphs = n; + return; + + Fail: + parser->error = error; + } + + + static + const Z1_KeyWord t1_keywords[] = + { + +#ifdef FT_FLAT_COMPILE + +#include "z1tokens.h" + +#else + +#include + +#endif + + /* now add the special functions... */ + Z1_KEYWORD_CALLBACK( "FontName", parse_font_name ), + Z1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox ), + Z1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix ), + Z1_KEYWORD_CALLBACK( "Encoding", parse_encoding ), + Z1_KEYWORD_CALLBACK( "Subrs", parse_subrs ), + Z1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ), + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + Z1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ), + Z1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map ), + Z1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ), + Z1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector ), + Z1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ), +#endif + + Z1_KEYWORD_CALLBACK( 0, 0 ) + }; + + + static + FT_Error parse_dict( T1_Face face, + Z1_Loader* loader, + FT_Byte* base, + FT_Long size ) + { + Z1_Parser* parser = &loader->parser; + + + parser->cursor = base; + parser->limit = base + size; + parser->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 ) + { + Z1_Token_Rec token; + + + /* skip the `known' keyword and the token following it */ + cur += 5; + loader->parser.cursor = cur; + Z1_ToToken( &loader->parser, &token ); + + /* if the last token was an array, skip it! */ + if ( token.type == t1_token_array ) + cur2 = parser->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 = cur2 - cur; + if ( len > 0 && len < 22 ) + { + if ( !loader->fontdata ) + { + if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 ) + loader->fontdata = 1; + } + else + { + /* now, compare the immediate name to the keyword table */ + Z1_KeyWord* keyword = (Z1_KeyWord*)t1_keywords; + + + for (;;) + { + FT_Byte* name; + + + name = (FT_Byte*)keyword->name; + 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->cursor = cur2; + skip_whitespace( parser ); + parser->error = t1_load_keyword( face, loader, keyword ); + if ( parser->error ) + return parser->error; + + cur = parser->cursor; + break; + } + } + keyword++; + } + } + } + } + } + } + return parser->error; + } + + + static + void t1_init_loader( Z1_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->fontdata = 0; + } + + + static + void t1_done_loader( Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + + + /* finalize tables */ + Z1_Release_Table( &loader->encoding_table ); + Z1_Release_Table( &loader->charstrings ); + Z1_Release_Table( &loader->glyph_names ); + Z1_Release_Table( &loader->subrs ); + + /* finalize parser */ + Z1_Done_Parser( parser ); + } + + + LOCAL_FUNC + FT_Error Z1_Open_Face( T1_Face face ) + { + Z1_Loader loader; + Z1_Parser* parser; + T1_Font* type1 = &face->type1; + FT_Error error; + + + t1_init_loader( &loader, face ); + + /* default lenIV */ + type1->private_dict.lenIV = 4; + + parser = &loader.parser; + error = Z1_New_Parser( parser, face->root.stream, face->root.memory ); + if ( error ) + goto Exit; + + error = parse_dict( face, &loader, parser->base_dict, parser->base_len ); + if ( error ) + goto Exit; + + error = Z1_Get_Private_Dict( parser ); + 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 ) + { + FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" )); + error = T1_Err_Invalid_File_Format; + } + + if ( !loader.charstrings.init ) + { + FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" )); + error = T1_Err_Invalid_File_Format; + } + + 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; + + 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.num_elems; charcode++ ) + { + type1->encoding.char_index[charcode] = 0; + type1->encoding.char_name [charcode] = ".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] = index; + type1->encoding.char_name [charcode] = (char*)glyph_name; + + 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/reactos/subsys/win32k/freetype/src/type1z/z1load.h b/reactos/subsys/win32k/freetype/src/type1z/z1load.h new file mode 100644 index 00000000000..672b5531b66 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1load.h @@ -0,0 +1,93 @@ +/***************************************************************************/ +/* */ +/* z1load.h */ +/* */ +/* Experimental Type 1 font loader (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1LOAD_H +#define Z1LOAD_H + +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1parse.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + typedef struct Z1_Loader_ + { + Z1_Parser parser; /* parser used to read the stream */ + + FT_Int num_chars; /* number of characters in encoding */ + Z1_Table encoding_table; /* Z1_Table used to store the */ + /* encoding character names */ + + FT_Int num_glyphs; + Z1_Table glyph_names; + Z1_Table charstrings; + + FT_Int num_subrs; + Z1_Table subrs; + FT_Bool fontdata; + + } Z1_Loader; + + + LOCAL_DEF + FT_Error Z1_Open_Face( T1_Face face ); + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + + LOCAL_DEF + FT_Error Z1_Get_Multi_Master( T1_Face face, + FT_Multi_Master* master ); + + LOCAL_DEF + FT_Error Z1_Set_MM_Blend( T1_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + LOCAL_DEF + FT_Error Z1_Set_MM_Design( T1_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + LOCAL_DEF + void Z1_Done_Blend( T1_Face face ); + +#endif /* !Z1_CONFIG_OPTION_NO_MM_SUPPORT */ + + +#ifdef __cplusplus + } +#endif + +#endif /* Z1LOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/z1objs.c b/reactos/subsys/win32k/freetype/src/type1z/z1objs.c new file mode 100644 index 00000000000..e452bb5eddd --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1objs.c @@ -0,0 +1,398 @@ +/***************************************************************************/ +/* */ +/* z1objs.c */ +/* */ +/* Experimental Type 1 objects manager (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1gload.h" +#include "z1load.h" +#include "z1afm.h" + +#else + +#include +#include +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* 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_z1objs + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Face */ + /* */ + /* */ + /* The face object destructor. */ + /* */ + /* */ + /* face :: A typeless pointer to the face object to destroy. */ + /* */ + LOCAL_FUNC + void Z1_Done_Face( T1_Face face ) + { + FT_Memory memory; + T1_Font* type1 = &face->type1; + + + if ( face ) + { + memory = face->root.memory; + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + /* release multiple masters information */ + Z1_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->font_name ); + +#ifndef Z1_CONFIG_OPTION_NO_AFM + /* release afm data if present */ + if ( face->afm_data ) + Z1_Done_AFM( memory, (Z1_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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Face */ + /* */ + /* */ + /* The face object constructor. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: The face record to build. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_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; + + 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; + } + + /* open the tokenizer, this will also check the font format */ + error = Z1_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(( "Z1_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 = "Regular"; + } + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox = face->type1.font_bbox; + root->units_per_EM = 1000; + root->ascender = (FT_Short)face->type1.font_bbox.yMax; + root->descender = -(FT_Short)face->type1.font_bbox.yMin; + root->height = ( ( root->ascender + root->descender ) * 12 ) / 10; + + /* 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 = Z1_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; + + root->underline_position = face->type1.font_info.underline_position; + root->underline_thickness = face->type1.font_info.underline_thickness; + + root->max_points = 0; + root->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 ( 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 = FT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Driver */ + /* */ + /* */ + /* Initializes a given Type 1 driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_Init_Driver( Z1_Driver driver ) + { + FT_UNUSED( driver ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Driver */ + /* */ + /* */ + /* Finalizes a given Type 1 driver. */ + /* */ + /* */ + /* driver :: A handle to the target Type 1 driver. */ + /* */ + LOCAL_DEF + void Z1_Done_Driver( Z1_Driver driver ) + { + FT_UNUSED( driver ); + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/z1objs.h b/reactos/subsys/win32k/freetype/src/type1z/z1objs.h new file mode 100644 index 00000000000..c655a673180 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1objs.h @@ -0,0 +1,161 @@ +/***************************************************************************/ +/* */ +/* z1objs.h */ +/* */ +/* Experimental Type 1 objects manager (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1OBJS_H +#define Z1OBJS_H + +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + /* The following structures must be defined by the hinter */ + typedef struct Z1_Size_Hints_ Z1_Size_Hints; + typedef struct Z1_Glyph_Hints_ Z1_Glyph_Hints; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Driver */ + /* */ + /* */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct Z1_DriverRec_ *Z1_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Size */ + /* */ + /* */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct Z1_SizeRec_* Z1_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_GlyphSlot */ + /* */ + /* */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct Z1_GlyphSlotRec_* Z1_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_CharMap */ + /* */ + /* */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* */ + /* 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 Z1_CharMapRec_* Z1_CharMap; + + + /*************************************************************************/ + /* */ + /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_SizeRec */ + /* */ + /* */ + /* Type 1 size record. */ + /* */ + typedef struct Z1_SizeRec_ + { + FT_SizeRec root; + FT_Bool valid; + Z1_Size_Hints* hints; /* defined in the hinter. This allows */ + /* us to experiment with different */ + /* hinting schemes without having to */ + /* change `z1objs' each time. */ + } Z1_SizeRec; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_GlyphSlotRec */ + /* */ + /* */ + /* Type 1 glyph slot record. */ + /* */ + typedef struct Z1_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; + + Z1_Glyph_Hints* hints; /* defined in the hinter */ + + } Z1_GlyphSlotRec; + + + LOCAL_DEF + FT_Error Z1_Init_Face( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void Z1_Done_Face( T1_Face face ); + + LOCAL_DEF + FT_Error Z1_Init_Driver( Z1_Driver driver ); + + LOCAL_DEF + void Z1_Done_Driver( Z1_Driver driver ); + + +#ifdef __cplusplus + } +#endif + +#endif /* Z1OBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/z1parse.c b/reactos/subsys/win32k/freetype/src/type1z/z1parse.c new file mode 100644 index 00000000000..9bc29138744 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1parse.c @@ -0,0 +1,1398 @@ +/***************************************************************************/ +/* */ +/* z1parse.c */ +/* */ +/* Experimental Type 1 parser (body). */ +/* */ +/* Copyright 1996-2000 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 `Z1_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 `z1load.c' to see how data is loaded from the font file. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1parse.h" + +#else + +#include + +#endif + + +#include /* 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_z1parse + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** IMPLEMENTATION OF Z1_TABLE OBJECT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_New_Table */ + /* */ + /* */ + /* Initialises a Z1_Table. */ + /* */ + /* */ + /* table :: The address of the target table. */ + /* */ + /* */ + /* count :: The table size = the maximum number of elements. */ + /* */ + /* memory :: The memory object to use for all subsequent */ + /* reallocations. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_New_Table( Z1_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 = 0xdeadbeef; + table->num_elems = 0; + table->block = 0; + table->capacity = 0; + table->cursor = 0; + + Exit: + if ( error ) + FREE( table->elements ); + + return error; + } + + + static + void shift_elements( Z1_Table* table, + FT_Byte* old_base ) + { + FT_Long delta = table->block - old_base; + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + if ( delta ) + for ( ; offset < limit; offset++ ) + { + if ( offset[0] ) + offset[0] += delta; + } + } + + + static + FT_Error reallocate_t1_table( Z1_Table* table, + FT_Int new_size ) + { + FT_Memory memory = table->memory; + FT_Byte* old_base = table->block; + FT_Error error; + + + /* reallocate the base block */ + if ( REALLOC( table->block, table->capacity, new_size ) ) + return error; + + table->capacity = new_size; + + /* shift all offsets if necessary */ + if ( old_base ) + shift_elements( table, old_base ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Add_Table */ + /* */ + /* */ + /* Adds an object to a Z1_Table, possibly growing its memory block. */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. An error is returned if a */ + /* reallocation fails. */ + /* */ + LOCAL_FUNC + FT_Error Z1_Add_Table( Z1_Table* table, + FT_Int index, + void* object, + FT_Int length ) + { + if ( index < 0 || index > table->max_elems ) + { + FT_ERROR(( "Z1_Add_Table: invalid index\n" )); + return T1_Err_Syntax_Error; + } + + /* grow the base block if needed */ + if ( table->cursor + length > table->capacity ) + { + FT_Error error; + FT_Int new_size = table->capacity; + + + while ( new_size < table->cursor + length ) + new_size += 1024; + + error = reallocate_t1_table( table, new_size ); + if ( error ) + return error; + } + + /* 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 T1_Err_Ok; + } + + +#if 0 + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Table */ + /* */ + /* */ + /* Finalizes a Z1_Table (i.e., reallocate it to its current cursor). */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* 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. */ + /* */ + LOCAL_FUNC + void Z1_Done_Table( Z1_Table* table ) + { + FT_Memory memory = table->memory; + FT_Error error; + FT_Byte* old_base; + + + /* should never fail, as rec.cursor <= rec.size */ + old_base = table->block; + if ( !old_base ) + return; + + (void)REALLOC( table->block, table->capacity, table->cursor ); + table->capacity = table->cursor; + + if ( old_base != table->block ) + shift_elements( table, old_base ); + } + +#endif /* 0 */ + + + LOCAL_FUNC + void Z1_Release_Table( Z1_Table* table ) + { + FT_Memory memory = table->memory; + + + if ( table->init == (FT_Long)0xDEADBEEF ) + { + FREE( table->block ); + FREE( table->elements ); + FREE( table->lengths ); + table->init = 0; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** INPUT STREAM PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define IS_Z1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' ) +#define IS_Z1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' ) + +#define IS_Z1_SPACE( c ) ( IS_Z1_WHITESPACE( c ) || IS_Z1_LINESPACE( c ) ) + + + LOCAL_FUNC + void Z1_Skip_Spaces( Z1_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( !IS_Z1_SPACE( c ) ) + break; + cur++; + } + parser->cursor = cur; + } + + + LOCAL_FUNC + void Z1_ToToken( Z1_Parser* parser, + Z1_Token_Rec* 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 */ + Z1_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_Z1_SPACE( *cur ) ) + cur++; + + token->limit = cur; + } + + if ( !token->limit ) + { + token->start = 0; + token->type = t1_token_none; + } + + parser->cursor = cur; + } + } + + + LOCAL_FUNC + void Z1_ToTokenArray( Z1_Parser* parser, + Z1_Token_Rec* tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ) + { + Z1_Token_Rec master; + + + *pnum_tokens = -1; + + Z1_ToToken( parser, &master ); + if ( master.type == t1_token_array ) + { + FT_Byte* old_cursor = parser->cursor; + FT_Byte* old_limit = parser->limit; + Z1_Token_Rec* cur = tokens; + Z1_Token_Rec* limit = cur + max_tokens; + + + parser->cursor = master.start; + parser->limit = master.limit; + + while ( parser->cursor < parser->limit ) + { + Z1_Token_Rec token; + + + Z1_ToToken( parser, &token ); + if ( !token.type ) + break; + + if ( cur < limit ) + *cur = token; + + cur++; + } + + *pnum_tokens = 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, 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, read the integer part */ + result = t1_toint( &cur, limit ) << 16; + num = 0; + divider = 1; + + if ( result < 0 ) + { + sign = 1; + result = -result; + } + + 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 */ + LOCAL_FUNC + FT_Error Z1_Load_Field( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ) + { + Z1_Token_Rec token; + FT_Byte* cur; + FT_Byte* limit; + FT_UInt count; + FT_UInt index; + FT_Error error; + + + Z1_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 = limit-cur; + + 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 ( pflags ) + *pflags |= 1L << field->flag_bit; + + error = FT_Err_Ok; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + +#define T1_MAX_TABLE_ELEMENTS 32 + + + LOCAL_FUNC + FT_Error Z1_Load_Field_Table( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ) + { + Z1_Token_Rec elements[T1_MAX_TABLE_ELEMENTS]; + Z1_Token_Rec* token; + FT_Int num_elements; + FT_Error error = 0; + FT_Byte* old_cursor; + FT_Byte* old_limit; + Z1_Field_Rec fieldrec = *(Z1_Field_Rec*)field; + + + Z1_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 ) = 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; + Z1_Load_Field( parser, &fieldrec, objects, max_objects, 0 ); + fieldrec.offset += fieldrec.size; + } + + if ( pflags ) + *pflags |= 1L << field->flag_bit; + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + + LOCAL_FUNC + FT_Long Z1_ToInt ( Z1_Parser* parser ) + { + return t1_toint( &parser->cursor, parser->limit ); + } + + + LOCAL_FUNC + FT_Long Z1_ToFixed( Z1_Parser* parser, + FT_Int power_ten ) + { + return t1_tofixed( &parser->cursor, parser->limit, power_ten ); + } + + + LOCAL_FUNC + FT_Int Z1_ToCoordArray( Z1_Parser* parser, + FT_Int max_coords, + FT_Short* coords ) + { + return t1_tocoordarray( &parser->cursor, parser->limit, + max_coords, coords ); + } + + + LOCAL_FUNC + FT_Int Z1_ToFixedArray( Z1_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 + + LOCAL_FUNC + FT_String* Z1_ToString( Z1_Parser* parser ) + { + return t1_tostring( &parser->cursor, parser->limit, parser->memory ); + } + + + LOCAL_FUNC + FT_Bool Z1_ToBool( Z1_Parser* parser ) + { + return t1_tobool( &parser->cursor, parser->limit ); + } + +#endif /* 0 */ + + + static + FT_Error read_pfb_tag( FT_Stream stream, + FT_UShort* tag, + FT_Long* size ) + { + FT_Error error; + + + if ( READ_UShort( *tag ) ) + goto Exit; + + if ( *tag == 0x8001 || *tag == 0x8002 ) + { + FT_Long asize; + + + if ( READ_ULong( asize ) ) + goto Exit; + + /* swap between big and little endianness */ + *size = ( ( asize & 0xFF000000L ) >> 24 ) | + ( ( asize & 0x00FF0000L ) >> 8 ) | + ( ( asize & 0x0000FF00L ) << 8 ) | + ( ( asize & 0x000000FFL ) << 24 ); + } + + Exit: + return error; + } + + + LOCAL_FUNC + FT_Error Z1_New_Parser( Z1_Parser* parser, + FT_Stream stream, + FT_Memory memory ) + { + FT_Error error; + FT_UShort tag; + FT_Long size; + + + parser->stream = stream; + parser->memory = memory; + 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; + + parser->cursor = 0; + parser->limit = 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 */ + (void)FILE_Seek( 0L ); + 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 = FT_Err_Unknown_File_Format; + } + else + { + parser->cursor = parser->base_dict; + parser->limit = parser->cursor + parser->base_len; + } + } + + Exit: + if ( error && !parser->in_memory ) + FREE( parser->base_dict ); + + return error; + } + + + LOCAL_FUNC + void Z1_Done_Parser( Z1_Parser* parser ) + { + FT_Memory memory = parser->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 ); + } + + + /* 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; + } + + + LOCAL_FUNC + void Z1_Decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ) + { + while ( length > 0 ) + { + FT_Byte plain; + + + plain = ( *buffer ^ ( seed >> 8 ) ); + seed = ( *buffer + seed ) * 52845 + 22719; + *buffer++ = plain; + length--; + } + } + + + LOCAL_FUNC + FT_Error Z1_Get_Private_Dict( Z1_Parser* parser ) + { + FT_Stream stream = parser->stream; + FT_Memory memory = parser->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; + FT_Long size; + + + 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(( "Z1_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 = FT_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(( "Z1_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 = 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++ = ( hex1 << 4 ) | hexa_value( cur[1] ); + count++; + cur++; + } + + /* put a safeguard */ + parser->private_len = write - parser->private_dict; + *write++ = 0; + } + } + + /* we now decrypt the encoded binary private dictionary */ + Z1_Decrypt( parser->private_dict, parser->private_len, 55665 ); + parser->cursor = parser->private_dict; + parser->limit = parser->cursor + parser->private_len; + + Fail: + Exit: + return error; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/z1parse.h b/reactos/subsys/win32k/freetype/src/type1z/z1parse.h new file mode 100644 index 00000000000..d0b6a6503e2 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1parse.h @@ -0,0 +1,363 @@ +/***************************************************************************/ +/* */ +/* z1parse.h */ +/* */ +/* Experimental Type 1 parser (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1PARSE_H +#define Z1PARSE_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /* simple enumeration type used to identify token types */ + typedef enum Z1_Token_Type_ + { + t1_token_none = 0, + t1_token_any, + t1_token_string, + t1_token_array, + + /* do not remove */ + t1_token_max + + } Z1_Token_Type; + + + /* a simple structure used to identify tokens */ + typedef struct Z1_Token_Rec_ + { + FT_Byte* start; /* first character of token in input stream */ + FT_Byte* limit; /* first character after the token */ + Z1_Token_Type type; /* type of token.. */ + + } Z1_Token_Rec; + + + /* enumeration type used to identify object fields */ + typedef enum Z1_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, + + /* do not remove */ + t1_field_max + + } Z1_Field_Type; + + + /* structure type used to model object fields */ + typedef struct Z1_Field_Rec_ + { + Z1_Field_Type type; /* type of field */ + FT_UInt offset; /* offset of field in object */ + FT_UInt size; /* size of field in bytes */ + FT_UInt array_max; /* maximum number of elements for array */ + FT_UInt count_offset; /* offset of element count for arrays */ + FT_Int flag_bit; /* bit number for field flag */ + + } Z1_Field_Rec; + + +#define Z1_FIELD_REF( s, f ) ( ((s*)0)->f ) + +#define Z1_FIELD_BOOL( _ftype, _fname ) \ + { \ + t1_field_bool, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_NUM( _ftype, _fname ) \ + { \ + t1_field_integer, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_FIXED( _ftype, _fname, _power ) \ + { \ + t1_field_fixed, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_STRING( _ftype, _fname ) \ + { \ + t1_field_string, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_NUM_ARRAY( _ftype, _fname, _fcount, _fmax ) \ + { \ + t1_field_integer, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fcount ), \ + 0 \ + } + +#define Z1_FIELD_FIXED_ARRAY( _ftype, _fname, _fcount, _fmax ) \ + { \ + t1_field_fixed, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fcount ), \ + 0 \ + } + +#define Z1_FIELD_NUM_ARRAY2( _ftype, _fname, _fmax ) \ + { \ + t1_field_integer, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + 0, 0 \ + } + +#define Z1_FIELD_FIXED_ARRAY2( _ftype, _fname, _fmax ) \ + { \ + t1_field_fixed, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + 0, 0 \ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Table */ + /* */ + /* */ + /* A Z1_Table is a simple object used to store an array of objects in */ + /* a single memory block. */ + /* */ + /* */ + /* block :: The address in memory of the growheap's block. This */ + /* can change between two object adds, due to the use of */ + /* reallocation. */ + /* */ + /* cursor :: The current top of the grow heap within its block. */ + /* */ + /* capacity :: The current size of the heap block. Increments in */ + /* 1kByte blocks. */ + /* */ + /* init :: A boolean. Set when the table has been initialized */ + /* (the table user should set this field). */ + /* */ + /* max_elems :: The maximum number of elements in the table. */ + /* */ + /* num_elems :: The current number of elements in the table. */ + /* */ + /* elements :: A table of element addresses within the block. */ + /* */ + /* lengths :: A table of element sizes within the block. */ + /* */ + /* memory :: The memory object used for memory operations */ + /* (allocation/reallocation). */ + /* */ + typedef struct Z1_Table_ + { + FT_Byte* block; /* current memory block */ + FT_Int cursor; /* current cursor in memory block */ + FT_Int 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; + + } Z1_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Parser */ + /* */ + /* */ + /* A Z1_Parser is an object used to parse a Type 1 fonts very */ + /* quickly. */ + /* */ + /* */ + /* stream :: The current input stream. */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* 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. */ + /* */ + /* cursor :: The current parser cursor. */ + /* */ + /* limit :: The current parser limit (first byte after the */ + /* current dictionary). */ + /* */ + /* error :: The current parsing error. */ + /* */ + typedef struct Z1_Parser_ + { + FT_Stream stream; + FT_Memory memory; + + 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; + + FT_Byte* cursor; + FT_Byte* limit; + FT_Error error; + + } Z1_Parser; + + + LOCAL_DEF + FT_Error Z1_New_Table( Z1_Table* table, + FT_Int count, + FT_Memory memory ); + + + LOCAL_DEF + FT_Error Z1_Add_Table( Z1_Table* table, + FT_Int index, + void* object, + FT_Int length ); + +#if 0 + LOCAL_DEF + void Z1_Done_Table( Z1_Table* table ); +#endif + + LOCAL_DEF + void Z1_Release_Table( Z1_Table* table ); + + LOCAL_DEF + FT_Long Z1_ToInt( Z1_Parser* parser ); + + LOCAL_DEF + FT_Long Z1_ToFixed( Z1_Parser* parser, + FT_Int power_ten ); + + LOCAL_DEF + FT_Int Z1_ToCoordArray( Z1_Parser* parser, + FT_Int max_coords, + FT_Short* coords ); + + LOCAL_DEF + FT_Int Z1_ToFixedArray( Z1_Parser* parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ); + +#if 0 + LOCAL_DEF + FT_String* Z1_ToString( Z1_Parser* parser ); + + LOCAL_DEF + FT_Bool Z1_ToBool( Z1_Parser* parser ); +#endif + + + LOCAL_DEF + void Z1_Skip_Spaces( Z1_Parser* parser ); + + LOCAL_DEF + void Z1_ToToken( Z1_Parser* parser, + Z1_Token_Rec* token ); + + LOCAL_FUNC + void Z1_ToTokenArray( Z1_Parser* parser, + Z1_Token_Rec* tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ); + + LOCAL_DEF + FT_Error Z1_Load_Field( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ); + + LOCAL_DEF + FT_Error Z1_Load_Field_Table( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ); + + + LOCAL_DEF + FT_Error Z1_New_Parser( Z1_Parser* parser, + FT_Stream stream, + FT_Memory memory ); + + LOCAL_DEF + FT_Error Z1_Get_Private_Dict( Z1_Parser* parser ); + + LOCAL_DEF + void Z1_Decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ); + + LOCAL_DEF + void Z1_Done_Parser( Z1_Parser* parser ); + +#ifdef __cplusplus + } +#endif + +#endif /* Z1PARSE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/type1z/z1tokens.h b/reactos/subsys/win32k/freetype/src/type1z/z1tokens.h new file mode 100644 index 00000000000..73c0228e53f --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/type1z/z1tokens.h @@ -0,0 +1,132 @@ +/***************************************************************************/ +/* */ +/* z1tokens.h */ +/* */ +/* Experimental Type 1 tokenizer (specification). */ +/* */ +/* Copyright 1996-2000 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 T1TYPE +#define T1TYPE T1_FontInfo + + Z1_FONTINFO_STRING( "version", version ) + Z1_FONTINFO_STRING( "Notice", notice ) + Z1_FONTINFO_STRING( "FullName", full_name ) + Z1_FONTINFO_STRING( "FamilyName", family_name ) + Z1_FONTINFO_STRING( "Weight", weight ) + + Z1_FONTINFO_NUM ( "ItalicAngle", italic_angle ) + Z1_FONTINFO_BOOL ( "isFixedPitch", is_fixed_pitch ) + Z1_FONTINFO_NUM ( "UnderlinePosition", underline_position ) + Z1_FONTINFO_NUM ( "UnderlineThickness", underline_thickness ) + + +#undef T1TYPE +#define T1TYPE T1_Private + + Z1_PRIVATE_NUM ( "UniqueID", unique_id ) + Z1_PRIVATE_NUM ( "lenIV", lenIV ) + Z1_PRIVATE_NUM ( "LanguageGroup", language_group ) + Z1_PRIVATE_NUM ( "password", password ) + + Z1_PRIVATE_FIXED ( "BlueScale", blue_scale ) + Z1_PRIVATE_NUM ( "BlueShift", blue_shift ) + Z1_PRIVATE_NUM ( "BlueFuzz", blue_fuzz ) + + Z1_PRIVATE_NUM_TABLE ( "BlueValues", blue_values, 14, num_blue_values ) + Z1_PRIVATE_NUM_TABLE ( "OtherBlues", other_blues, 10, num_other_blues ) + Z1_PRIVATE_NUM_TABLE ( "FamilyBlues", family_blues, 14, num_family_blues ) + Z1_PRIVATE_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10, \ + num_family_other_blues ) + + Z1_PRIVATE_NUM_TABLE2( "StdHW", standard_width, 1 ) + Z1_PRIVATE_NUM_TABLE2( "StdVW", standard_height, 1 ) + Z1_PRIVATE_NUM_TABLE2( "MinFeature", min_feature, 2 ) + + Z1_PRIVATE_NUM_TABLE ( "StemSnapH", snap_widths, 12, num_snap_widths ) + Z1_PRIVATE_NUM_TABLE ( "StemSnapV", snap_heights, 12, num_snap_heights ) + + +#undef T1TYPE +#define T1TYPE T1_Font + + Z1_TOPDICT_NUM( "PaintType", paint_type ) + Z1_TOPDICT_NUM( "FontType", font_type ) + Z1_TOPDICT_NUM( "StrokeWidth", stroke_width ) + + +#if 0 + + /* define the font info dictionary parsing callbacks */ +#undef FACE +#define FACE (face->type1.font_info) + + PARSE_STRING( "version", version ) + PARSE_STRING( "Notice", notice ) + PARSE_STRING( "FullName", full_name ) + PARSE_STRING( "FamilyName", family_name ) + PARSE_STRING( "Weight", weight ) + + PARSE_INT ( "ItalicAngle", italic_angle ) + PARSE_BOOL ( "isFixedPitch", is_fixed_pitch ) + PARSE_NUM ( "UnderlinePosition", underline_position, FT_Short ) + PARSE_NUM ( "UnderlineThickness", underline_thickness, FT_UShort ) + + + /* define the private dict parsing callbacks */ +#undef FACE +#define FACE (face->type1.private_dict) + + PARSE_INT ("UniqueID", unique_id ) + PARSE_INT ("lenIV", lenIV ) + + PARSE_COORDS ( "BlueValues", num_blues, 14, blue_values) + PARSE_COORDS ( "OtherBlues", num_other_blues, 10, other_blues) + + PARSE_COORDS ( "FamilyBlues", num_family_blues, 14, family_blues ) + PARSE_COORDS ( "FamilyOtherBlues", num_family_other_blues, 10, + family_other_blues ) + + PARSE_FIXED ( "BlueScale", blue_scale ) + PARSE_INT ( "BlueShift", blue_shift ) + + PARSE_INT ( "BlueFuzz", blue_fuzz ) + + PARSE_COORDS2( "StdHW", 1, standard_width ) + PARSE_COORDS2( "StdVW", 1, standard_height ) + + PARSE_COORDS ( "StemSnapH", num_snap_widths, 12, stem_snap_widths ) + PARSE_COORDS ( "StemSnapV", num_snap_heights, 12, stem_snap_heights ) + + PARSE_INT ( "LanguageGroup", language_group ) + PARSE_INT ( "password", password ) + PARSE_COORDS2( "MinFeature", 2, min_feature ) + + + /* define the top-level dictionary parsing callbacks */ +#undef FACE +#define FACE (face->type1) + +/*PARSE_STRING ( "FontName", font_name ) -- handled by special routine */ + PARSE_NUM ( "PaintType", paint_type, FT_Byte ) + PARSE_NUM ( "FontType", font_type, FT_Byte ) + PARSE_FIXEDS2( "FontMatrix", 4, font_matrix ) +/*PARSE_COORDS2( "FontBBox", 4, font_bbox ) -- handled by special routine */ + PARSE_INT ( "StrokeWidth", stroke_width ) + +#undef FACE + +#endif /* 0 */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/winfonts/module.mk b/reactos/subsys/win32k/freetype/src/winfonts/module.mk new file mode 100644 index 00000000000..5c12eb6ee82 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/winfonts/module.mk @@ -0,0 +1,6 @@ +make_module_list: add_windows_driver + +add_windows_driver: + $(OPEN_DRIVER)winfnt_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)winfnt $(ECHO_DRIVER_DESC)Windows bitmap fonts with extension *.fnt or *.fon$(ECHO_DRIVER_DONE) + diff --git a/reactos/subsys/win32k/freetype/src/winfonts/rules.mk b/reactos/subsys/win32k/freetype/src/winfonts/rules.mk new file mode 100644 index 00000000000..8396894d974 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/winfonts/rules.mk @@ -0,0 +1,64 @@ +# +# FreeType 2 Windows FNT/FON driver configuration rules +# + + +# Copyright 1996-2000 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. + + +# Windows driver directory +# +FNT_DIR := $(SRC_)winfonts +FNT_DIR_ := $(FNT_DIR)$(SEP) + + +FNT_COMPILE := $(FT_COMPILE) + + +# Windows driver sources (i.e., C files) +# +FNT_DRV_SRC := $(FNT_DIR_)winfnt.c + +# Windows driver headers +# +FNT_DRV_H := $(FNT_DRV_SRC:%.c=%.h) + + +# Windows driver object(s) +# +# FNT_DRV_OBJ_M is used during `multi' builds +# FNT_DRV_OBJ_S is used during `single' builds +# +FNT_DRV_OBJ_M := $(FNT_DRV_SRC:$(FNT_DIR_)%.c=$(OBJ_)%.$O) +FNT_DRV_OBJ_S := $(OBJ_)winfnt.$O + +# Windows driver source file for single build +# +FNT_DRV_SRC_S := $(FNT_DIR_)winfnt.c + + +# Windows driver - single object +# +$(FNT_DRV_OBJ_S): $(FNT_DRV_SRC_S) $(FNT_DRV_SRC) $(FREETYPE_H) $(FNT_DRV_H) + $(FNT_COMPILE) $T$@ $(FNT_DRV_SRC_S) + + +# Windows driver - multiple objects +# +$(OBJ_)%.$O: $(FNT_DIR_)%.c $(FREETYPE_H) $(FNT_DRV_H) + $(FNT_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(FNT_DRV_OBJ_S) +DRV_OBJS_M += $(FNT_DRV_OBJ_M) + +# EOF diff --git a/reactos/subsys/win32k/freetype/src/winfonts/winfnt.c b/reactos/subsys/win32k/freetype/src/winfonts/winfnt.c new file mode 100644 index 00000000000..470440a2ca9 --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/winfonts/winfnt.c @@ -0,0 +1,623 @@ +/***************************************************************************/ +/* */ +/* winfnt.c */ +/* */ +/* FreeType font driver for Windows FNT/FON files */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "winfnt.h" + +#else + +#include + +#endif + + +#include +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* 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[] = + { + FT_FRAME_START( 64 ), + FT_FRAME_USHORT_LE ( WinMZ_Header, magic ), + FT_FRAME_SKIP_BYTES( 29 * 2 ), + FT_FRAME_ULONG_LE ( WinMZ_Header, lfanew ), + FT_FRAME_END + }; + + static + const FT_Frame_Field winne_header_fields[] = + { + FT_FRAME_START( 40 ), + FT_FRAME_USHORT_LE ( WinNE_Header, magic ), + FT_FRAME_SKIP_BYTES( 34 ), + FT_FRAME_USHORT_LE ( WinNE_Header, resource_tab_offset ), + FT_FRAME_USHORT_LE ( WinNE_Header, rname_tab_offset ), + FT_FRAME_END + }; + + static + const FT_Frame_Field winfnt_header_fields[] = + { + FT_FRAME_START( 134 ), + FT_FRAME_USHORT_LE( WinFNT_Header, version ), + FT_FRAME_ULONG_LE ( WinFNT_Header, file_size ), + FT_FRAME_BYTES ( WinFNT_Header, copyright, 60 ), + FT_FRAME_USHORT_LE( WinFNT_Header, file_type ), + FT_FRAME_USHORT_LE( WinFNT_Header, nominal_point_size ), + FT_FRAME_USHORT_LE( WinFNT_Header, vertical_resolution ), + FT_FRAME_USHORT_LE( WinFNT_Header, horizontal_resolution ), + FT_FRAME_USHORT_LE( WinFNT_Header, ascent ), + FT_FRAME_USHORT_LE( WinFNT_Header, internal_leading ), + FT_FRAME_USHORT_LE( WinFNT_Header, external_leading ), + FT_FRAME_BYTE ( WinFNT_Header, italic ), + FT_FRAME_BYTE ( WinFNT_Header, underline ), + FT_FRAME_BYTE ( WinFNT_Header, strike_out ), + FT_FRAME_USHORT_LE( WinFNT_Header, weight ), + FT_FRAME_BYTE ( WinFNT_Header, charset ), + FT_FRAME_USHORT_LE( WinFNT_Header, pixel_width ), + FT_FRAME_USHORT_LE( WinFNT_Header, pixel_height ), + FT_FRAME_BYTE ( WinFNT_Header, pitch_and_family ), + FT_FRAME_USHORT_LE( WinFNT_Header, avg_width ), + FT_FRAME_USHORT_LE( WinFNT_Header, max_width ), + FT_FRAME_BYTE ( WinFNT_Header, first_char ), + FT_FRAME_BYTE ( WinFNT_Header, last_char ), + FT_FRAME_BYTE ( WinFNT_Header, default_char ), + FT_FRAME_BYTE ( WinFNT_Header, break_char ), + FT_FRAME_USHORT_LE( WinFNT_Header, bytes_per_row ), + FT_FRAME_ULONG_LE ( WinFNT_Header, device_offset ), + FT_FRAME_ULONG_LE ( WinFNT_Header, face_name_offset ), + FT_FRAME_ULONG_LE ( WinFNT_Header, bits_pointer ), + FT_FRAME_ULONG_LE ( WinFNT_Header, bits_offset ), + FT_FRAME_BYTE ( WinFNT_Header, reserved ), + FT_FRAME_ULONG_LE ( WinFNT_Header, flags ), + FT_FRAME_USHORT_LE( WinFNT_Header, A_space ), + FT_FRAME_USHORT_LE( WinFNT_Header, B_space ), + FT_FRAME_USHORT_LE( WinFNT_Header, C_space ), + FT_FRAME_USHORT_LE( WinFNT_Header, color_table_offset ), + FT_FRAME_BYTES ( WinFNT_Header, reserved, 4 ), + FT_FRAME_END + }; + + + static + void fnt_done_font( FT_Stream stream, + FNT_Font* font ) + { + if ( font->fnt_frame ) + RELEASE_Frame( font->fnt_frame ); + + font->fnt_size = 0; + font->fnt_frame = 0; + } + + + static + FT_Error fnt_load_font( FT_Stream stream, + FNT_Font* font ) + { + 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 = FT_Err_Unknown_File_Format; + goto Exit; + } + + if ( header->file_type & 1 ) + { + FT_TRACE2(( "can't handle vector FNT fonts\n" )); + error = FT_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_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_done_font( stream, cur ); + + FREE( face->fonts ); + face->num_fonts = 0; + } + + static + FT_Error fnt_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 = FT_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 = FT_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 = 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 = FT_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_load_font( stream, cur ); + if ( error ) + goto Fail; + } + } + } + } + + Fail: + if ( error ) + fnt_done_fonts( face ); + + Exit: + return error; + } + + + static + void FNT_Done_Face( FNT_Face face ) + { + FT_Memory memory = FT_FACE_MEMORY( face ); + + + fnt_done_fonts( face ); + + FREE( face->root.available_sizes ); + face->root.num_fixed_sizes = 0; + } + + + static + FT_Error FNT_Init_Face( 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_get_dll_fonts( face ); + if ( error ) + { + /* this didn't work, now try to load a single FNT font */ + FT_Memory memory = FT_FACE_MEMORY( face ); + 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_load_font( stream, font ); + 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 = "Regular"; + + if ( root->style_flags & FT_STYLE_FLAG_BOLD ) + { + if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) + root->style_name = "Bold Italic"; + else + root->style_name = "Bold"; + } + else if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) + root->style_name = "Italic"; + } + + Fail: + if ( error ) + FNT_Done_Face( face ); + + Exit: + return error; + } + + + static + FT_Error FNT_Set_Pixel_Size( 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 ? FT_Err_Ok : FT_Err_Invalid_Argument ); + } + + + static + FT_UInt FNT_Get_Char_Index( FT_CharMap charmap, + FT_ULong char_code ) + { + FT_UInt result = char_code; + + + if ( charmap ) + { + FNT_Font* font = ((FNT_Face)charmap->face)->fonts; + FT_UInt first = font->header.first_char; + FT_UInt 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 = FT_Err_Invalid_Argument; + goto Exit; + } + + if ( glyph_index > 0 ) + glyph_index--; + else + glyph_index = font->header.default_char - font->header.first_char; + + new_format = 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; + + Exit: + return error; + } + + + 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_Init_Face, + (FTDriver_doneFace) FNT_Done_Face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) FNT_Set_Pixel_Size, + (FTDriver_setPixelSizes)FNT_Set_Pixel_Size, + + (FTDriver_loadGlyph) FNT_Load_Glyph, + (FTDriver_getCharIndex) FNT_Get_Char_Index, + + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, + (FTDriver_getAdvances) 0 + }; + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/src/winfonts/winfnt.h b/reactos/subsys/win32k/freetype/src/winfonts/winfnt.h new file mode 100644 index 00000000000..eaf308b875b --- /dev/null +++ b/reactos/subsys/win32k/freetype/src/winfonts/winfnt.h @@ -0,0 +1,150 @@ +/***************************************************************************/ +/* */ +/* winfnt.h */ +/* */ +/* FreeType font driver for Windows FNT/FON files */ +/* */ +/* Copyright 1996-2000 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 + + + 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_EXPORT_VAR( const FT_Driver_Class ) winfnt_driver_class; + + +#endif /* WINFNT_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1afm.c b/reactos/subsys/win32k/freetype/t1afm.c new file mode 100644 index 00000000000..a6ac1b98a69 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1afm.c @@ -0,0 +1,293 @@ +/***************************************************************************/ +/* */ +/* t1afm.c */ +/* */ +/* AFM support for Type 1 fonts (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t1afm.h" + +#else + +#include + +#endif + + +#include +#include + +#include /* for qsort() */ +#include /* for strcmp() */ +#include /* 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 + + + LOCAL_FUNC + void T1_Done_AFM( FT_Memory memory, + T1_AFM* afm ) + { + FREE( afm->kern_pairs ); + afm->num_pairs = 0; + } + + +#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 = 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 */ + static + 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 */ + LOCAL_FUNC + 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; + + 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 */ + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/t1afm.h b/reactos/subsys/win32k/freetype/t1afm.h new file mode 100644 index 00000000000..709154ec7b7 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1afm.h @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* t1afm.h */ +/* */ +/* AFM support for Type 1 fonts (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + 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; + + + LOCAL_DEF + FT_Error T1_Read_AFM( FT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void T1_Done_AFM( FT_Memory memory, + T1_AFM* afm ); + + LOCAL_DEF + void T1_Get_Kerning( T1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T1AFM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1driver.c b/reactos/subsys/win32k/freetype/t1driver.c new file mode 100644 index 00000000000..49b5a563749 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1driver.c @@ -0,0 +1,381 @@ +/***************************************************************************/ +/* */ +/* t1driver.c */ +/* */ +/* Type 1 driver interface (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t1driver.h" +#include "t1gload.h" +#include "t1afm.h" + +#else + +#include +#include +#include + +#endif + + +#include +#include +#include + +#include /* 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 + + +#ifndef T1_CONFIG_OPTION_NO_AFM + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 */ + + + static + FT_Error get_t1_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 = strlen( gname ); + + + if ( len >= buffer_max ) + len = buffer_max - 1; + + MEM_Copy( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return T1_Err_Ok; + } + + + static + FT_Module_Interface T1_Get_Interface( FT_Module module, + const char* interface ) + { + FT_UNUSED( module ); + + if ( strcmp( interface, "glyph_name" ) == 0 ) + return (FT_Module_Interface)get_t1_glyph_name; + + return 0; + } + + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Char_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in fractional points. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Set_Char_Sizes( T1_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_UNUSED( char_width ); + FT_UNUSED( char_height ); + FT_UNUSED( horz_resolution ); + FT_UNUSED( vert_resolution ); + + size->valid = FALSE; + + return T1_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Pixel_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in integer pixels. */ + /* */ + /* */ + /* pixel_width :: The character width expressed in integer pixels. */ + /* */ + /* pixel_height :: The character height expressed in integer pixels. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Set_Pixel_Sizes( T1_Size size, + FT_Int pixel_width, + FT_Int pixel_height ) + { + FT_UNUSED( pixel_width ); + FT_UNUSED( pixel_height ); + + size->valid = FALSE; + + return T1_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* 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; + } + + + + const FT_Driver_Class t1_driver_class = + { + { + ft_module_font_driver | ft_module_driver_scalable, + sizeof( FT_DriverRec ), + + "type1", /* driver name */ + 0x10000L, /* driver version 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or above */ + + 0, /* module specific interface */ + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) T1_Get_Interface + }, + + sizeof( T1_FaceRec ), + sizeof( T1_SizeRec ), + sizeof( T1_GlyphSlotRec ), + + (FTDriver_initFace) T1_Init_Face, + (FTDriver_doneFace) T1_Done_Face, + (FTDriver_initSize) T1_Init_Size, + (FTDriver_doneSize) T1_Done_Size, + (FTDriver_initGlyphSlot)T1_Init_GlyphSlot, + (FTDriver_doneGlyphSlot)T1_Done_GlyphSlot, + + (FTDriver_setCharSizes) Set_Char_Sizes, + (FTDriver_setPixelSizes)Set_Pixel_Sizes, + (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 + + EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void ) + { + return &t1_driver_class; + } + +#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1driver.h b/reactos/subsys/win32k/freetype/t1driver.h new file mode 100644 index 00000000000..5d615b5bafa --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1driver.h @@ -0,0 +1,30 @@ +/***************************************************************************/ +/* */ +/* t1driver.h */ +/* */ +/* High-level Type 1 driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + FT_EXPORT_VAR( const FT_Driver_Class ) t1_driver_class; + + +#endif /* T1DRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1gload.c b/reactos/subsys/win32k/freetype/t1gload.c new file mode 100644 index 00000000000..37cfc8c5d76 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1gload.c @@ -0,0 +1,1823 @@ +/***************************************************************************/ +/* */ +/* t1gload.c */ +/* */ +/* Type 1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t1gload.h" + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include "t1hinter.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#include +#include +#include + +#include /* 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 + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + void T1_Reset_Builder( T1_Builder* builder, + FT_Bool reset_base ) + { + 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->pass = 0; + builder->hint_point = 0; + + if ( builder->loader ) + { + if ( reset_base ) + FT_GlyphLoader_Rewind( builder->loader ); + + FT_GlyphLoader_Prepare( builder->loader ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + /* funcs :: Glyph builder functions (or `methods'). */ + /* */ + LOCAL_FUNC + void T1_Init_Builder( T1_Builder* builder, + T1_Face face, + T1_Size size, + T1_GlyphSlot glyph, + const T1_Builder_Funcs* funcs ) + { + builder->funcs = *funcs; + builder->path_begun = 0; + builder->load_points = 1; + + builder->face = face; + builder->size = size; + builder->glyph = glyph; + builder->memory = face->root.memory; + + if ( glyph ) + { + FT_GlyphLoader* loader = FT_SLOT( glyph )->loader; + + + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; + } + + if ( size ) + { + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.metrics.y_scale; + } + + T1_Reset_Builder( builder, 1 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Builder */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + LOCAL_FUNC + void T1_Done_Builder( T1_Builder* builder ) + { + T1_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* funcs :: The hinting functions interface. */ + /* */ + LOCAL_FUNC + void T1_Init_Decoder( T1_Decoder* decoder, + const T1_Hinter_Funcs* funcs ) + { + decoder->hinter = *funcs; /* copy hinter interface */ + decoder->top = 0; + decoder->zone = 0; + + decoder->flex_state = 0; + decoder->num_flex_vectors = 0; + + /* Clear loader */ + MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* lookup_glyph_by_stdcharcode */ + /* */ + /* */ + /* Looks up a given glyph by its StandardEncoding charcode. Used */ + /* to implement the SEAC Type 1 operator. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + static + FT_Int lookup_glyph_by_stdcharcode( T1_Face face, + FT_Int charcode ) + { + FT_Int n; + const FT_String* glyph_name; + PSNames_Interface* psnames = (PSNames_Interface*)face->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 < face->type1.num_glyphs; n++ ) + { + FT_String* name = (FT_String*)face->type1.glyph_names[n]; + + + if ( name && strcmp( name, glyph_name ) == 0 ) + return n; + } + + return -1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_seac */ + /* */ + /* */ + /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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; + T1_Face face = decoder->builder.face; + T1_Font* type1 = &face->type1; + + + bchar_index = lookup_glyph_by_stdcharcode( face, bchar ); + achar_index = lookup_glyph_by_stdcharcode( face, achar ); + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return T1_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->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->current.subglyphs; + glyph->format = ft_glyph_format_composite; + + loader->current.num_subglyphs = 2; + goto Exit; + } + + /* First load `bchar' in builder */ + /* now load the unscaled outline */ + + if ( decoder->builder.loader ) + FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ + + error = T1_Parse_CharStrings( decoder, + type1->charstrings [bchar_index], + type1->charstrings_len[bchar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + 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_Parse_CharStrings( decoder, + type1->charstrings [achar_index], + type1->charstrings_len[achar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + return error; + + /* 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 = base->n_points - n_base_points; + dummy.points = base->points + n_base_points; + + FT_Outline_Translate( &dummy, adx - asb, ady ); + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_flex */ + /* */ + /* */ + /* Implements the `flex' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* decoder :: The current Type 1 decoder. */ + /* threshold :: The threshold. */ + /* end_x :: The horizontal position of the final flex point. */ + /* end_y :: The vertical position of the final flex point. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error t1operator_flex( T1_Decoder* decoder, + FT_Pos threshold, + FT_Pos end_x, + FT_Pos end_y ) + { + FT_Vector vec; + FT_Vector* flex = decoder->flex_vectors; + FT_Int n; + + FT_UNUSED( threshold ); + FT_UNUSED( end_x ); + FT_UNUSED( end_y ); + + + /* we don't even try to test the threshold in the non-hinting */ + /* builder, even if the flex operator is said to be a path */ + /* construction statement in the specification. This is better */ + /* left to the hinter. */ + + flex = decoder->flex_vectors; + vec = *flex++; + + for ( n = 0; n < 6; n++ ) + { + flex->x += vec.x; + flex->y += vec.y; + + vec = *flex++; + } + + flex = decoder->flex_vectors; + + return decoder->builder.funcs.rcurve_to( &decoder->builder, + flex[0].x, flex[0].y, + flex[1].x, flex[1].y, + flex[2].x, flex[2].y ) || + + decoder->builder.funcs.rcurve_to( &decoder->builder, + flex[3].x, flex[3].y, + flex[4].x, flex[4].y, + flex[5].x, flex[5].y ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given Type 1 charstrings program. */ + /* */ + /* */ + /* 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. */ + /* */ + /* num_subrs :: The number of sub-routines. */ + /* */ + /* subrs_base :: An array of sub-routines addresses. */ + /* */ + /* subrs_len :: An array of sub-routines lengths. */ + /* */ + /* */ + /* Free error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Parse_CharStrings( T1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ) + { + FT_Error error; + T1_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + T1_Builder* builder = &decoder->builder; + T1_Builder_Funcs* builds = &builder->funcs; + T1_Hinter_Funcs* hints = &decoder->hinter; + + static + const FT_Int 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 */ + }; + + + /* 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 = T1_Err_Ok; + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Int* top = decoder->top; + T1_Operator op = op_none; + FT_Long value = 0; + + + /* Start with the decompression of 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_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_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_Parse_CharStrings: unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = ( (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_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_Parse_CharStrings: invalid byte (%d)\n", + ip[-1] )); + goto Syntax_Error; + } + } + + /* push value if necessary */ + if ( op == op_none ) + { + if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) + { + FT_ERROR(( "T1_Parse_CharStrings: stack overflow!\n" )); + goto Syntax_Error; + } + + *top++ = value; + decoder->top = top; + } + + else if ( op == op_callothersubr ) /* check arguments differently */ + { + 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; + decoder->flex_vectors[0].x = 0; + decoder->flex_vectors[0].y = 0; + break; + + case 2: /* add flex vector */ + { + FT_Int index; + FT_Vector* flex; + + + if ( top[0] != 0 ) + goto Unexpected_OtherSubr; + + top -= 2; + if ( top < decoder->stack ) + goto Stack_Underflow; + + index = decoder->num_flex_vectors++; + if ( index >= 7 ) + { + FT_ERROR(( "T1_Parse_CharStrings: too many flex vectors!\n" )); + goto Syntax_Error; + } + + flex = decoder->flex_vectors + index; + flex->x += top[0]; + flex->y += top[1]; + } + break; + + case 0: /* end flex feature */ + if ( decoder->flex_state == 0 || + decoder->num_flex_vectors != 7 ) + { + FT_ERROR(( "T1_Parse_CharStrings: unexpected flex end\n" )); + goto Syntax_Error; + } + + if ( top[0] != 3 ) + goto Unexpected_OtherSubr; + + top -= 3; + if ( top < decoder->stack ) + goto Stack_Underflow; + + /* now consume the remaining `pop pop setcurrentpoint' */ + if ( ip + 6 > limit || + ip[0] != 12 || ip[1] != 17 || /* pop */ + ip[2] != 12 || ip[3] != 17 || /* pop */ + ip[4] != 12 || ip[5] != 33 ) /* setcurrentpoint */ + { + FT_ERROR(( "T1_Parse_CharStrings: invalid flex charstring\n" )); + goto Syntax_Error; + } + + decoder->flex_state = 0; + decoder->top = top; + + error = t1operator_flex( decoder, top[0], top[1], top[2] ); + break; + + case 3: /* change hints */ + if ( top[0] != 1 ) + goto Unexpected_OtherSubr; + + /* eat the following `pop' */ + if ( ip + 2 > limit ) + { + FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if ( ip[0] != 12 || ip[1] != 17 ) + { + FT_ERROR(( "T1_Parse_CharStrings:" )); + FT_ERROR(( " `pop' expected, found (%d %d)\n", ip[0], ip[1] )); + goto Syntax_Error; + } + + ip += 2; + + error = hints->change_hints( builder ); + break; + + default: + /* invalid OtherSubrs call */ + Unexpected_OtherSubr: + FT_ERROR(( "T1_Parse_CharStrings: unexpected OtherSubrs [%d %d]\n", + top[0], top[1] )); + goto Syntax_Error; + } + decoder->top = top; + } + else + { + FT_Int num_args = args_count[op]; + + + if ( top - decoder->stack < num_args ) + goto Stack_Underflow; + + top -= num_args; + + switch ( op ) + { + case op_endchar: + error = builds->end_char( builder ); + break; + + case op_hsbw: + error = builds->set_bearing_point( builder, top[0], 0, + top[1], 0 ); + 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: + error = builds->set_bearing_point( builder, top[0], top[1], + top[2], top[3] ); + break; + + case op_closepath: + error = builds->close_path( builder ); + break; + + case op_hlineto: + error = builds->rline_to( builder, top[0], 0 ); + break; + + case op_hmoveto: + error = builds->rmove_to( builder, top[0], 0 ); + break; + + case op_hvcurveto: + error = builds->rcurve_to( builder, top[0], 0, + top[1], top[2], + 0, top[3] ); + break; + + case op_rlineto: + error = builds->rline_to( builder, top[0], top[1] ); + break; + + case op_rmoveto: + /* ignore operator when in flex mode */ + if ( decoder->flex_state == 0 ) + error = builds->rmove_to( builder, top[0], top[1] ); + else + top += 2; + break; + + case op_rrcurveto: + error = builds->rcurve_to( builder, top[0], top[1], + top[2], top[3], + top[4], top[5] ); + break; + + case op_vhcurveto: + error = builds->rcurve_to( builder, 0, top[0], + top[1], top[2], + top[3], 0 ); + break; + + case op_vlineto: + error = builds->rline_to( builder, 0, top[0] ); + break; + + case op_vmoveto: + error = builds->rmove_to( builder, 0, top[0] ); + break; + + case op_dotsection: + error = hints->dot_section( builder ); + break; + + case op_hstem: + error = hints->stem( builder, top[0], top[1], 0 ); + break; + + case op_hstem3: + error = hints->stem3( builder, top[0], top[1], top[2], + top[3], top[4], top[5], 0 ); + break; + + case op_vstem: + error = hints->stem( builder, top[0], top[1], 1 ); + break; + + case op_vstem3: + error = hints->stem3( builder, top[0], top[1], top[2], + top[3], top[4], top[5], 1 ); + break; + + case op_div: + if ( top[1] ) + { + *top = top[0] / top[1]; + ++top; + } + else + { + FT_ERROR(( "T1_Parse_CHarStrings: division by 0\n" )); + goto Syntax_Error; + } + break; + + case op_callsubr: + { + FT_Int index = top[0]; + + + if ( index < 0 || index >= num_subrs ) + { + FT_ERROR(( "T1_Parse_CharStrings: invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "T1_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = subrs_base[index]; + zone->limit = zone->base + subrs_len[index]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "T1_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case op_pop: + FT_ERROR(( "T1_Parse_CharStrings: unexpected POP\n" )); + goto Syntax_Error; + + case op_return: + if ( zone <= decoder->zones ) + { + FT_ERROR(( "T1_Parse_CharStrings: unexpected return\n" )); + goto Syntax_Error; + } + + zone--; + ip = zone->cursor; + limit = zone->limit; + decoder->zone = zone; + break; + + case op_setcurrentpoint: + FT_ERROR(( "T1_Parse_CharStrings:" )); + FT_ERROR(( " unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + break; + + default: + FT_ERROR(( "T1_Parse_CharStrings: unhandled opcode %d\n", op )); + goto Syntax_Error; + } + + decoder->top = top; + } + } + + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Add_Points */ + /* */ + /* */ + /* Checks that there is enough room in the current load glyph outline */ + /* to accept `num_points' additional outline points. If not, this */ + /* function grows the load outline's arrays accordingly. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder object. */ + /* */ + /* num_points :: The number of points that will be added later. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function does NOT update the points count in the glyph */ + /* builder. This must be done by the caller itself, after this */ + /* function has been invoked. */ + /* */ + LOCAL_FUNC + FT_Error T1_Add_Points( T1_Builder* builder, + FT_Int num_points ) + { + return FT_GlyphLoader_Check_Points( builder->loader, num_points, 0 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Add_Contours */ + /* */ + /* */ + /* Checks that there is enough room in the current load glyph outline */ + /* to accept `num_contours' additional contours. If not, this */ + /* function grows the load outline's arrays accordingly. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder object. */ + /* */ + /* num_contours :: The number of contours that will be added later. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function does NOT update the contours count in the load glyph */ + /* This must be done by the caller itself, after this function is */ + /* invoked. */ + /* */ + LOCAL_FUNC + FT_Error T1_Add_Contours( T1_Builder* builder, + FT_Int num_contours ) + { + return FT_GlyphLoader_Check_Points( builder->loader, 0, num_contours ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** 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. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error maxadv_sbw( T1_Decoder* decoder, + FT_Pos sbx, + FT_Pos sby, + FT_Pos wx, + FT_Pos wy ) + { + FT_UNUSED( sbx ); + FT_UNUSED( sby ); + FT_UNUSED( wy ); + + if ( wx > decoder->builder.advance.x ) + decoder->builder.advance.x = wx; + + return -1; /* return an error code to exit the Type 1 parser */ + /* immediately. */ + } + + + static + FT_Int maxadv_error( void ) + { + /* we should never reach this code, unless with a buggy font */ + return -2; + } + + + /* the maxadv_gbuilder_interface is used when computing the maximum */ + /* advance width of all glyphs in a given font. We only process the */ + /* `sbw' operator here, and return an error for all others. */ + + /* Note that `seac' is processed by the T1_Decoder. */ + static + const T1_Builder_Funcs maxadv_builder_interface = + { + (T1_Builder_EndChar) maxadv_error, + (T1_Builder_Sbw) maxadv_sbw, + (T1_Builder_ClosePath)maxadv_error, + (T1_Builder_RLineTo) maxadv_error, + (T1_Builder_RMoveTo) maxadv_error, + (T1_Builder_RCurveTo) maxadv_error + }; + + + /* the maxadv_hinter_interface always return an error. */ + static + const T1_Hinter_Funcs maxadv_hinter_interface = + { + (T1_Hinter_DotSection) maxadv_error, + (T1_Hinter_ChangeHints)maxadv_error, + (T1_Hinter_Stem) maxadv_error, + (T1_Hinter_Stem3) maxadv_error, + }; + + + LOCAL_FUNC + 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; + + + *max_advance = 0; + + /* Initialize load decoder */ + T1_Init_Decoder( &decoder, &maxadv_hinter_interface ); + + T1_Init_Builder( &decoder.builder, face, 0, 0, + &maxadv_builder_interface ); + + /* 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_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + /* 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' *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error close_open_path( T1_Builder* builder ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Int num_points; + FT_Int first_point; + + + /* Some fonts, like Hershey, are made of `open paths' which are */ + /* now managed directly by FreeType. In this case, it is necessary */ + /* to close the path by duplicating its points in reverse order, */ + /* which is precisely the purpose of this function. */ + + /* first compute the number of points to duplicate */ + if ( cur->n_contours > 1 ) + first_point = cur->contours[cur->n_contours - 2] + 1; + else + first_point = 0; + + num_points = cur->n_points - first_point - 2; + if ( num_points > 0 ) + { + FT_Vector* source_point; + char* source_tags; + FT_Vector* point; + char* tags; + + + error = T1_Add_Points( builder, num_points ); + if ( error ) + return error; + + point = cur->points + cur->n_points; + tags = cur->tags + cur->n_points; + + source_point = point - 2; + source_tags = tags - 2; + + cur->n_points += num_points; + + if ( builder->load_points ) + do + { + *point++ = *source_point--; + *tags++ = *source_tags--; + num_points--; + + } while ( num_points > 0 ); + } + + builder->path_begun = 0; + return T1_Err_Ok; + } + + + static + FT_Error gload_closepath( T1_Builder* builder ) + { + FT_Outline* cur = builder->current; + + + /* XXXX: We must not include the last point in the path if it */ + /* is located on the first point. */ + if ( cur->n_points > 1 ) + { + FT_Int first = 0; + FT_Vector* p1 = cur->points + first; + FT_Vector* p2 = cur->points + cur->n_points - 1; + + + if ( cur->n_contours > 1 ) + { + first = cur->contours[cur->n_contours - 2] + 1; + p1 = cur->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + cur->n_points--; + } + + /* save current contour, if any */ + if ( cur->n_contours > 0 ) + cur->contours[cur->n_contours - 1] = cur->n_points - 1; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + /* hint last points if necessary -- this is not strictly required */ + /* there, but it helps for debugging, and doesn't affect performance */ + if ( builder->pass == 1 ) + T1_Hint_Points( builder ); +#endif + + builder->path_begun = 0; + return T1_Err_Ok; + } + + + static + FT_Error gload_endchar( T1_Builder* builder ) + { + FT_Error error; + + + /* close path if needed */ + if ( builder->path_begun ) + { + error = close_open_path( builder ); + if ( error ) + return error; + } + + error = gload_closepath( builder ); + + FT_GlyphLoader_Add( builder->loader ); + + return error; + } + + + static + FT_Error gload_sbw( T1_Builder* builder, + FT_Pos sbx, + FT_Pos sby, + FT_Pos wx, + FT_Pos wy ) + { + builder->left_bearing.x += sbx; + builder->left_bearing.y += sby; + builder->advance.x = wx; + builder->advance.y = wy; + + builder->last.x = sbx; + builder->last.y = sby; + + return 0; + } + + + static + FT_Error gload_rlineto( T1_Builder* builder, + FT_Pos dx, + FT_Pos dy ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Vector vec; + + + /* grow buffer if necessary */ + error = T1_Add_Points( builder, 1 ); + if ( error ) + return error; + + if ( builder->load_points ) + { + /* save point */ + vec.x = builder->last.x + dx; + vec.y = builder->last.y + dy; + + cur->points[cur->n_points] = vec; + cur->tags [cur->n_points] = FT_Curve_Tag_On; + + builder->last = vec; + } + cur->n_points++; + + builder->path_begun = 1; + + return T1_Err_Ok; + } + + + static + FT_Error gload_rmoveto( T1_Builder* builder, + FT_Pos dx, + FT_Pos dy ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Vector vec; + + + /* in the case where `path_begun' is set, we have an `rmoveto' */ + /* after some normal path definition. If the face's paint type */ + /* is set to 1, this means that we have an `open path', also */ + /* called a `stroke'. The FreeType raster doesn't support */ + /* opened paths, so we'll close it explicitely there. */ + + if ( builder->path_begun && builder->face->type1.paint_type == 1 ) + { + if ( builder->face->type1.paint_type == 1 ) + { + error = close_open_path( builder ); + if ( error ) + return error; + } + } + + /* grow buffer if necessary */ + error = T1_Add_Contours( builder, 1 ) || + T1_Add_Points ( builder, 1 ); + if ( error ) + return error; + + /* save current contour, if any */ + if ( cur->n_contours > 0 ) + cur->contours[cur->n_contours - 1] = cur->n_points - 1; + + if ( builder->load_points ) + { + /* save point */ + vec.x = builder->last.x + dx; + vec.y = builder->last.y + dy; + cur->points[cur->n_points] = vec; + cur->tags [cur->n_points] = FT_Curve_Tag_On; + + builder->last = vec; + } + + cur->n_contours++; + cur->n_points++; + + return T1_Err_Ok; + } + + + static + FT_Error gload_rrcurveto( T1_Builder* builder, + FT_Pos dx1, + FT_Pos dy1, + FT_Pos dx2, + FT_Pos dy2, + FT_Pos dx3, + FT_Pos dy3 ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Vector vec; + FT_Vector* points; + char* tags; + + + /* grow buffer if necessary */ + error = T1_Add_Points( builder, 3 ); + if ( error ) + return error; + + if ( builder->load_points ) + { + /* save point */ + points = cur->points + cur->n_points; + tags = cur->tags + cur->n_points; + + vec.x = builder->last.x + dx1; + vec.y = builder->last.y + dy1; + points[0] = vec; + tags[0] = FT_Curve_Tag_Cubic; + + vec.x += dx2; + vec.y += dy2; + points[1] = vec; + tags[1] = FT_Curve_Tag_Cubic; + + vec.x += dx3; + vec.y += dy3; + points[2] = vec; + tags[2] = FT_Curve_Tag_On; + + builder->last = vec; + } + + cur->n_points += 3; + builder->path_begun = 1; + + return T1_Err_Ok; + } + + + static + FT_Error gload_ignore( void ) + { + return 0; + } + + + static + const T1_Builder_Funcs gload_builder_interface = + { + gload_endchar, + gload_sbw, + gload_closepath, + gload_rlineto, + gload_rmoveto, + gload_rrcurveto + }; + + + static + const T1_Builder_Funcs gload_builder_interface_null = + { + (T1_Builder_EndChar) gload_ignore, + (T1_Builder_Sbw) gload_sbw, /* record left bearing */ + (T1_Builder_ClosePath)gload_ignore, + (T1_Builder_RLineTo) gload_ignore, + (T1_Builder_RMoveTo) gload_ignore, + (T1_Builder_RCurveTo) gload_ignore + }; + + + static + const T1_Hinter_Funcs gload_hinter_interface = + { + (T1_Hinter_DotSection) gload_ignore, /* dotsection */ + (T1_Hinter_ChangeHints)gload_ignore, /* changehints */ + (T1_Hinter_Stem) gload_ignore, /* hstem & vstem */ + (T1_Hinter_Stem3) gload_ignore, /* hstem3 & vestem3 */ + }; + + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + + /*************************************************************************/ + /* */ + /* Hinter overview: */ + /* */ + /* This is a two-pass hinter. On the first pass, the hints are all */ + /* recorded by the hinter, and no point is loaded in the outline. */ + /* */ + /* When the first pass is finished, all stems hints are grid-fitted */ + /* at once. */ + /* */ + /* Then, a second pass is performed to load the outline points as */ + /* well as hint/scale them correctly. */ + /* */ + /*************************************************************************/ + + + static + FT_Error t1_load_hinted_glyph( T1_Decoder* decoder, + FT_UInt glyph_index, + FT_Bool recurse ) + { + T1_Builder* builder = &decoder->builder; + T1_GlyphSlot glyph = builder->glyph; + T1_Font* type1 = &builder->face->type1; + FT_UInt old_points, old_contours; + FT_GlyphLoader* loader = decoder->builder.loader; + FT_Error error; + + + /* Pass 1 -- try to load first glyph, simply recording points */ + old_points = loader->base.outline.n_points; + old_contours = loader->base.outline.n_contours; + + FT_GlyphLoader_Prepare( decoder->builder.loader ); + + T1_Reset_Builder( builder, 0 ); + + builder->no_recurse = recurse; + builder->pass = 0; + glyph->hints->hori_stems.num_stems = 0; + glyph->hints->vert_stems.num_stems = 0; + + error = T1_Parse_CharStrings( decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + goto Exit; + + /* check for composite (i.e. `seac' operator) */ + if ( glyph->root.format == ft_glyph_format_composite ) + { + /* this is a composite glyph, we must then load the first one, */ + /* then load the second one on top of it and translate it by a */ + /* fixed amount. */ + FT_UInt n_base_points; + FT_SubGlyph* subglyph = loader->base.subglyphs; + T1_Size size = builder->size; + FT_Pos dx, dy; + FT_Vector left_bearing, advance; + + + /* clean glyph format */ + glyph->root.format = ft_glyph_format_none; + + /* First load `bchar' in builder */ + builder->no_recurse = 0; + error = t1_load_hinted_glyph( decoder, subglyph->index, 0 ); + if ( error ) + goto Exit; + + /* save the left bearing and width of the base character */ + /* as they will be erased by the next load */ + left_bearing = builder->left_bearing; + advance = builder->advance; + + /* Then load `achar' in builder */ + n_base_points = builder->base->n_points; + subglyph++; + error = t1_load_hinted_glyph( decoder, subglyph->index, 0 ); + if ( error ) + goto Exit; + + /* Finally, move the accent */ + dx = FT_MulFix( subglyph->arg1, size->root.metrics.x_scale ); + dy = FT_MulFix( subglyph->arg2, size->root.metrics.y_scale ); + dx = ( dx + 32 ) & -64; + dy = ( dy + 32 ) & -64; + { + FT_Outline dummy; + + + dummy.n_points = loader->base.outline.n_points - n_base_points; + dummy.points = loader->base.outline.points + n_base_points; + + FT_Outline_Translate( &dummy, dx, dy ); + } + + /* restore the left side bearing and */ + /* advance width of the base character */ + builder->left_bearing = left_bearing; + builder->advance = advance; + } + else + { + /* All right, pass 1 is finished, now grid-fit all stem hints */ + T1_Hint_Stems( &decoder->builder ); + + /* undo the end-char */ + builder->base->n_points = old_points; + builder->base->n_contours = old_contours; + + /* Pass 2 -- record and scale/hint the points */ + T1_Reset_Builder( builder, 0 ); + + builder->pass = 1; + builder->no_recurse = 0; + + error = T1_Parse_CharStrings( decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + } + + /* save new glyph tables */ + if ( recurse ) + T1_Done_Builder( builder ); + + Exit: + return error; + } + + +#endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */ + + + LOCAL_FUNC + 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; + + + 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; + + glyph->root.format = ft_glyph_format_outline; /* by default */ + + hinting = 0; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + hinting = ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0; + + if ( hinting ) + { + T1_Init_Decoder( &decoder, &t1_hinter_funcs ); + T1_Init_Builder( &decoder.builder, face, size, glyph, + &gload_builder_interface ); + + error = t1_load_hinted_glyph( &decoder, glyph_index, 1 ); + } + else + +#endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */ + + { + T1_Init_Decoder( &decoder, &gload_hinter_interface ); + + T1_Init_Builder( &decoder.builder, face, size, glyph, + &gload_builder_interface ); + + decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0; + + /* now load the unscaled outline */ + error = T1_Parse_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + + /* save new glyph tables */ + T1_Done_Builder( &decoder.builder ); + } + + /* 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 the left side bearing and the */ + /* advance width */ + if ( glyph->root.format == ft_glyph_format_composite ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.builder.advance.x; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, + &face->type1.font_matrix ); + + 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; + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.format = ft_glyph_format_outline; + + glyph->root.outline.flags = 0; + + if ( size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= ft_outline_high_precision; + + glyph->root.outline.flags |= ft_outline_reverse_fill; + + if ( hinting ) + { + /* adjust the advance width */ + /* XXX TODO: consider stem hints grid-fit */ + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, + glyph->x_scale ); + } + else 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 ); + } + + /* Then scale the metrics */ + metrics->width = FT_MulFix( metrics->width, x_scale ); + metrics->height = FT_MulFix( metrics->height, y_scale ); + + metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale ); + metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale ); + + metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); + metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); + + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + } + } + } + + return error; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1gload.h b/reactos/subsys/win32k/freetype/t1gload.h new file mode 100644 index 00000000000..658a929d068 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1gload.h @@ -0,0 +1,326 @@ +/***************************************************************************/ +/* */ +/* t1gload.h */ +/* */ +/* Type 1 Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct T1_Builder_ T1_Builder; + + typedef FT_Error (*T1_Builder_EndChar)( T1_Builder* loader ); + + typedef FT_Error (*T1_Builder_Sbw)( T1_Builder* loader, + FT_Pos sbx, + FT_Pos sby, + FT_Pos wx, + FT_Pos wy ); + + typedef FT_Error (*T1_Builder_ClosePath)( T1_Builder* loader ); + + typedef FT_Error (*T1_Builder_RLineTo)( T1_Builder* loader, + FT_Pos dx, + FT_Pos dy ); + + typedef FT_Error (*T1_Builder_RMoveTo)( T1_Builder* loader, + FT_Pos dx, + FT_Pos dy ); + + typedef FT_Error (*T1_Builder_RCurveTo)( T1_Builder* loader, + FT_Pos dx1, + FT_Pos dy1, + FT_Pos dx2, + FT_Pos dy2, + FT_Pos dx3, + FT_Pos dy3 ); + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Builder_Funcs */ + /* */ + /* */ + /* A structure to store the address of various functions used by a */ + /* glyph builder to implement the outline's `path construction'. */ + /* */ + typedef struct T1_Builder_Funcs_ + { + T1_Builder_EndChar end_char; + T1_Builder_Sbw set_bearing_point; + T1_Builder_ClosePath close_path; + T1_Builder_RLineTo rline_to; + T1_Builder_RMoveTo rmove_to; + T1_Builder_RCurveTo rcurve_to; + + } T1_Builder_Funcs; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* loader :: The current glyph loader. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* base :: The base glyph 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 (for composite glyphs). */ + /* */ + /* pos_y :: The vertical translation (for composite glyphs). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* no_recurse :: */ + /* */ + /* bbox :: The glyph's bounding box. */ + /* */ + /* path_begun :: A flag which indicates that a new path has begun. */ + /* */ + /* load_points :: A flag which indicates, if not set, that no points */ + /* are loaded. */ + /* */ + /* pass :: The pass number for multi-pass hinters. */ + /* */ + /* hint_point :: The index of the next point to hint. */ + /* */ + /* funcs :: A table of builder functions used to perform the */ + /* outline's path construction. */ + /* */ + struct T1_Builder_ + { + FT_Memory memory; + T1_Face face; + T1_Size size; + T1_GlyphSlot glyph; + FT_GlyphLoader* loader; + + FT_Outline* current; /* the current glyph outline */ + FT_Outline* base; /* the composite glyph outline */ + + 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_Bool no_recurse; + + FT_BBox bbox; /* bounding box */ + FT_Bool path_begun; + FT_Bool load_points; + + FT_Int pass; + FT_Int hint_point; + + /* path construction function interface */ + T1_Builder_Funcs funcs; + }; + + + typedef FT_Error (*T1_Hinter_ChangeHints)( T1_Builder* builder ); + + typedef FT_Error (*T1_Hinter_DotSection)( T1_Builder* builder ); + + typedef FT_Error (*T1_Hinter_Stem)( T1_Builder* builder, + FT_Pos pos, + FT_Pos width, + FT_Bool vertical ); + + typedef FT_Error (*T1_Hinter_Stem3)( T1_Builder* builder, + FT_Pos pos0, + FT_Pos width0, + FT_Pos pos1, + FT_Pos width1, + FT_Pos pos2, + FT_Pos width2, + FT_Bool vertical ); + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Hinter_Funcs */ + /* */ + /* */ + /* A structure to store the address of various functions used by a */ + /* Type 1 hinter to perform outline hinting. */ + /* */ + typedef struct T1_Hinter_Func_ + { + T1_Hinter_ChangeHints change_hints; + T1_Hinter_DotSection dot_section; + T1_Hinter_Stem stem; + T1_Hinter_Stem3 stem3; + + } T1_Hinter_Funcs; + + + 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; + + + /* execution context charstring zone */ + typedef struct T1_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } T1_Decoder_Zone; + + + typedef struct T1_Decoder_ + { + T1_Builder builder; + T1_Hinter_Funcs hinter; + + FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS]; + FT_Int* top; + + T1_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1]; + T1_Decoder_Zone* zone; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + } T1_Decoder; + + + LOCAL_DEF + void T1_Init_Builder( T1_Builder* builder, + T1_Face face, + T1_Size size, + T1_GlyphSlot glyph, + const T1_Builder_Funcs* funcs ); + + LOCAL_DEF + void T1_Done_Builder( T1_Builder* builder ); + + LOCAL_DEF + void T1_Init_Decoder( T1_Decoder* decoder, + const T1_Hinter_Funcs* funcs ); + + LOCAL_DEF + FT_Error T1_Compute_Max_Advance( T1_Face face, + FT_Int* max_advance ); + + LOCAL_DEF + FT_Error T1_Parse_CharStrings( T1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ); + + LOCAL_DEF + FT_Error T1_Add_Points( T1_Builder* builder, + FT_Int num_points ); + + LOCAL_DEF + FT_Error T1_Add_Contours( T1_Builder* builder, + FT_Int num_contours ); + + LOCAL_DEF + FT_Error T1_Load_Glyph( T1_GlyphSlot glyph, + T1_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T1GLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1hinter.c b/reactos/subsys/win32k/freetype/t1hinter.c new file mode 100644 index 00000000000..7ce746228aa --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1hinter.c @@ -0,0 +1,1347 @@ +/***************************************************************************/ +/* */ +/* t1hinter.c */ +/* */ +/* Type 1 hinter (body). */ +/* */ +/* Copyright 1996-2000 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 Hinter is in charge of fitting th scaled outline to the pixel */ + /* grid in order to considerably improve the quality of the Type 1 font */ + /* driver's output. */ + /* */ + /*************************************************************************/ + + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" +#include "t1hinter.h" + +#else + +#include +#include + +#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_t1hint + + +#undef ONE_PIXEL +#define ONE_PIXEL 64 + +#undef ROUND +#define ROUND( x ) ( ( x + ONE_PIXEL / 2 ) & -ONE_PIXEL ) + +#undef SCALE +#define SCALE( val ) FT_MulFix( val, scale ) + +/* various constants used to describe the alignment of a horizontal */ +/* stem with regards to the blue zones */ + +#define T1_ALIGN_NONE 0 +#define T1_ALIGN_BOTTOM 1 +#define T1_ALIGN_TOP 2 +#define T1_ALIGN_BOTH 3 + + + /* very simple bubble sort (not a lot of elements, mostly */ + /* pre-sorted, no need for quicksort) */ + + static + void t1_sort_blues( FT_Int* blues, + FT_Int count ) + { + FT_Int i, swap; + FT_Int* cur; + + + for ( i = 2; i < count; i += 2 ) + { + cur = blues + i; + do + { + if ( cur[-1] < cur[0] ) + break; + + swap = cur[-2]; cur[-2] = cur[0]; cur[0] = swap; + swap = cur[-1]; cur[-1] = cur[1]; cur[1] = swap; + cur -= 2; + + } while ( cur > blues ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_set_blue_zones */ + /* */ + /* */ + /* Sets a size object's blue zones during reset. This will compute */ + /* the `snap' zone corresponding to each blue zone. */ + /* */ + /* */ + /* size :: A handle to target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This functions does the following: */ + /* */ + /* 1. It extracts the bottom and top blue zones from the face object. */ + /* */ + /* 2. Each zone is then grown by `BlueFuzz', overlapping is */ + /* eliminated by adjusting the zone edges appropriately. */ + /* */ + /* 3. For each zone, we keep its original font units position, its */ + /* original scaled position, as well as its grown/adjusted edges. */ + /* */ + static + FT_Error t1_set_blue_zones( T1_Size size ) + { + T1_Face face = (T1_Face)size->root.face; + T1_Private* priv = &face->type1.private_dict; + FT_Int n; + FT_Int blues[24]; + FT_Int num_bottom; + FT_Int num_top; + FT_Int num_blues; + T1_Size_Hints* hints = size->hints; + T1_Snap_Zone* zone; + FT_Pos pix, orus; + FT_Pos min, max, threshold; + FT_Fixed scale; + FT_Bool is_bottom; + + + /***********************************************************************/ + /* */ + /* copy bottom and top blue zones in local arrays */ + /* */ + + /* First of all, check the sizes of the /BlueValues and /OtherBlues */ + /* tables. They all must contain an even number of arguments. */ + if ( priv->num_other_blues & 1 || + priv->num_blue_values & 1 ) + { + FT_ERROR(( "t1_set_blue_zones: odd number of blue values\n" )); + return T1_Err_Syntax_Error; + } + + /* copy the bottom blue zones from /OtherBlues */ + num_top = 0; + num_bottom = priv->num_other_blues; + + for ( n = 0; n < num_bottom; n++ ) + blues[n] = priv->other_blues[n]; + + /* add the first blue zone in /BlueValues to the table */ + num_top = priv->num_blue_values - 2; + if ( num_top >= 0 ) + { + blues[num_bottom ] = priv->blue_values[0]; + blues[num_bottom + 1] = priv->blue_values[1]; + + num_bottom += 2; + } + + /* sort the bottom blue zones */ + t1_sort_blues( blues, num_bottom ); + + hints->num_bottom_zones = num_bottom >> 1; + + /* now copy the /BlueValues to the top of the blues array */ + if ( num_top > 0 ) + { + for ( n = 0; n < num_top; n++ ) + blues[num_bottom + n] = priv->blue_values[n + 2]; + + /* sort the top blue zones */ + t1_sort_blues( blues + num_bottom, num_top ); + } + else + num_top = 0; + + num_blues = num_top + num_bottom; + hints->num_blue_zones = ( num_blues ) >> 1; + + /***********************************************************************/ + /* */ + /* build blue snap zones from the local blues arrays */ + /* */ + + scale = size->root.metrics.y_scale; + zone = hints->blue_zones; + threshold = ONE_PIXEL / 4; /* 0.25 pixels */ + + for ( n = 0; n < num_blues; n += 2, zone++ ) + { + is_bottom = n < num_bottom ? 1 : 0; + + orus = blues[n + is_bottom]; /* get alignement coordinate */ + pix = SCALE( orus ); /* scale it */ + + min = SCALE( blues[n ] - priv->blue_fuzz ); + max = SCALE( blues[n + 1] + priv->blue_fuzz ); + + if ( min > pix - threshold ) + min = pix - threshold; + if ( max < pix + threshold ) + max = pix + threshold; + + zone->orus = orus; + zone->pix = pix; + zone->min = min; + zone->max = max; + } + + /* adjust edges in case of overlap */ + zone = hints->blue_zones; + for ( n = 0; n < num_blues - 2; n += 2, zone++ ) + { + if ( n != num_bottom - 2 && + zone[0].max > zone[1].min ) + zone[0].max = zone[1].min = ( zone[0].pix + zone[1].pix ) / 2; + } + + /* compare the current pixel size with the BlueScale value */ + /* to know whether to supress overshoots */ + + hints->supress_overshoots = + size->root.metrics.y_ppem < FT_MulFix( 1000, priv->blue_scale ); + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* now print the new blue values in tracing mode */ + + FT_TRACE2(( "Blue Zones for size object at $%08lx:\n", (long)size )); + FT_TRACE2(( " orus pix min max\n" )); + FT_TRACE2(( "-------------------------------\n" )); + + zone = hints->blue_zones; + for ( n = 0; n < hints->num_blue_zones; n++ ) + { + FT_TRACE2(( " %3d %.2f %.2f %.2f\n", + zone->orus, + zone->pix / 64.0, + zone->min / 64.0, + zone->max / 64.0 )); + zone++; + } + FT_TRACE2(( "\nOvershoots are %s\n\n", + hints->supress_overshoots ? "supressed" : "active" )); + +#endif /* DEBUG_LEVEL_TRACE */ + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_set_snap_zones */ + /* */ + /* */ + /* This function set a size object's stem snap zones. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function performs the following: */ + /* */ + /* 1. It reads and scales the stem snap widths from the parent face. */ + /* */ + /* 2. A `snap zone' is computed for each snap width, by `growing' it */ + /* with a threshold of 1/2 pixel. Overlapping is avoided through */ + /* proper edge adjustment. */ + /* */ + /* 3. Each width whose zone contain the scaled standard set width is */ + /* removed from the table. */ + /* */ + /* 4. Finally, the standard set width is scaled, and its correponding */ + /* `snap zone' is inserted into the sorted snap zones table. */ + /* */ + static + FT_Error t1_set_snap_zones( T1_Size size ) + { + FT_Int n, direction, n_zones, num_zones; + T1_Snap_Zone* zone; + T1_Snap_Zone* base_zone; + FT_Short* orgs; + FT_Pos standard_width; + FT_Fixed scale; + + T1_Face face = (T1_Face)size->root.face; + T1_Private* priv = &face->type1.private_dict; + T1_Size_Hints* hints = size->hints; + + + /* start with horizontal snap zones */ + direction = 0; + standard_width = priv->standard_width[0]; + n_zones = priv->num_snap_widths; + base_zone = hints->snap_widths; + orgs = priv->snap_widths; + scale = size->root.metrics.x_scale; + + while ( direction < 2 ) + { + /*********************************************************************/ + /* */ + /* Read and scale stem snap widths table from the physical font */ + /* record. */ + /* */ + + FT_Pos prev, orus, pix, min, max, threshold; + + + threshold = ONE_PIXEL / 4; + zone = base_zone; + + if ( n_zones > 0 ) + { + orus = *orgs++; + pix = SCALE( orus ); + min = pix - threshold; + max = pix + threshold; + + zone->orus = orus; + zone->pix = pix; + zone->min = min; + prev = pix; + + for ( n = 1; n < n_zones; n++ ) + { + orus = *orgs++; + pix = SCALE( orus ); + + if ( pix - prev < 2 * threshold ) + { + min = max = ( pix + prev ) / 2; + } + else + min = pix - threshold; + + zone->max = max; + zone++; + zone->orus = orus; + zone->pix = pix; + zone->min = min; + + max = pix + threshold; + prev = pix; + } + zone->max = max; + } + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* print the scaled stem snap values in tracing mode */ + + FT_TRACE2(( "Set_Snap_Zones: first %s pass\n", + direction ? "vertical" : "horizontal" )); + + FT_TRACE2(( "Scaled original stem snap zones:\n" )); + FT_TRACE2(( " orus pix min max\n" )); + FT_TRACE2(( "-----------------------------\n" )); + + zone = base_zone; + for ( n = 0; n < n_zones; n++, zone++ ) + FT_TRACE2(( " %3d %.2f %.2f %.2f\n", + zone->orus, + zone->pix / 64.0, + zone->min / 64.0, + zone->max / 64.0 )); + FT_TRACE2(( "\n" )); + + FT_TRACE2(( "Standard width = %d\n", standard_width )); + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + /*********************************************************************/ + /* */ + /* Now, each snap width which is in the range of the standard set */ + /* width will be removed from the list. */ + /* */ + + if ( standard_width > 0 ) + { + T1_Snap_Zone* parent; + FT_Pos std_pix, std_min, std_max; + + + std_pix = SCALE( standard_width ); + + std_min = std_pix - threshold; + std_max = std_pix + threshold; + + num_zones = 0; + zone = base_zone; + parent = base_zone; + + for ( n = 0; n < n_zones; n++ ) + { + if ( zone->pix >= std_min && zone->pix <= std_max ) + { + /* this zone must be removed from the list */ + if ( std_min > zone->min ) + std_min = zone->min; + if ( std_max < zone->max ) + std_max = zone->max; + } + else + { + *parent++ = *zone; + num_zones++; + } + zone++; + } + + /*******************************************************************/ + /* */ + /* Now, insert the standard width zone */ + /* */ + + zone = base_zone + num_zones; + while ( zone > base_zone && zone[-1].pix > std_max ) + { + zone[0] = zone[-1]; + zone--; + } + + /* check border zones */ + if ( zone > base_zone && zone[-1].max > std_min ) + zone[-1].max = std_min; + + if ( zone < base_zone + num_zones && zone[1].min < std_max ) + zone[1].min = std_max; + + zone->orus = standard_width; + zone->pix = std_pix; + zone->min = std_min; + zone->max = std_max; + + num_zones++; + } + else + num_zones = n_zones; + + /* save total number of stem snaps now */ + if ( direction ) + hints->num_snap_heights = num_zones; + else + hints->num_snap_widths = num_zones; + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* print the scaled stem snap values in tracing mode */ + + FT_TRACE2(( "Set_Snap_Zones: second %s pass\n", + direction ? "vertical" : "horizontal" )); + + FT_TRACE2(( "Scaled clipped stem snap zones:\n" )); + FT_TRACE2(( " orus pix min max\n" )); + FT_TRACE2(( "-----------------------------\n" )); + + zone = base_zone; + for ( n = 0; n < num_zones; n++, zone++ ) + FT_TRACE2(( " %3d %.2f %.2f %.2f\n", + zone->orus, + zone->pix / 64.0, + zone->min / 64.0, + zone->max / 64.0 )); + FT_TRACE2(( "\n" )); + + FT_TRACE2(( "Standard width = %d\n", standard_width )); + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + /* continue with vertical snap zone */ + direction++; + standard_width = priv->standard_height[0]; + n_zones = priv->num_snap_heights; + base_zone = hints->snap_heights; + orgs = priv->snap_heights; + scale = size->root.metrics.y_scale; + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_New_Size_Hinter */ + /* */ + /* */ + /* Allocates a new hinter structure for a given size object. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType Error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_New_Size_Hinter( T1_Size size ) + { + FT_Memory memory = size->root.face->memory; + + + return MEM_Alloc( size->hints, sizeof ( *size->hints ) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Size_Hinter */ + /* */ + /* */ + /* Releases a given size object's hinter structure. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_FUNC + void T1_Done_Size_Hinter( T1_Size size ) + { + FT_Memory memory = size->root.face->memory; + + + FREE( size->hints ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Reset_Size_Hinter */ + /* */ + /* */ + /* Recomputes hinting information when a given size object has */ + /* changed its resolutions/char sizes/pixel sizes. */ + /* */ + /* */ + /* size :: A handle to the size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Reset_Size_Hinter( T1_Size size ) + { + return t1_set_blue_zones( size ) || t1_set_snap_zones( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_New_Glyph_Hinter */ + /* */ + /* */ + /* Allocates a new hinter structure for a given glyph slot. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph slot. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph ) + { + FT_Memory memory = glyph->root.face->memory; + + + return MEM_Alloc( glyph->hints, sizeof ( *glyph->hints ) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Glyph_Hinter */ + /* */ + /* */ + /* Releases a given glyph slot's hinter structure. */ + /* */ + /* */ + /* glyph :: A handle to the glyph slot. */ + /* */ + LOCAL_FUNC + void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph ) + { + FT_Memory memory = glyph->root.face->memory; + + + FREE( glyph->hints ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** **********/ + /********** HINTED GLYPH LOADER **********/ + /********** **********/ + /********** The following code is in charge of the first **********/ + /********** and second pass when loading a single outline **********/ + /********** **********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error t1_hinter_ignore( void ) + { + /* do nothing, used for `dotsection' which is unsupported for now */ + return 0; + } + + + static + FT_Error t1_hinter_stem( T1_Builder* builder, + FT_Pos pos, + FT_Int width, + FT_Bool vertical ) + { + T1_Stem_Table* stem_table; + T1_Stem_Hint* stems; + T1_Stem_Hint* cur_stem; + FT_Int min, max, n, num_stems; + FT_Bool new_stem; + T1_Glyph_Hints* hinter = builder->glyph->hints; + + + /* select the appropriate stem array */ + stem_table = vertical ? &hinter->vert_stems : &hinter->hori_stems; + stems = stem_table->stems; + num_stems = stem_table->num_stems; + + /* Compute minimum and maximum coord for the stem */ + min = pos + ( vertical + ? builder->left_bearing.x + : builder->left_bearing.y ); + + if ( width >= 0 ) + max = min + width; + else + { + /* a negative width indicates a `ghost' stem */ + if ( width == -21 ) + min += width; + + max = min; + } + + /* Now scan the array. If we find a stem with the same borders */ + /* simply activate it. */ + cur_stem = stems; + new_stem = 1; + + for ( n = 0; n < num_stems; n++, cur_stem++ ) + { + if ( cur_stem->min_edge.orus == min && + cur_stem->max_edge.orus == max ) + { + /* This stem is already in the table, simply activate it */ + if ( ( cur_stem->hint_flags & T1_HINT_FLAG_ACTIVE ) == 0 ) + { + cur_stem->hint_flags |= T1_HINT_FLAG_ACTIVE; + stem_table->num_active++; + } + new_stem = 0; + break; + } + } + + /* add a new stem to the array if necessary */ + if ( new_stem ) + { + if ( cur_stem >= stems + T1_HINTER_MAX_EDGES ) + { + FT_ERROR(( "t1_hinter_stem: too many stems in glyph charstring\n" )); + return T1_Err_Syntax_Error; + } + + /* on the first pass, we record the stem, otherwise, this is */ + /* a bug in the glyph loader! */ + if ( builder->pass == 0 ) + { + cur_stem->min_edge.orus = min; + cur_stem->max_edge.orus = max; + cur_stem->hint_flags = T1_HINT_FLAG_ACTIVE; + + stem_table->num_stems++; + stem_table->num_active++; + } + else + { + FT_ERROR(( "t1_hinter_stem:" )); + FT_ERROR(( " fatal glyph loader bug -- pass2-stem\n" )); + return T1_Err_Syntax_Error; + } + } + + return T1_Err_Ok; + } + + + static + FT_Error t1_hinter_stem3( T1_Builder* builder, + FT_Pos pos0, + FT_Int width0, + FT_Pos pos1, + FT_Int width1, + FT_Pos pos2, + FT_Int width2, + FT_Bool vertical ) + { + /* For now, simply call `stem' 3 times */ + return t1_hinter_stem( builder, pos0, width0, vertical ) || + t1_hinter_stem( builder, pos1, width1, vertical ) || + t1_hinter_stem( builder, pos2, width2, vertical ); + } + + + static + FT_Error t1_hinter_changehints( T1_Builder* builder ) + { + FT_Int dimension; + T1_Stem_Table* stem_table; + T1_Glyph_Hints* hinter = builder->glyph->hints; + + + /* If we are in the second pass of glyph hinting, we must */ + /* call the function T1_Hint_Points() on the builder in order */ + /* to force the fit the latest points to the pixel grid. */ + if ( builder->pass == 1 ) + T1_Hint_Points( builder ); + + /* Simply de-activate all hints in all arrays */ + stem_table = &hinter->hori_stems; + + for ( dimension = 2; dimension > 0; dimension-- ) + { + T1_Stem_Hint* cur = stem_table->stems; + T1_Stem_Hint* limit = cur + stem_table->num_stems; + + + for ( ; cur < limit; cur++ ) + cur->hint_flags &= ~T1_HINT_FLAG_ACTIVE; + + stem_table->num_active = 0; + stem_table = &hinter->vert_stems; + } + + return T1_Err_Ok; + } + + + const T1_Hinter_Funcs t1_hinter_funcs = + { + (T1_Hinter_ChangeHints)t1_hinter_changehints, + (T1_Hinter_DotSection) t1_hinter_ignore, + (T1_Hinter_Stem) t1_hinter_stem, + (T1_Hinter_Stem3) t1_hinter_stem3 + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** STEM HINTS MANAGEMENT *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the placement of each scaled stem hint. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* t1_sort_hints */ + /* */ + /* */ + /* Sorta the list of active stems in increasing order, through the */ + /* `sort' indexing table. */ + /* */ + /* */ + /* table :: A stem hints table. */ + /* */ + static + void t1_sort_hints( T1_Stem_Table* table ) + { + FT_Int num_stems = table->num_stems; + FT_Int num_active = 0; + FT_Int* sort = table->sort; + T1_Stem_Hint* stems = table->stems; + FT_Int n; + + + /* record active stems in sort table */ + for ( n = 0; n < num_stems; n++ ) + { + if ( stems[n].hint_flags & T1_HINT_FLAG_ACTIVE ) + sort[num_active++] = n; + } + + /* Now sort the indices. There are usually very few stems, */ + /* and they are pre-sorted in 90% cases, so we choose a */ + /* simple bubble sort (quicksort would be slower). */ + for ( n = 1; n < num_active; n++ ) + { + FT_Int p = n - 1; + T1_Stem_Hint* cur = stems + sort[n]; + + + do + { + FT_Int swap; + T1_Stem_Hint* prev = stems + sort[p]; + + + /* note that by definition, the active stems cannot overlap */ + /* so we simply compare their `min' to sort them (we could compare */ + /* their max values also; this wouldn't change anything). */ + if ( prev->min_edge.orus <= cur->min_edge.orus ) + break; + + /* swap elements */ + swap = sort[p ]; + sort[p ] = sort[p + 1]; + sort[p + 1] = swap; + p--; + + } while ( p >= 0 ); + } + + table->num_active = num_active; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hint_horizontal_stems */ + /* */ + /* */ + /* Computes the location of each scaled horizontal stem hint. This */ + /* takes care of the blue zones and the horizontal stem snap table. */ + /* */ + /* */ + /* table :: The horizontal stem hints table. */ + /* */ + /* hints :: The current size's hint structure. */ + /* */ + /* blueShift :: The value of the /BlueShift as taken from the face */ + /* object. */ + /* */ + /* scale :: The 16.16 scale used to convert outline units to */ + /* 26.6 pixels. */ + /* */ + /* */ + /* For now, all stems are hinted independently from each other. It */ + /* might be necessary, for better performance, to introduce the */ + /* notion of `controlled' hints describing things like counter-stems, */ + /* stem3, as well as overlapping stems control. */ + /* */ + static + void t1_hint_horizontal_stems( T1_Stem_Table* table, + T1_Size_Hints* hints, + FT_Pos blueShift, + FT_Fixed scale ) + { + T1_Stem_Hint* stem = table->stems; + T1_Stem_Hint* limit = stem + table->num_stems; + + + /* first of all, scale the blueShift */ + blueShift = SCALE( blueShift ); + + /* then scan the horizontal stem table */ + for ( ; stem < limit; stem++ ) + { + FT_Pos bottom_orus = stem->min_edge.orus; + FT_Pos top_orus = stem->max_edge.orus; + + FT_Pos top_pix = SCALE( top_orus ); + FT_Pos bottom_pix = SCALE( bottom_orus ); + FT_Pos width_pix = top_pix - bottom_pix; + + FT_Pos bottom = bottom_pix; + FT_Pos top = top_pix; + FT_Int align = T1_ALIGN_NONE; + + + /*********************************************************************/ + /* */ + /* Snap pixel width if in stem snap range */ + /* */ + + { + T1_Snap_Zone* zone = hints->snap_heights; + T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights; + FT_Pos best_dist = 32000; + T1_Snap_Zone* best_zone = 0; + + + for ( ; zone < zone_limit; zone++ ) + { + FT_Pos dist; + + + dist = width_pix - zone->min; + if ( dist < 0 ) + dist = -dist; + if ( dist < best_dist ) + { + best_zone = zone; + best_dist = dist; + } + } + + if ( best_zone ) + { + if ( width_pix > best_zone->pix ) + { + width_pix -= 0x20; + if ( width_pix < best_zone->pix ) + width_pix = best_zone->pix; + } + else + { + width_pix += 0x20; + if ( width_pix > best_zone->pix ) + width_pix = best_zone->pix; + } + } + } + + /*********************************************************************/ + /* */ + /* round width - minimum 1 pixel if this isn't a ghost stem */ + /* */ + + if ( width_pix > 0 ) + width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND( width_pix ); + + + /*********************************************************************/ + /* */ + /* Now check for bottom blue zones alignement */ + /* */ + + { + FT_Int num_blues = hints->num_bottom_zones; + T1_Snap_Zone* blue = hints->blue_zones; + T1_Snap_Zone* blue_limit = blue + num_blues; + + + for ( ; blue < blue_limit; blue++ ) + { + if ( bottom_pix < blue->min ) + break; + + if ( bottom_pix <= blue->max ) + { + align = T1_ALIGN_BOTTOM; + bottom = ROUND( blue->pix ); + + /* implement blue shift */ + if ( !hints->supress_overshoots ) + { + FT_Pos delta = blue->pix - bottom_pix; + + + delta = delta < blueShift ? 0 : ROUND( delta ); + bottom -= delta; + } + } + } + } + + /*********************************************************************/ + /* */ + /* check for top blue zones alignement */ + /* */ + + { + FT_Int num_blues = hints->num_blue_zones - + hints->num_bottom_zones; + + T1_Snap_Zone* blue = hints->blue_zones + + hints->num_bottom_zones; + + T1_Snap_Zone* blue_limit = blue + num_blues; + + + for ( ; blue < blue_limit; blue++ ) + { + if ( top_pix < blue->min ) + break; + + if ( top_pix <= blue->max ) + { + align |= T1_ALIGN_TOP; + top = ROUND( blue->pix ); + + /* implement blue shift */ + if ( !hints->supress_overshoots ) + { + FT_Pos delta = top - blue->pix; + + + delta = delta < blueShift ? 0 : ROUND( delta ); + top += delta; + } + } + } + } + + /*********************************************************************/ + /* */ + /* compute the hinted stem position, according to its alignment */ + /* */ + + switch ( align ) + { + case T1_ALIGN_BOTTOM: /* bottom zone alignment */ + bottom_pix = bottom; + top_pix = bottom + width_pix; + break; + + case T1_ALIGN_TOP: /* top zone alignment */ + top_pix = top; + bottom_pix = top - width_pix; + break; + + case T1_ALIGN_BOTH: /* bottom+top zone alignment */ + bottom_pix = bottom; + top_pix = top; + break; + + default: /* no alignment */ + /* XXX TODO: Add management of controlled stems */ + bottom = ( SCALE( bottom_orus + top_orus ) - width_pix ) / 2; + + bottom_pix = ROUND( bottom ); + top_pix = bottom_pix + width_pix; + } + + stem->min_edge.pix = bottom_pix; + stem->max_edge.pix = top_pix; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hint_vertical_stems */ + /* */ + /* */ + /* Computes the location of each scaled vertical stem hint. This */ + /* takes care of the vertical stem snap table. */ + /* */ + /* */ + /* table :: The vertical stem hints table. */ + /* hints :: The current size's hint structure. */ + /* scale :: The 16.16 scale used to convert outline units to */ + /* 26.6 pixels. */ + /* */ + /* */ + /* For now, all stems are hinted independently from each other. It */ + /* might be necessary, for better performance, to introduce the */ + /* notion of `controlled' hints describing things like counter-stems, */ + /* stem3 as well as overlapping stems control. */ + /* */ + static + void t1_hint_vertical_stems( T1_Stem_Table* table, + T1_Size_Hints* hints, + FT_Fixed scale ) + { + T1_Stem_Hint* stem = table->stems; + T1_Stem_Hint* limit = stem + table->num_stems; + + + for ( ; stem < limit; stem++ ) + { + FT_Pos stem_left = stem->min_edge.orus; + FT_Pos stem_right = stem->max_edge.orus; + FT_Pos width_pix, left; + + + width_pix = SCALE( stem_right - stem_left ); + + /* Snap pixel width if in stem snap range */ + { + T1_Snap_Zone* zone = hints->snap_heights; + T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights; + FT_Pos best_dist = 32000; + T1_Snap_Zone* best_zone = 0; + + + for ( ; zone < zone_limit; zone++ ) + { + FT_Pos dist; + + + dist = width_pix - zone->min; + if ( dist < 0 ) + dist = -dist; + if ( dist < best_dist ) + { + best_zone = zone; + best_dist = dist; + } + } + + if ( best_zone ) + { + if ( width_pix > best_zone->pix ) + { + width_pix -= 0x20; + if ( width_pix < best_zone->pix ) + width_pix = best_zone->pix; + } + else + { + width_pix += 0x20; + if ( width_pix > best_zone->pix ) + width_pix = best_zone->pix; + } + } + } + + /* round width - minimum 1 pixel if this isn't a ghost stem */ + if ( width_pix > 0 ) + width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL + : ROUND( width_pix ); + + /* now place the snapped and rounded stem */ + + /* XXX TODO: implement controlled stems for the overlapping */ + /* cases */ + + left = ( SCALE( stem_left + stem_right ) - width_pix ) / 2; + + stem->min_edge.pix = ROUND( left ); + stem->max_edge.pix = stem->min_edge.pix + width_pix; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hint_point */ + /* */ + /* */ + /* Grid-fit a coordinate with regards to a given stem hints table. */ + /* */ + /* */ + /* table :: The source stem hints table. */ + /* coord :: The original coordinate, expressed in font units. */ + /* scale :: The 16.16 scale used to convert font units into */ + /* 26.6 pixels. */ + /* */ + /* */ + /* The hinted/scaled value in 26.6 pixels. */ + /* */ + /* */ + /* For now, all stems are hinted independently from each other. It */ + /* might be necessary, for better performance, to introduce the */ + /* notion of `controlled' hints describing things like counter-stems, */ + /* stem3 as well as overlapping stems control. */ + /* */ + static + FT_Pos t1_hint_point( T1_Stem_Table* table, + FT_Pos coord, + FT_Fixed scale ) + { + FT_Int num_active = table->num_active; + FT_Int n; + T1_Stem_Hint* prev = 0; + T1_Stem_Hint* cur = 0; + T1_Edge* min; + T1_Edge* max; + FT_Pos delta; + + + /* only hint when there is at least one stem defined */ + if ( num_active <= 0 ) + return SCALE( coord ); + + /* scan the stem table to determine placement of coordinate */ + /* relative to the list of sorted and stems */ + for ( n = 0; n < num_active; n++, prev = cur ) + { + cur = table->stems + table->sort[n]; + + /* is it on the left of the current edge? */ + delta = cur->min_edge.orus - coord; + if ( delta == 0 ) + return cur->min_edge.pix; + + if ( delta > 0 ) + { + /* if this is the left of the first edge, simply shift */ + if ( !prev ) + return cur->min_edge.pix - SCALE( delta ); + + /* otherwise, interpolate between the maximum of the */ + /* previous stem, and the minimum of the current one */ + min = &prev->max_edge; + max = &cur->min_edge; + + goto Interpolate; + } + + /* is it within the current edge? */ + delta = cur->max_edge.orus - coord; + if ( delta == 0 ) + return cur->max_edge.pix; + + if ( delta > 0 ) + { + /* interpolate within the stem */ + min = &cur->min_edge; + max = &cur->max_edge; + + goto Interpolate; + } + } + + /* apparently, this coordinate is on the right of the last stem */ + delta = coord - cur->max_edge.orus; + return cur->max_edge.pix + SCALE( delta ); + + Interpolate: + return min->pix + FT_MulDiv( coord - min->orus, + max->pix - min->pix, + max->orus - min->orus ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Hint_Points */ + /* */ + /* */ + /* This function grid-fits several points in a given Type 1 builder */ + /* at once. */ + /* */ + /* */ + /* builder :: A handle to target Type 1 builder. */ + /* */ + LOCAL_FUNC + void T1_Hint_Points( T1_Builder* builder ) + { + FT_Int first = builder->hint_point; + FT_Int last = builder->current->n_points - 1; + + T1_Size size = builder->size; + FT_Fixed scale_x = size->root.metrics.x_scale; + FT_Fixed scale_y = size->root.metrics.y_scale; + + T1_Glyph_Hints* hints = builder->glyph->hints; + T1_Stem_Table* hori_stems = &hints->hori_stems; + T1_Stem_Table* vert_stems = &hints->vert_stems; + + FT_Vector* cur = builder->current->points + first; + FT_Vector* limit = cur + last - first + 1; + + + /* first of all, sort the active stem hints */ + t1_sort_hints( hori_stems ); + t1_sort_hints( vert_stems ); + + for ( ; cur < limit; cur++ ) + { + cur->x = t1_hint_point( vert_stems, cur->x, scale_x ); + cur->y = t1_hint_point( hori_stems, cur->y, scale_y ); + } + + builder->hint_point = builder->current->n_points; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Hint_Stems */ + /* */ + /* */ + /* This function is used to compute the location of each stem hint */ + /* between the first and second passes of the glyph loader on the */ + /* charstring. */ + /* */ + /* */ + /* builder :: A handle to the target builder. */ + /* */ + LOCAL_FUNC + void T1_Hint_Stems( T1_Builder* builder ) + { + T1_Glyph_Hints* hints = builder->glyph->hints; + T1_Private* priv = &builder->face->type1.private_dict; + + T1_Size size = builder->size; + FT_Fixed scale_x = size->root.metrics.x_scale; + FT_Fixed scale_y = size->root.metrics.y_scale; + + + t1_hint_horizontal_stems( &hints->hori_stems, + builder->size->hints, + priv->blue_shift, + scale_y ); + + t1_hint_vertical_stems( &hints->vert_stems, + builder->size->hints, + scale_x ); + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1hinter.h b/reactos/subsys/win32k/freetype/t1hinter.h new file mode 100644 index 00000000000..a82882e097f --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1hinter.h @@ -0,0 +1,273 @@ +/***************************************************************************/ +/* */ +/* t1hinter.h */ +/* */ +/* Type 1 hinter (body). */ +/* */ +/* Copyright 1996-2000 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 T1HINTER_H +#define T1HINTER_H + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" +#include "t1gload.h" + +#else + +#include +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Snap_Zone */ + /* */ + /* */ + /* A `snap zone' is used to model either a blue zone or a stem width */ + /* at a given character size. It is made of a minimum and maximum */ + /* edge, defined in 26.6 pixels, as well as an `original' and */ + /* `scaled' position. */ + /* */ + /* The position corresponds to the stem width (for stem snap zones) */ + /* or to the blue position (for blue zones). */ + /* */ + /* */ + /* orus :: The original position in font units. */ + /* */ + /* pix :: The current position in sub-pixel units. */ + /* */ + /* min :: The minimum boundary in sub-pixel units. */ + /* */ + /* max :: The maximum boundary in sub-pixel units. */ + /* */ + typedef struct T1_Snap_Zone_ + { + FT_Pos orus; + FT_Pos pix; + FT_Pos min; + FT_Pos max; + + } T1_Snap_Zone; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Edge */ + /* */ + /* */ + /* A very simple structure used to model a stem edge. */ + /* */ + /* */ + /* orus :: The original edge position in font units. */ + /* */ + /* pix :: The scaled edge position in sub-pixel units. */ + /* */ + typedef struct T1_Edge_ + { + FT_Pos orus; + FT_Pos pix; + + } T1_Edge; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Stem_Hint */ + /* */ + /* */ + /* A simple structure used to model a stem hint. */ + /* */ + /* */ + /* min_edge :: The hint's minimum edge. */ + /* */ + /* max_edge :: The hint's maximum edge. */ + /* */ + /* hint_flags :: Some flags describing the stem properties. */ + /* */ + /* */ + /* The min and max edges of a ghost stem have the same position, even */ + /* if they are coded in a weird way in the charstrings. */ + /* */ + typedef struct T1_Stem_Hint_ + { + T1_Edge min_edge; + T1_Edge max_edge; + FT_Int hint_flags; + + } T1_Stem_Hint; + + +#define T1_HINT_FLAG_ACTIVE 1 /* indicates an active stem */ +#define T1_HINT_FLAG_MIN_BORDER 2 /* unused for now */ +#define T1_HINT_FLAG_MAX_BORDER 4 /* unused for now */ + + /* hinter's configuration constants */ +#define T1_HINTER_MAX_BLUES 24 /* maximum number of blue zones */ +#define T1_HINTER_MAX_SNAPS 16 /* maximum number of stem snap zones */ +#define T1_HINTER_MAX_EDGES 64 /* maximum number of stem hints */ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Size_Hints */ + /* */ + /* */ + /* A structure used to model the hinting information related to a size */ + /* object. */ + /* */ + /* */ + /* supress_overshoots :: A boolean flag to tell whether overshoot */ + /* supression should occur. */ + /* */ + /* num_blue_zones :: The total number of blue zones (top+bottom). */ + /* */ + /* num_bottom_zones :: The number of bottom zones. */ + /* */ + /* blue_zones :: The blue zones table. Bottom zones are */ + /* stored first in the table, followed by all */ + /* top zones. */ + /* */ + /* num_snap_widths :: The number of horizontal stem snap zones. */ + /* */ + /* snap_widths :: An array of horizontal stem snap zones. */ + /* */ + /* num_snap_heights :: The number of vertical stem snap zones. */ + /* */ + /* snap_heights :: An array of vertical stem snap zones. */ + /* */ + struct T1_Size_Hints_ + { + FT_Bool supress_overshoots; + + FT_Int num_blue_zones; + FT_Int num_bottom_zones; + T1_Snap_Zone blue_zones[T1_HINTER_MAX_BLUES]; + + FT_Int num_snap_widths; + T1_Snap_Zone snap_widths[T1_HINTER_MAX_SNAPS]; + + FT_Int num_snap_heights; + T1_Snap_Zone snap_heights[T1_HINTER_MAX_SNAPS]; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Stem_Table */ + /* */ + /* */ + /* A simple structure used to model a set of stem hints in a single */ + /* direction during the loading of a given glyph outline. Not all */ + /* stem hints are active at a time. Moreover, stems must be sorted */ + /* regularly. */ + /* */ + /* */ + /* num_stems :: The total number of stems in the table. */ + /* */ + /* num_active :: The number of active stems in the table. */ + /* */ + /* stems :: A table of all stems. */ + /* */ + /* sort :: A table of indices into the stems table, used to */ + /* keep a sorted list of the active stems. */ + /* */ + typedef struct T1_Stem_Table_ + { + FT_Int num_stems; + FT_Int num_active; + + T1_Stem_Hint stems[T1_HINTER_MAX_EDGES]; + FT_Int sort [T1_HINTER_MAX_EDGES]; + + } T1_Stem_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Glyph_Hints */ + /* */ + /* */ + /* A structure used to model the stem hints of a given glyph outline */ + /* during glyph loading. */ + /* */ + /* */ + /* hori_stems :: The horizontal stem hints table. */ + /* vert_stems :: The vertical stem hints table. */ + /* */ + struct T1_Glyph_Hints_ + { + T1_Stem_Table hori_stems; + T1_Stem_Table vert_stems; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hinter_funcs */ + /* */ + /* */ + /* A table containing the address of various functions used during */ + /* the loading of an hinted scaled outline. */ + /* */ + extern const T1_Hinter_Funcs t1_hinter_funcs; + + + LOCAL_DEF + FT_Error T1_New_Size_Hinter( T1_Size size ); + + LOCAL_DEF + void T1_Done_Size_Hinter( T1_Size size ); + + LOCAL_DEF + FT_Error T1_Reset_Size_Hinter( T1_Size size ); + + LOCAL_DEF + FT_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph ); + + LOCAL_DEF + void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph ); + + + LOCAL_DEF + void T1_Hint_Points( T1_Builder* builder ); + + LOCAL_DEF + void T1_Hint_Stems( T1_Builder* builder ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T1HINTER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1load.c b/reactos/subsys/win32k/freetype/t1load.c new file mode 100644 index 00000000000..00a56a2463d --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1load.c @@ -0,0 +1,1594 @@ +/***************************************************************************/ +/* */ +/* t1load.c */ +/* */ +/* Type 1 font loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1tokens.h" +#include "t1parse.h" + +#else + +#include +#include + +#endif + + +#include + +#include /* for strncpy(), strncmp(), 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_t1load + + + typedef FT_Error (*T1_Parse_Func)( T1_Parser* parser ); + + + /*************************************************************************/ + /* */ + /* */ + /* Init_T1_Parser */ + /* */ + /* */ + /* Initializes a given parser object to build a given T1_Face. */ + /* */ + /* */ + /* parser :: A handle to the newly built parser object. */ + /* */ + /* */ + /* face :: A handle to the target Type 1 face object. */ + /* */ + /* tokenizer :: A handle to the target Type 1 token manager. */ + /* */ + LOCAL_FUNC + void Init_T1_Parser( T1_Parser* parser, + T1_Face face, + T1_Tokenizer tokenizer ) + { + parser->error = 0; + parser->face = face; + parser->tokenizer = tokenizer; + parser->top = parser->stack; + parser->limit = parser->stack + T1_MAX_STACK_DEPTH; + + parser->state_index = 0; + parser->state_stack[0] = dict_none; + + parser->encoding_type = t1_encoding_none; + parser->encoding_names = 0; + parser->encoding_offsets = 0; + parser->encoding_lengths = 0; + + parser->dump_tokens = 0; + face->type1.private_dict.lenIV = 4; /* XXX : is it sure? */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Next_T1_Token */ + /* */ + /* */ + /* Grabs the next significant token from a parser's input stream. */ + /* This function ignores a number of tokens, and translates */ + /* alternate forms into their common ones. */ + /* */ + /* */ + /* parser :: A handle to the source parser. */ + /* */ + /* */ + /* token :: The extracted token descriptor. */ + /* */ + /* */ + /* FreeTyoe error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Next_T1_Token( T1_Parser* parser, + T1_Token* token ) + { + FT_Error error; + T1_Tokenizer tokzer = parser->tokenizer; + + + L1: + error = Read_Token( tokzer ); + if ( error ) + return error; + + /* we now must ignore a number of tokens like `dup', `executeonly', */ + /* `readonly', etc. */ + *token = tokzer->token; + if ( token->kind == tok_keyword ) + switch( token->kind2 ) + { + case key_dup: + case key_execonly: + case key_readonly: + case key_noaccess: + case key_userdict: + /* do nothing - loop */ + goto L1; + + /* we also translate some other keywords from their alternative */ + /* to their `normal' form */ + + case key_NP_alternate: + token->kind2 = key_NP; + break; + + case key_RD_alternate: + token->kind2 = key_RD; + break; + + case key_ND_alternate: + token->kind2 = key_ND; + break; + + default: + ; + } + +#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE ) + + /* Dump the token when requested. This feature is only available */ + /* in the `error' and `trace' debug levels. */ + if ( parser->dump_tokens ) + { + FT_String temp_string[128]; + FT_Int len; + + + len = token->len; + if ( len > 127 ) + len = 127; + strncpy( temp_string, + (FT_String*)tokzer->base + token->start, + len ); + temp_string[len] = '\0'; + FT_ERROR(( "%s\n", temp_string )); + } + +#endif /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE */ + + return T1_Err_Ok; + } + + + static + FT_Error Expect_Keyword( T1_Parser* parser, + T1_TokenType keyword ) + { + T1_Token token; + FT_Error error; + + + error = Next_T1_Token( parser, &token ); + if ( error ) + goto Exit; + + if ( token.kind != tok_keyword || + token.kind2 != keyword ) + { + error = T1_Err_Syntax_Error; + FT_ERROR(( "Expect_Keyword: keyword `%s' expected.\n", + t1_keywords[keyword - key_first_] )); + } + + Exit: + return error; + } + + + static + FT_Error Expect_Keyword2( T1_Parser* parser, + T1_TokenType keyword1, + T1_TokenType keyword2 ) + { + T1_Token token; + FT_Error error; + + + error = Next_T1_Token( parser, &token ); + if ( error ) + goto Exit; + + if ( token.kind != tok_keyword || + ( token.kind2 != keyword1 && + token.kind2 != keyword2 ) ) + { + error = T1_Err_Syntax_Error; + FT_ERROR(( "Expect_Keyword2: keyword `%s' or `%s' expected.\n", + t1_keywords[keyword1 - key_first_], + t1_keywords[keyword2 - key_first_] )); + } + + Exit: + return error; + } + + + static + void Parse_Encoding( T1_Parser* parser ) + { + T1_Token* token = parser->top+1; + FT_Memory memory = parser->face->root.memory; + T1_Encoding* encode = &parser->face->type1.encoding; + FT_Error error = 0; + + + if ( token->kind == tok_keyword && + ( token->kind2 == key_StandardEncoding || + token->kind2 == key_ExpertEncoding ) ) + { + encode->num_chars = 256; + encode->code_first = 32; + encode->code_last = 255; + + if ( ALLOC_ARRAY( encode->char_index, 256, FT_Short ) ) + goto Exit; + + encode->char_name = 0; /* no need to store glyph names */ + + /* Now copy the encoding */ + switch ( token->kind2 ) + { + case key_ExpertEncoding: + parser->encoding_type = t1_encoding_expert; + break; + + default: + parser->encoding_type = t1_encoding_standard; + break; + } + } + else + { + FT_ERROR(( "Parse_Encoding: invalid encoding type\n" )); + error = T1_Err_Syntax_Error; + } + + Exit: + parser->error = error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* IMPLEMENTATION OF THE `DEF' KEYWORD DEPENDING ON */ + /* CURRENT DICTIONARY STATE */ + /* */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_Font */ + /* */ + /* */ + /* This function performs a `def' if in the Font dictionary. Its */ + /* purpose is to build the T1_Face attributes directly from the */ + /* stream. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_Font( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_Face face = parser->face; + T1_Font* type1 = &face->type1; + + + switch ( top[0].kind2 ) + { + case imm_FontName: + /* in some cases, the /FontName is an immediate like */ + /* /TimesNewRoman. In this case, we simply copy the */ + /* token string (without the /). */ + if ( top[1].kind == tok_immediate ) + { + FT_Memory memory = parser->tokenizer->memory; + FT_Error error; + FT_Int len = top[1].len; + + + if ( ALLOC( type1->font_name, len + 1 ) ) + { + parser->error = error; + return error; + } + + MEM_Copy( type1->font_name, + parser->tokenizer->base + top[1].start, + len ); + type1->font_name[len] = '\0'; + } + else + type1->font_name = CopyString( parser ); + break; + + case imm_Encoding: + Parse_Encoding( parser ); + break; + + case imm_PaintType: + type1->paint_type = (FT_Byte)CopyInteger( parser ); + break; + + case imm_FontType: + type1->font_type = (FT_Byte)CopyInteger( parser ); + break; + + case imm_FontMatrix: + CopyMatrix( parser, &type1->font_matrix ); + break; + + case imm_FontBBox: + CopyBBox( parser, &type1->font_bbox ); + break; + + case imm_UniqueID: + type1->private_dict.unique_id = CopyInteger( parser ); + break; + + case imm_StrokeWidth: + type1->stroke_width = CopyInteger( parser ); + break; + + case imm_FontID: + type1->font_id = CopyInteger( parser ); + break; + + default: + /* ignore all other things */ + parser->error = T1_Err_Ok; + } + + return parser->error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_FontInfo */ + /* */ + /* */ + /* This function performs a `def' if in the FontInfo dictionary. Its */ + /* purpose is to build the T1_FontInfo structure directly from the */ + /* stream. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeTyoe error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_FontInfo( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_FontInfo* info = &parser->face->type1.font_info; + + + switch ( top[0].kind2 ) + { + case imm_version: + info->version = CopyString( parser ); + break; + + case imm_Notice: + info->notice = CopyString( parser ); + break; + + case imm_FullName: + info->full_name = CopyString( parser ); + break; + + case imm_FamilyName: + info->family_name = CopyString( parser ); + break; + + case imm_Weight: + info->weight = CopyString( parser ); + break; + + case imm_ItalicAngle: + info->italic_angle = CopyInteger( parser ); + break; + + case imm_isFixedPitch: + info->is_fixed_pitch = CopyBoolean( parser ); + break; + + case imm_UnderlinePosition: + info->underline_position = (FT_Short)CopyInteger( parser ); + break; + + case imm_UnderlineThickness: + info->underline_thickness = (FT_Short)CopyInteger( parser ); + break; + + default: + /* ignore all other things */ + parser->error = T1_Err_Ok; + } + + return parser->error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_Private */ + /* */ + /* */ + /* This function performs a `def' if in the Private dictionary. Its */ + /* purpose is to build the T1_Private structure directly from the */ + /* stream. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeTyoe error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_Private( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_Private* priv = &parser->face->type1.private_dict; + + + switch ( top[0].kind2 ) + { + /* Ignore the definitions of RD, NP, ND, and their alternate forms */ + case imm_RD: + case imm_RD_alternate: + case imm_ND: + case imm_ND_alternate: + case imm_NP: + case imm_NP_alternate: + parser->error = T1_Err_Ok; + break; + + case imm_BlueValues: + CopyArray( parser, &priv->num_blue_values, + priv->blue_values, 14 ); + break; + + case imm_OtherBlues: + CopyArray( parser, &priv->num_other_blues, + priv->other_blues, 10 ); + break; + + case imm_FamilyBlues: + CopyArray( parser, &priv->num_family_blues, + priv->family_blues, 14 ); + break; + + case imm_FamilyOtherBlues: + CopyArray( parser, &priv->num_family_other_blues, + priv->family_other_blues, 10 ); + break; + + case imm_BlueScale: + priv->blue_scale = CopyFloat( parser, 0x10000L ); + break; + + case imm_BlueShift: + priv->blue_shift = CopyInteger( parser ); + break; + + case imm_BlueFuzz: + priv->blue_fuzz = CopyInteger( parser ); + break; + + case imm_StdHW: + CopyArray( parser, 0, (FT_Short*)&priv->standard_width, 1 ); + break; + + case imm_StdVW: + CopyArray( parser, 0, (FT_Short*)&priv->standard_height, 1 ); + break; + + case imm_StemSnapH: + CopyArray( parser, &priv->num_snap_widths, + priv->snap_widths, 12 ); + break; + + case imm_StemSnapV: + CopyArray( parser, &priv->num_snap_heights, + priv->snap_heights, 12 ); + break; + + case imm_ForceBold: + priv->force_bold = CopyBoolean( parser ); + break; + + case imm_LanguageGroup: + priv->language_group = CopyInteger( parser ); + break; + + case imm_password: + priv->password = CopyInteger( parser ); + break; + + case imm_UniqueID: + priv->unique_id = CopyInteger( parser ); + break; + + case imm_lenIV: + priv->lenIV = CopyInteger( parser ); + break; + + case imm_MinFeature: + CopyArray( parser, 0, priv->min_feature, 2 ); + break; + + default: + /* ignore all other things */ + parser->error = T1_Err_Ok; + } + + return parser->error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_Error */ + /* */ + /* */ + /* This function returns a simple syntax error when invoked. It is */ + /* used for the `def' keyword if in the `encoding', `subrs', */ + /* `othersubrs', and `charstrings' dictionary states. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_Error( T1_Parser* parser ) + { + FT_ERROR(( "Do_Def_Error:" )); + FT_ERROR(( " `def' keyword encountered in bad dictionary/array\n" )); + + parser->error = T1_Err_Syntax_Error; + + return parser->error; + } + + + static + FT_Error Do_Def_Ignore( T1_Parser* parser ) + { + FT_UNUSED( parser ); + return T1_Err_Ok; + } + + + static + T1_Parse_Func def_funcs[dict_max] = + { + Do_Def_Error, + Do_Def_Font, + Do_Def_FontInfo, + Do_Def_Ignore, + Do_Def_Private, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + }; + + + /*************************************************************************/ + /* */ + /* */ + /* IMPLEMENTATION OF THE `PUT' KEYWORD DEPENDING ON */ + /* CURRENT DICTIONARY STATE */ + /* */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Put_Encoding */ + /* */ + /* */ + /* This function performs a `put' if in the Encoding array. The */ + /* glyph name is copied into the T1 recorder, and the charcode and */ + /* glyph name pointer are written into the face object encoding. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_Put_Encoding( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Encoding* encode = &face->type1.encoding; + FT_Int index; + + + /* record and check the character code */ + if ( top[0].kind != tok_number ) + { + FT_TRACE4(( "Do_Put_Encoding: number expected\n" )); + goto Syntax_Error; + } + index = (FT_Int)CopyInteger( parser ); + if ( parser->error ) + return parser->error; + + if ( index < 0 || index >= encode->num_chars ) + { + FT_TRACE4(( "Do_Put_Encoding: invalid character code\n" )); + goto Syntax_Error; + } + + /* record the immediate name */ + if ( top[1].kind != tok_immediate ) + { + FT_TRACE4(( "Do_Put_Encoding: immediate name expected\n" )); + goto Syntax_Error; + } + + /* if the glyph name is `.notdef', store a NULL char name; */ + /* otherwise, record the glyph name */ + if ( top[1].kind == imm_notdef ) + { + parser->table.elements[index] = 0; + parser->table.lengths [index] = 0; + } + else + { + FT_String temp_name[128]; + T1_Token* token = top + 1; + FT_Int len = token->len - 1; + + + /* copy immediate name */ + if ( len > 127 ) + len = 127; + MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len ); + temp_name[len] = '\0'; + + error = T1_Add_Table( &parser->table, index, + (FT_Byte*)temp_name, len + 1 ); + + /* adjust code_first and code_last */ + if ( index < encode->code_first ) encode->code_first = index; + if ( index > encode->code_last ) encode->code_last = index; + } + return error; + + Syntax_Error: + /* ignore the error, and simply clear the stack */ + FT_TRACE4(( "Do_Put_Encoding: invalid syntax encountered\n" )); + parser->top = parser->stack; + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* IMPLEMENTATION OF THE "RD" KEYWORD DEPENDING ON */ + /* CURRENT DICTIONARY STATE */ + /* */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Do_RD_Subrs */ + /* */ + /* */ + /* This function performs an `RD' if in the Subrs dictionary. It */ + /* simply records the array of bytecodes/charstrings corresponding to */ + /* the sub-routine. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_RD_Subrs( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Tokenizer tokzer = parser->tokenizer; + FT_Int index, count; + + + /* record and check the character code */ + if ( top[0].kind != tok_number || + top[1].kind != tok_number ) + { + FT_ERROR(( "Do_RD_Subrs: number expected\n" )); + goto Syntax_Error; + } + index = (FT_Int)CopyInteger( parser ); + error = parser->error; + if ( error ) + goto Exit; + + count = (FT_Int)CopyInteger( parser ); + error = parser->error; + if ( error ) + goto Exit; + + if ( index < 0 || index >= face->type1.num_subrs ) + { + FT_ERROR(( "Do_RD_Subrs: invalid character code\n" )); + goto Syntax_Error; + } + + /* decrypt charstring and skip it */ + { + FT_Byte* base = tokzer->base + tokzer->cursor; + + + tokzer->cursor += count; + + /* 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 ) + { + t1_decrypt( base, count, 4330 ); + + base += face->type1.private_dict.lenIV; + count -= face->type1.private_dict.lenIV; + } + + error = T1_Add_Table( &parser->table, index, base, count ); + } + + /* consume the closing NP or `put' */ + error = Expect_Keyword2( parser, key_NP, key_put ); + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_RD_CharStrings */ + /* */ + /* */ + /* This function performs an `RD' if in the CharStrings dictionary. */ + /* It simply records the array of bytecodes/charstrings corresponding */ + /* to the glyph program string. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_RD_Charstrings( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Tokenizer tokzer = parser->tokenizer; + FT_Int index, count; + + + /* check the character name argument */ + if ( top[0].kind != tok_immediate ) + { + FT_ERROR(( "Do_RD_Charstrings: immediate character name expected\n" )); + goto Syntax_Error; + } + + /* check the count argument */ + if ( top[1].kind != tok_number ) + { + FT_ERROR(( "Do_RD_Charstrings: number expected\n" )); + goto Syntax_Error; + } + + parser->args++; + count = (FT_Int)CopyInteger( parser ); + error = parser->error; + if ( error ) + goto Exit; + + /* record the glyph name and get the corresponding glyph index */ + if ( top[0].kind2 == imm_notdef ) + index = 0; + else + { + FT_String temp_name[128]; + T1_Token* token = top; + FT_Int len = token->len - 1; + + + /* copy immediate name */ + if ( len > 127 ) + len = 127; + MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len ); + temp_name[len] = '\0'; + + index = parser->cur_name++; + error = T1_Add_Table( &parser->table, index * 2, + (FT_Byte*)temp_name, len + 1 ); + if ( error ) + goto Exit; + } + + /* decrypt and record charstring, then skip them */ + { + FT_Byte* base = tokzer->base + tokzer->cursor; + + + tokzer->cursor += count; /* skip */ + + if ( face->type1.private_dict.lenIV >= 0 ) + { + t1_decrypt( base, count, 4330 ); + + base += face->type1.private_dict.lenIV; + count -= face->type1.private_dict.lenIV; + } + + error = T1_Add_Table( &parser->table, index * 2 + 1, base, count ); + } + + /* consume the closing `ND' */ + if ( !error ) + error = Expect_Keyword( parser, key_ND ); + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + static + FT_Error Expect_Dict_Arguments( T1_Parser* parser, + FT_Int num_args, + T1_TokenType immediate, + T1_DictState new_state, + FT_Int* count ) + { + /* check that we have enough arguments in the stack, including */ + /* the `dict' keyword */ + if ( parser->top - parser->stack < num_args ) + { + FT_ERROR(( "Expect_Dict_Arguments: expecting at least %d arguments", + num_args )); + goto Syntax_Error; + } + + /* check that we have the correct immediate, if needed */ + if ( num_args == 2 ) + { + if ( parser->top[-2].kind != tok_immediate || + parser->top[-2].kind2 != immediate ) + { + FT_ERROR(( "Expect_Dict_Arguments: expecting `/%s' dictionary\n", + t1_immediates[immediate - imm_first_] )); + goto Syntax_Error; + } + } + + parser->args = parser->top-1; + + /* check that the count argument is a number */ + if ( parser->args->kind != tok_number ) + { + FT_ERROR(( "Expect_Dict_Arguments:" )); + FT_ERROR(( " expecting numerical count argument for `dict'\n" )); + goto Syntax_Error; + } + + if ( count ) + { + *count = CopyInteger( parser ); + if ( parser->error ) + return parser->error; + } + + /* save the dictionary state */ + parser->state_stack[++parser->state_index] = new_state; + + /* consume the `begin' keyword and clear the stack */ + parser->top -= num_args; + return Expect_Keyword( parser, key_begin ); + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + static + FT_Error Expect_Array_Arguments( T1_Parser* parser ) + { + T1_Token* top = parser->top; + FT_Error error = T1_Err_Ok; + T1_DictState new_state; + FT_Int count; + T1_Face face = parser->face; + FT_Memory memory = face->root.memory; + + + /* Check arguments format */ + if ( top - parser->stack < 2 ) + { + FT_ERROR(( "Expect_Array_Arguments: two arguments expected\n" )); + error = T1_Err_Stack_Underflow; + goto Exit; + } + + parser->top -= 2; + top -= 2; + parser->args = top + 1; + + if ( top[0].kind != tok_immediate ) + { + FT_ERROR(( "Expect_Array_Arguments:" )); + FT_ERROR(( " first argument must be an immediate name\n" )); + goto Syntax_Error; + } + + if ( top[1].kind != tok_number ) + { + FT_ERROR(( "Expect_Array_Arguments:" )); + FT_ERROR(( " second argument must be a number\n" )); + goto Syntax_Error; + } + + count = (FT_Int)CopyInteger( parser ); + + /* Is this an array we know about? */ + switch ( top[0].kind2 ) + { + case imm_Encoding: + { + T1_Encoding* encode = &face->type1.encoding; + + + new_state = dict_encoding; + + encode->code_first = count; + encode->code_last = 0; + encode->num_chars = count; + + /* Allocate the table of character indices. The table of */ + /* character names is allocated through init_t1_recorder(). */ + if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) ) + return error; + + error = T1_New_Table( &parser->table, count, memory ); + if ( error ) + goto Exit; + + parser->encoding_type = t1_encoding_array; + } + break; + + case imm_Subrs: + new_state = dict_subrs; + face->type1.num_subrs = count; + + error = T1_New_Table( &parser->table, count, memory ); + if ( error ) + goto Exit; + break; + + case imm_CharStrings: + new_state = dict_charstrings; + break; + + default: + new_state = dict_unknown_array; + } + + parser->state_stack[++parser->state_index] = new_state; + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + static + FT_Error Finalize_Parsing( T1_Parser* parser ) + { + T1_Face face = parser->face; + T1_Font* type1 = &face->type1; + FT_Memory memory = face->root.memory; + T1_Table* strings = &parser->table; + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; + + FT_Int num_glyphs; + FT_Int n; + FT_Error error; + + + num_glyphs = type1->num_glyphs = parser->cur_name; + + /* allocate glyph names and charstrings arrays */ + if ( ALLOC_ARRAY( type1->glyph_names, num_glyphs, FT_String* ) || + ALLOC_ARRAY( type1->charstrings, num_glyphs, FT_Byte* ) || + ALLOC_ARRAY( type1->charstrings_len, num_glyphs, FT_Int* ) ) + return error; + + /* copy glyph names and charstrings offsets and lengths */ + type1->charstrings_block = strings->block; + for ( n = 0; n < num_glyphs; n++ ) + { + type1->glyph_names[n] = (FT_String*)strings->elements[2 * n]; + type1->charstrings[n] = strings->elements[2 * n + 1]; + type1->charstrings_len[n] = strings->lengths [2 * n + 1]; + } + + /* now free the old tables */ + FREE( strings->elements ); + FREE( strings->lengths ); + + if ( !psnames ) + { + FT_ERROR(( "Finalize_Parsing: `PSNames' module missing!\n" )); + return T1_Err_Unimplemented_Feature; + } + + /* compute encoding if required */ + if ( parser->encoding_type == t1_encoding_none ) + { + FT_ERROR(( "Finalize_Parsing: no encoding specified in font file\n" )); + return T1_Err_Syntax_Error; + } + + { + FT_Int n; + T1_Encoding* encode = &type1->encoding; + + + encode->code_first = encode->num_chars - 1; + encode->code_last = 0; + + for ( n = 0; n < encode->num_chars; n++ ) + { + FT_String** names; + FT_Int index; + FT_Int m; + + + switch ( parser->encoding_type ) + { + case t1_encoding_standard: + index = psnames->adobe_std_encoding[n]; + names = 0; + break; + + case t1_encoding_expert: + index = psnames->adobe_expert_encoding[n]; + names = 0; + break; + + default: + index = n; + names = (FT_String**)parser->encoding_offsets; + } + + encode->char_index[n] = 0; + + if ( index ) + { + FT_String* name; + + + if ( names ) + name = names[index]; + else + name = (FT_String*)psnames->adobe_std_strings(index); + + if ( name ) + { + FT_Int len = strlen( name ); + + + /* lookup glyph index from name */ + for ( m = 0; m < num_glyphs; m++ ) + { + if ( strncmp( type1->glyph_names[m], name, len ) == 0 ) + { + encode->char_index[n] = m; + break; + } + } + + if ( n < encode->code_first ) encode->code_first = n; + if ( n > encode->code_last ) encode->code_last = n; + } + } + } + + parser->encoding_type = t1_encoding_none; + + FREE( parser->encoding_names ); + FREE( parser->encoding_lengths ); + FREE( parser->encoding_offsets ); + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Parse_T1_FontProgram */ + /* */ + /* */ + /* Parses a given Type 1 font file and builds its face object. */ + /* */ + /* */ + /* parser :: A handle to the target parser object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The parser contains a handle to the target face object. */ + /* */ + LOCAL_FUNC + FT_Error Parse_T1_FontProgram( T1_Parser* parser ) + { + FT_Error error; + T1_Font* type1 = &parser->face->type1; + + + for (;;) + { + T1_Token token; + T1_Token* top; + T1_DictState dict_state; + FT_Int dict_index; + + + error = Next_T1_Token( parser, &token ); + top = parser->top; + dict_index = parser->state_index; + dict_state = parser->state_stack[dict_index]; + + switch ( token.kind ) + { + /* a keyword has been detected */ + case tok_keyword: + switch ( token.kind2 ) + { + case key_dict: + switch ( dict_state ) + { + case dict_none: + /* All right, we are beginning the font dictionary. */ + /* Check that we only have one number argument, then */ + /* consume the `begin' and change to `dict_font' */ + /* state. */ + error = Expect_Dict_Arguments( parser, 1, tok_error, + dict_font, 0 ); + if ( error ) + goto Exit; + + /* clear stack from all the previous content. This */ + /* could be some stupid Postscript code. */ + parser->top = parser->stack; + break; + + case dict_font: + /* This must be the /FontInfo dictionary, so check */ + /* that we have at least two arguments, that they */ + /* are `/FontInfo' and a number, then change the */ + /* dictionary state. */ + error = Expect_Dict_Arguments( parser, 2, imm_FontInfo, + dict_fontinfo, 0 ); + if ( error ) + goto Exit; + break; + + case dict_none2: + error = Expect_Dict_Arguments( parser, 2, imm_Private, + dict_private, 0 ); + if ( error ) + goto Exit; + break; + + case dict_private: + { + T1_Face face = parser->face; + FT_Int count; + + + error = Expect_Dict_Arguments( parser, 2, imm_CharStrings, + dict_charstrings, &count ); + if ( error ) + goto Exit; + + type1->num_glyphs = count; + error = T1_New_Table( &parser->table, count * 2, + face->root.memory ); + if ( error ) + goto Exit; + + /* record `.notdef' as the first glyph in the font */ + error = T1_Add_Table( &parser->table, 0, + (FT_Byte*)".notdef", 8 ); + parser->cur_name = 1; + /* XXX: DO SOMETHING HERE */ + } + break; + + default: + /* All other uses are invalid */ + FT_ERROR(( "Parse_T1_FontProgram:" )); + FT_ERROR(( " invalid use of `dict' keyword\n" )); + goto Syntax_Error; + } + break; + + case key_array: + /* Are we in an array yet? If so, raise an error */ + switch ( dict_state ) + { + case dict_encoding: + case dict_subrs: + case dict_othersubrs: + case dict_charstrings: + case dict_unknown_array: + FT_ERROR(( "Parse_T1_FontProgram: nested array definitions\n" )); + goto Syntax_Error; + + default: + ; + } + error = Expect_Array_Arguments( parser ); + if ( error ) + goto Exit; + break; + + case key_ND: + case key_NP: + case key_def: + /* Are we in an array? If so, finalize it. */ + switch ( dict_state ) + { + case dict_encoding: /* finish encoding array */ + /* copy table names to the face object */ + T1_Done_Table( &parser->table ); + + parser->encoding_names = parser->table.block; + parser->encoding_lengths = parser->table.lengths; + parser->encoding_offsets = parser->table.elements; + + parser->state_index--; + break; + + case dict_subrs: + /* copy recorder sub-routines */ + T1_Done_Table( &parser->table ); + + parser->subrs = parser->table.block; + type1->subrs = parser->table.elements; + type1->subrs_len = parser->table.lengths; + type1->subrs_block = parser->table.block; + + parser->state_index--; + break; + + case dict_charstrings: + case dict_othersubrs: + case dict_unknown_array: + FT_ERROR(( "Parse_T1_FontProgram: unsupported array\n" )); + goto Syntax_Error; + break; + + default: /* normal `def' processing */ + /* Check that we have sufficient operands in the stack */ + if ( top >= parser->stack + 2 ) + { + /* Now check that the first operand is an immediate. */ + /* If so, call the appropriate `def' routine based */ + /* on the current parser state. */ + if ( top[-2].kind == tok_immediate ) + { + parser->top -= 2; + parser->args = parser->top + 1; + error = def_funcs[dict_state](parser); + } + else + { + /* This is an error, but some fonts contain */ + /* stupid Postscript code. We simply ignore */ + /* an invalid `def' by clearing the stack. */ +#if 0 + FT_ERROR(( "Parse_T1_FontProgram: immediate expected\n" )); + goto Syntax_Error; +#else + parser->top = parser->stack; +#endif + } + } + else + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + } + break; + + case key_index: + if ( top <= parser->stack ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + /* simply ignore? */ + parser->top --; + break; + + case key_put: + /* Check that we have sufficient operands in stack */ + if ( top < parser->stack + 2 ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + parser->top -= 2; + parser->args = parser->top; + + switch ( dict_state ) + { + case dict_encoding: + error = Do_Put_Encoding( parser ); + if ( error ) + goto Exit; + break; + + case dict_unknown_array: /* ignore the `put' */ + break; + + default: +#if 0 + FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" )); + goto Syntax_Error; +#else + /* invalid context; simply ignore the `put' and */ + /* clear the stack (stupid Postscript code) */ + FT_TRACE4(( "Parse_T1_FontProgram: invalid context ignored.\n" )); + parser->top = parser->stack; +#endif + } + break; + + case key_RD: + /* Check that we have sufficient operands in stack */ + if ( top < parser->stack + 2 ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + parser->top -= 2; + parser->args = parser->top; + switch ( dict_state ) + { + case dict_subrs: + error = Do_RD_Subrs( parser ); + if ( error ) + goto Exit; + break; + + case dict_charstrings: + error = Do_RD_Charstrings( parser ); + if ( error ) + goto Exit; + break; + + default: + FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" )); + goto Syntax_Error; + } + break; + + case key_end: + /* Were we in a dictionary or in an array? */ + if ( dict_index <= 0 ) + { + FT_ERROR(( "Parse_T1_FontProgram: no dictionary defined\n" )); + goto Syntax_Error; + } + + switch ( dict_state ) + { + /* jump to the private dictionary if we are closing the */ + /* `/Font' dictionary */ + case dict_font: + goto Open_Private; + + /* exit the parser when closing the CharStrings dictionary */ + case dict_charstrings: + return Finalize_Parsing( parser ); + + default: + /* Pop the current dictionary state and return to previous */ + /* one. Consume the `def'. */ + + /* Because some buggy fonts (BitStream) have incorrect */ + /* syntax, we never escape from the private dictionary */ + if ( dict_state != dict_private ) + parser->state_index--; + + /* many fonts use `NP' instead of `def' or `put', so */ + /* we simply ignore the next token */ +#if 0 + error = Expect_Keyword2( parser, key_def, key_put ); + if ( error ) + goto Exit; +#else + (void)Expect_Keyword2( parser, key_def, key_put ); +#endif + } + break; + + case key_for: + /* check that we have four arguments and simply */ + /* ignore them */ + if ( top - parser->stack < 4 ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + parser->top -= 4; + break; + + case key_currentdict: + Open_Private: + parser->state_index = 0; + parser->state_stack[0] = dict_none2; + error = Open_PrivateDict( parser->tokenizer ); + if ( error ) + goto Exit; + break; + + case key_true: + case key_false: + case key_StandardEncoding: + case key_ExpertEncoding: + goto Push_Element; + + default: + FT_ERROR(( "Parse_T1_FontProgram:" )); + FT_ERROR(( " invalid keyword in context\n" )); + error = T1_Err_Syntax_Error; + } + break; + + /* check for the presence of `/BlendAxisTypes' -- we cannot deal */ + /* with multiple master fonts, so we must return a correct error */ + /* code to allow another driver to load them */ + case tok_immediate: + if ( token.kind2 == imm_BlendAxisTypes ) + { + error = FT_Err_Unknown_File_Format; + goto Exit; + } + /* fallthrough */ + + /* A number was detected */ + case tok_string: + case tok_program: + case tok_array: + case tok_hexarray: + case tok_any: + case tok_number: /* push number on stack */ + + Push_Element: + if ( top >= parser->limit ) + { + error = T1_Err_Stack_Overflow; + goto Exit; + } + else + *parser->top++ = token; + break; + + /* anything else is an error per se the spec, but we */ + /* frequently encounter stupid postscript code in fonts, */ + /* so just ignore them */ + default: + error = T1_Err_Ok; /* ignore token */ + } + + if ( error ) + return error; + } + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1load.h b/reactos/subsys/win32k/freetype/t1load.h new file mode 100644 index 00000000000..d278374f0f8 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1load.h @@ -0,0 +1,57 @@ +/***************************************************************************/ +/* */ +/* t1load.h */ +/* */ +/* Type 1 font loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "t1parse.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + LOCAL_DEF + void Init_T1_Parser( T1_Parser* parser, + T1_Face face, + T1_Tokenizer tokenizer ); + + + LOCAL_DEF + FT_Error Parse_T1_FontProgram( T1_Parser* parser ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1LOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1objs.c b/reactos/subsys/win32k/freetype/t1objs.c new file mode 100644 index 00000000000..1e6f9ca2a31 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1objs.c @@ -0,0 +1,544 @@ +/***************************************************************************/ +/* */ +/* t1objs.c */ +/* */ +/* Type 1 objects manager (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1gload.h" +#include "t1load.h" +#include "t1afm.h" + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include "t1hinter.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* SIZE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Size */ + /* */ + /* */ + /* The Type 1 size object destructor. Used to discard a given size */ + /* object. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_FUNC + void T1_Done_Size( T1_Size size ) + { + if ( size ) + { + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + T1_Done_Size_Hinter( size ); +#endif + + size->valid = 0; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Size */ + /* */ + /* */ + /* The size object initializer. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeTrue error code. 0 means success. */ + /* */ + LOCAL_DEF + FT_Error T1_Init_Size( T1_Size size ) + { + FT_Error error; + + + size->valid = 0; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + error = T1_New_Size_Hinter( size ); + + return error; +#else + + FT_UNUSED( error ); + + return T1_Err_Ok; + +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Reset_Size */ + /* */ + /* */ + /* Resets an instance to a new pointsize/transform. This function is */ + /* in charge of resetting the blue zones,a s well as the stem snap */ + /* tables for a given size. */ + /* */ + /* */ + /* size :: The target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Reset_Size( T1_Size size ) + { + /* recompute ascender, descender, etc. */ + T1_Face face = (T1_Face)size->root.face; + FT_Size_Metrics* metrics = &size->root.metrics; + + + if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) + return FT_Err_Invalid_Argument; + + /* 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; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + return T1_Reset_Size_Hinter( size ); +#else + return 0; +#endif + } + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Face */ + /* */ + /* */ + /* The face object destructor. */ + /* */ + /* */ + /* face :: A typeless pointer to the face object to destroy. */ + /* */ + LOCAL_FUNC + void T1_Done_Face( T1_Face face ) + { + FT_Memory memory; + T1_Font* type1 = &face->type1; + + + if ( face ) + { + memory = face->root.memory; + + /* 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->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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Face */ + /* */ + /* */ + /* The face object constructor. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: The face record to build. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Init_Face( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + T1_Tokenizer tokenizer; + FT_Error error; + PSNames_Interface* psnames; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + FT_UNUSED( face ); + + + 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; + } + + /* open the tokenizer, this will also check the font format */ + error = New_Tokenizer( stream, &tokenizer ); + if ( error ) + goto Fail; + + /* if we just wanted to check the format, leave successfully now */ + if ( face_index < 0 ) + goto Leave; + + /* check the face index */ + if ( face_index != 0 ) + { + FT_ERROR(( "T1_Init_Face: invalid face index\n" )); + error = T1_Err_Invalid_Argument; + goto Leave; + } + + /* Now, load the font program into the face object */ + { + T1_Parser parser; + + + Init_T1_Parser( &parser, face, tokenizer ); + error = Parse_T1_FontProgram( &parser ); + if ( error ) + goto Leave; + + /* Init the face object fields */ + /* Now set up root face fields */ + { + FT_Face root = (FT_Face)&face->root; + T1_Font* type1 = &face->type1; + + + root->num_glyphs = 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 ( type1->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 = type1->font_info.family_name; + if ( root->family_name ) + { + char* full = 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 (type1->font_name) + { + root->family_name = type1->font_name; + root->style_name = "Regular"; + } + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox = type1->font_bbox; + root->units_per_EM = 1000; + root->ascender = (FT_Short)type1->font_bbox.yMax; + root->descender = -(FT_Short)type1->font_bbox.yMin; + root->height = ( ( root->ascender + root->descender) * 12 ) + / 10; + + /* now compute the maximum advance width */ + + root->max_advance_width = type1->private_dict.standard_width[0]; + + /* compute max advance width for proportional fonts */ + if ( !type1->font_info.is_fixed_pitch ) + { + 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 = max_advance; + else + error = 0; /* clear error */ + } + + root->max_advance_height = root->height; + + root->underline_position = type1->font_info.underline_position; + root->underline_thickness = type1->font_info.underline_thickness; + + root->max_points = 0; + root->max_contours = 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]; + } + + Leave: + Done_Tokenizer( tokenizer ); + + Fail: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_GlyphSlot */ + /* */ + /* */ + /* The glyph slot object destructor. */ + /* */ + /* */ + /* glyph :: The glyph slot handle to destroy. */ + /* */ + LOCAL_FUNC + void T1_Done_GlyphSlot( T1_GlyphSlot glyph ) + { +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + T1_Done_Glyph_Hinter( glyph ); + +#else + + FT_UNUSED( glyph ); + +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_GlyphSlot */ + /* */ + /* */ + /* The glyph slot object constructor. */ + /* */ + /* */ + /* glyph :: The glyph slot handle to initialize. */ + /* */ + LOCAL_FUNC + FT_Error T1_Init_GlyphSlot( T1_GlyphSlot glyph ) + { + FT_Error error = FT_Err_Ok; + + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + error = T1_New_Glyph_Hinter( glyph ); + +#else + + FT_UNUSED( glyph ); + +#endif + + return error; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1objs.h b/reactos/subsys/win32k/freetype/t1objs.h new file mode 100644 index 00000000000..47b0a37be1c --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1objs.h @@ -0,0 +1,172 @@ +/***************************************************************************/ +/* */ +/* t1objs.h */ +/* */ +/* Type 1 objects manager (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Driver */ + /* */ + /* */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct T1_DriverRec_* T1_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Size */ + /* */ + /* */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct T1_SizeRec_* T1_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_GlyphSlot */ + /* */ + /* */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct T1_GlyphSlotRec_* T1_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_CharMap */ + /* */ + /* */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* */ + /* 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 */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_SizeRec */ + /* */ + /* */ + /* 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; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_GlyphSlotRec */ + /* */ + /* */ + /* 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; + + + LOCAL_DEF + FT_Error T1_Init_Face( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void T1_Done_Face( T1_Face face ); + + LOCAL_DEF + FT_Error T1_Init_Size( T1_Size size ); + + LOCAL_DEF + void T1_Done_Size( T1_Size size ); + + LOCAL_DEF + FT_Error T1_Reset_Size( T1_Size size ); + + LOCAL_DEF + FT_Error T1_Init_GlyphSlot( T1_GlyphSlot slot ); + + LOCAL_DEF + void T1_Done_GlyphSlot( T1_GlyphSlot slot ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1OBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1parse.c b/reactos/subsys/win32k/freetype/t1parse.c new file mode 100644 index 00000000000..8b7ca252457 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1parse.c @@ -0,0 +1,761 @@ +/***************************************************************************/ +/* */ +/* t1parse.c */ +/* */ +/* Type 1 parser (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1parse.h" + +#else + +#include + +#endif + + +#include /* for sscanf() */ +#include /* for strncpy() */ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_New_Table */ + /* */ + /* */ + /* Initializes a T1_Table structure. */ + /* */ + /* */ + /* table :: The address of the target table. */ + /* */ + /* */ + /* count :: The table size (i.e. maximum number of elements). */ + /* memory :: The memory object to use for all subsequent */ + /* reallocations. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_New_Table( T1_Table* table, + FT_Int count, + FT_Memory memory ) + { + FT_Error error; + + + table->memory = memory; + + if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) ) + return error; + + if ( ALLOC_ARRAY( table->lengths, count, FT_Byte* ) ) + { + FREE( table->elements ); + return error; + } + + table->max_elems = count; + table->num_elems = 0; + + table->block = 0; + table->capacity = 0; + table->cursor = 0; + + return error; + } + + + static + FT_Error reallocate_t1_table( T1_Table* table, + FT_Int new_size ) + { + FT_Memory memory = table->memory; + FT_Byte* old_base = table->block; + FT_Error error; + + + /* reallocate the base block */ + if ( REALLOC( table->block, table->capacity, new_size ) ) + return error; + table->capacity = new_size; + + /* shift all offsets if necessary */ + if ( old_base ) + { + FT_Long delta = table->block - old_base; + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + if ( delta ) + for ( ; offset < limit; offset ++ ) + if (offset[0]) + offset[0] += delta; + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Add_Table */ + /* */ + /* */ + /* Adds an object to a T1_Table, possibly growing its memory block. */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. An error is returned if a */ + /* reallocation failed. */ + /* */ + LOCAL_FUNC + FT_Error T1_Add_Table( T1_Table* table, + FT_Int index, + void* object, + FT_Int length ) + { + if ( index < 0 || index > table->max_elems ) + { + FT_ERROR(( "T1_Add_Table: invalid index\n" )); + return T1_Err_Syntax_Error; + } + + /* grow the base block if needed */ + if ( table->cursor + length > table->capacity ) + { + FT_Error error; + FT_Int new_size = table->capacity; + + + while ( new_size < table->cursor + length ) + new_size += 1024; + + error = reallocate_t1_table( table, new_size ); + if ( error ) + return error; + } + + /* 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 T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Table */ + /* */ + /* */ + /* Finalize a T1_Table (reallocate it to its current cursor). */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* 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. */ + /* */ + LOCAL_FUNC + void T1_Done_Table( T1_Table* table ) + { + FT_Memory memory = table->memory; + FT_Error error; + FT_Byte* old_base; + + + /* should never fail, as rec.cursor <= rec.size */ + old_base = table->block; + if ( !old_base ) + return; + + (void)REALLOC( table->block, table->capacity, table->cursor ); + table->capacity = table->cursor; + + if ( old_base != table->block ) + { + FT_Long delta = table->block - old_base; + FT_Byte** element = table->elements; + FT_Byte** limit = element + table->max_elems; + + + for ( ; element < limit; element++ ) + if ( element[0] ) + element[0] += delta; + } + } + + + LOCAL_FUNC + FT_String* CopyString( T1_Parser* parser ) + { + FT_String* string = NULL; + T1_Token* token = parser->args++; + FT_Memory memory = parser->tokenizer->memory; + FT_Error error; + + + if ( token->kind == tok_string ) + { + FT_Int len = token->len - 2; + + + if ( ALLOC( string, len + 1 ) ) + { + parser->error = error; + return 0; + } + + MEM_Copy( string, parser->tokenizer->base + token->start + 1, len ); + string[len] = '\0'; + + parser->error = T1_Err_Ok; + } + else + { + FT_ERROR(( "T1_CopyString: syntax error, string token expected!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + return string; + } + + + static + FT_Error parse_int( FT_Byte* base, + FT_Byte* limit, + FT_Long* result ) + { + FT_Bool sign = 0; + FT_Long sum = 0; + + + if ( base >= limit ) + goto Fail; + + /* check sign */ + if ( *base == '+' ) + base++; + + else if ( *base == '-' ) + { + sign++; + base++; + } + + /* parse digits */ + if ( base >= limit ) + goto Fail; + + do + { + sum = ( 10 * sum + ( *base++ - '0' ) ); + + } while ( base < limit ); + + if ( sign ) + sum = -sum; + + *result = sum; + return T1_Err_Ok; + + Fail: + FT_ERROR(( "parse_int: integer expected\n" )); + *result = 0; + return T1_Err_Syntax_Error; + } + + + static + FT_Error parse_float( FT_Byte* base, + FT_Byte* limit, + FT_Long scale, + FT_Long* result ) + { +#if 1 + + /* XXX: We are simply much too lazy to code this function */ + /* properly for now. We will do that when the rest of */ + /* the driver works properly. */ + char temp[32]; + int len = limit - base; + double value; + + + if ( len > 31 ) + goto Fail; + + strncpy( temp, (char*)base, len ); + temp[len] = '\0'; + if ( sscanf( temp, "%lf", &value ) != 1 ) + goto Fail; + + *result = (FT_Long)( scale * value ); + return 0; + +#else + + FT_Byte* cur; + FT_Bool sign = 0; /* sign */ + FT_Long number_int = 0; /* integer part */ + FT_Long number_frac = 0; /* fractional part */ + FT_Long exponent = 0; /* exponent value */ + FT_Int num_frac = 0; /* number of fractional digits */ + + + /* check sign */ + if ( *base == '+' ) + base++; + + else if ( *base == '-' ) + { + sign++; + base++; + } + + /* find integer part */ + cur = base; + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( c == '.' || c == 'e' || c == 'E' ) + break; + + cur++; + } + + if ( cur > base ) + { + error = parse_integer( base, cur, &number_int ); + if ( error ) + goto Fail; + } + + /* read fractional part, if any */ + if ( *cur == '.' ) + { + cur++; + base = cur; + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( c == 'e' || c == 'E' ) + break; + cur++; + } + + num_frac = cur - base; + + if ( cur > base ) + { + error = parse_integer( base, cur, &number_frac ); + if ( error ) + goto Fail; + base = cur; + } + } + + /* read exponent, if any */ + if ( *cur == 'e' || *cur == 'E' ) + { + cur++; + base = cur; + error = parse_integer( base, limit, &exponent ); + if ( error ) + goto Fail; + + /* now check that exponent is within `correct bounds' */ + /* i.e. between -6 and 6 */ + if ( exponent < -6 || exponent > 6 ) + goto Fail; + } + + /* now adjust integer value and exponent for fractional part */ + while ( num_frac > 0 ) + { + number_int *= 10; + exponent--; + num_frac--; + } + + number_int += num_frac; + + /* skip point if any, read fractional part */ + if ( cur + 1 < limit ) + { + if (*cur.. + } + + /* now compute scaled float value */ + /* XXX: incomplete! */ + +#endif /* 1 */ + + Fail: + FT_ERROR(( "parse_float: syntax error!\n" )); + return T1_Err_Syntax_Error; + } + + + static + FT_Error parse_integer( FT_Byte* base, + FT_Byte* limit, + FT_Long* result ) + { + FT_Byte* cur; + + + /* the lexical analyser accepts floats as well as integers */ + /* now; check that we really have an int in this token */ + cur = base; + while ( cur < limit ) + { + FT_Byte c = *cur++; + + + if ( c == '.' || c == 'e' || c == 'E' ) + goto Float_Number; + } + + /* now read the number's value */ + return parse_int( base, limit, result ); + + Float_Number: + /* we really have a float there; simply call parse_float in this */ + /* case with a scale of `10' to perform round */ + { + FT_Error error; + + + error = parse_float( base, limit, 10, result ); + if ( !error ) + { + if ( *result >= 0 ) + *result = ( *result + 5 ) / 10; /* round value */ + else + *result = -( ( 5 - *result ) / 10 ); + } + return error; + } + } + + + LOCAL_FUNC + FT_Long CopyInteger( T1_Parser* parser ) + { + FT_Long sum = 0; + T1_Token* token = parser->args++; + + + if ( token->kind == tok_number ) + { + FT_Byte* base = parser->tokenizer->base + token->start; + FT_Byte* limit = base + token->len; + + + /* now read the number's value */ + parser->error = parse_integer( base, limit, &sum ); + return sum; + } + + FT_ERROR(( "CopyInteger: number expected\n" )); + parser->args--; + parser->error = T1_Err_Syntax_Error; + return 0; + } + + + LOCAL_FUNC + FT_Bool CopyBoolean( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + FT_Bool result = 0; + T1_Token* token = parser->args++; + + + if ( token->kind == tok_keyword ) + { + if ( token->kind2 == key_false ) + result = 0; + + else if ( token->kind2 == key_true ) + result = !0; + + else + goto Fail; + } + else + { + Fail: + FT_ERROR(( "CopyBoolean:" )); + FT_ERROR(( " syntax error; `false' or `true' expected\n" )); + error = T1_Err_Syntax_Error; + } + parser->error = error; + return result; + } + + + LOCAL_FUNC + FT_Long CopyFloat( T1_Parser* parser, + FT_Int scale ) + { + FT_Error error; + FT_Long sum = 0; + T1_Token* token = parser->args++; + + + if ( token->kind == tok_number ) + { + FT_Byte* base = parser->tokenizer->base + token->start; + FT_Byte* limit = base + token->len; + + + error = parser->error = parse_float( base, limit, scale, &sum ); + if ( error ) + goto Fail; + + return sum; + } + + Fail: + FT_ERROR(( "CopyFloat: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + return 0; + } + + + LOCAL_FUNC + void CopyBBox( T1_Parser* parser, + FT_BBox* bbox ) + { + T1_Token* token = parser->args++; + FT_Int n; + FT_Error error; + + + if ( token->kind == tok_program || + token->kind == tok_array ) + { + /* get rid of `['/`]', or `{'/`}' */ + FT_Byte* base = parser->tokenizer->base + token->start + 1; + FT_Byte* limit = base + token->len - 2; + FT_Byte* cur; + FT_Byte* start; + + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < 4; n++ ) + { + FT_Long* result; + + + /* skip whitespace */ + while ( cur < limit && *cur == ' ' ) + cur++; + + /* skip numbers */ + start = cur; + while ( cur < limit && *cur != ' ' ) + cur++; + + /* compute result address */ + switch ( n ) + { + case 0: + result = &bbox->xMin; + break; + case 1: + result = &bbox->yMin; + break; + case 2: + result = &bbox->xMax; + break; + default: + result = &bbox->yMax; + } + + error = parse_integer( start, cur, result ); + if ( error ) + goto Fail; + } + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "CopyBBox: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + + LOCAL_FUNC + void CopyMatrix( T1_Parser* parser, + FT_Matrix* matrix ) + { + T1_Token* token = parser->args++; + FT_Error error; + + + if ( token->kind == tok_array ) + { + /* get rid of `[' and `]' */ + FT_Byte* base = parser->tokenizer->base + token->start + 1; + FT_Byte* limit = base + token->len - 2; + FT_Byte* cur; + FT_Byte* start; + FT_Int n; + + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < 4; n++ ) + { + FT_Long* result; + + + /* skip whitespace */ + while ( cur < limit && *cur == ' ' ) + cur++; + + /* skip numbers */ + start = cur; + while ( cur < limit && *cur != ' ') + cur++; + + /* compute result address */ + switch ( n ) + { + case 0: + result = &matrix->xx; + break; + case 1: + result = &matrix->yx; + break; + case 2: + result = &matrix->xy; + break; + default: + result = &matrix->yy; + } + + error = parse_float( start, cur, 65536000L, result ); + if ( error ) + goto Fail; + } + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "CopyMatrix: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + + LOCAL_FUNC + void CopyArray( T1_Parser* parser, + FT_Byte* num_elements, + FT_Short* elements, + FT_Int max_elements ) + { + T1_Token* token = parser->args++; + FT_Error error; + + + if ( token->kind == tok_array || + token->kind == tok_program ) /* in the case of MinFeature */ + { + /* get rid of `['/`]', or `{'/`}' */ + FT_Byte* base = parser->tokenizer->base + token->start + 1; + FT_Byte* limit = base + token->len - 2; + FT_Byte* cur; + FT_Byte* start; + FT_Int n; + + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < max_elements; n++ ) + { + FT_Long result; + + + /* test end of string */ + if ( cur >= limit ) + break; + + /* skip whitespace */ + while ( cur < limit && *cur == ' ' ) + cur++; + + /* end of list? */ + if ( cur >= limit ) + break; + + /* skip numbers */ + start = cur; + while ( cur < limit && *cur != ' ' ) + cur++; + + error = parse_integer( start, cur, &result ); + if ( error ) + goto Fail; + + *elements++ = (FT_Short)result; + } + + if ( num_elements ) + *num_elements = (FT_Byte)n; + + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "CopyArray: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1parse.h b/reactos/subsys/win32k/freetype/t1parse.h new file mode 100644 index 00000000000..2c42b8cec4b --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1parse.h @@ -0,0 +1,261 @@ +/***************************************************************************/ +/* */ +/* t1parse.h */ +/* */ +/* Type 1 parser (specification). */ +/* */ +/* Copyright 1996-2000 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 Type1 parser component is in charge of simply parsing the font */ + /* input stream and convert simple tokens and elements into integers, */ + /* floats, matrices, strings, etc. */ + /* */ + /* It is used by the Type1 loader. */ + /* */ + /*************************************************************************/ + + +#ifndef T1PARSE_H +#define T1PARSE_H + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1tokens.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* T1_DictState */ + /* */ + /* */ + /* An enumeration used to describe the Type 1 parser's state, i.e. */ + /* which dictionary (or array) it is scanning and processing at the */ + /* current moment. */ + /* */ + typedef enum T1_DictState_ + { + dict_none = 0, + dict_font, /* parsing the font dictionary */ + dict_fontinfo, /* parsing the font info dictionary */ + dict_none2, /* beginning to parse the encrypted section */ + dict_private, /* parsing the private dictionary */ + dict_encoding, /* parsing the encoding array */ + dict_subrs, /* parsing the subrs array */ + dict_othersubrs, /* parsing the othersubrs array (?) */ + dict_charstrings, /* parsing the charstrings dictionary */ + dict_unknown_array, /* parsing/ignoring an unknown array */ + dict_unknown_dict, /* parsing/ignoring an unknown dictionary */ + + dict_max /* do not remove from list */ + + } T1_DictState; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Table */ + /* */ + /* */ + /* A T1_Table is a simple object used to store an array of objects in */ + /* a single memory block. */ + /* */ + /* */ + /* 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). */ + /* */ + typedef struct T1_Table_ + { + FT_Byte* block; /* current memory block */ + FT_Int cursor; /* current cursor in memory block */ + FT_Int capacity; /* current size of memory block */ + + 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; + + } T1_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Parser */ + /* */ + /* */ + /* A Type 1 parser. This object is in charge of parsing Type 1 ASCII */ + /* streams and builds dictionaries for a T1_Face object. */ + /* */ + /* */ + /* error :: The current error code. 0 means success. */ + /* */ + /* face :: The target T1_Face object being built. */ + /* */ + /* tokenizer :: The tokenizer (lexical analyser) used for */ + /* processing the input stream. */ + /* */ + /* dump_tokens :: XXX */ + /* */ + /* stack :: The current token stack. Note that we don't */ + /* use intermediate Postscript objects here! */ + /* */ + /* top :: The current top of token stack. */ + /* */ + /* limit :: The current upper bound of the token stack. */ + /* Used for overflow checks. */ + /* */ + /* args :: The arguments of a given operator. Used and */ + /* increased by the various CopyXXX() functions. */ + /* */ + /* state_index :: The index of the top of the dictionary state */ + /* stack. */ + /* */ + /* state_stack :: The dictionary states stack. */ + /* */ + /* table :: A T1_Table object used to record various kinds */ + /* of dictionaries or arrays (like `/Encoding', */ + /* `/Subrs', `/CharStrings'). */ + /* */ + /* cur_name :: XXX */ + /* */ + /* encoding_type :: XXX */ + /* */ + /* encoding_names :: XXX */ + /* */ + /* encoding_lengths :: XXX */ + /* */ + /* encoding_offsets :: XXX */ + /* */ + /* subrs :: XXX */ + /* */ + /* charstrings :: XXX */ + /* */ + typedef struct T1_Parser_ + { + FT_Error error; + T1_Face face; + + T1_Tokenizer tokenizer; + FT_Bool dump_tokens; + + T1_Token stack[T1_MAX_STACK_DEPTH]; + T1_Token* top; + T1_Token* limit; + T1_Token* args; + + FT_Int state_index; + T1_DictState state_stack[T1_MAX_DICT_DEPTH]; + + T1_Table table; + + FT_Int cur_name; + + T1_EncodingType encoding_type; + FT_Byte* encoding_names; + FT_Int* encoding_lengths; + FT_Byte** encoding_offsets; + + FT_Byte* subrs; + FT_Byte* charstrings; + + } T1_Parser; + + + LOCAL_DEF + FT_Error T1_New_Table( T1_Table* table, + FT_Int count, + FT_Memory memory ); + + LOCAL_DEF + FT_Error T1_Add_Table( T1_Table* table, + FT_Int index, + void* object, + FT_Int length ); + + LOCAL_DEF + void T1_Done_Table( T1_Table* table ); + + + LOCAL_DEF + FT_String* CopyString( T1_Parser* parser ); + + LOCAL_DEF + FT_Long CopyInteger( T1_Parser* parser ); + + LOCAL_DEF + FT_Bool CopyBoolean( T1_Parser* parser ); + + LOCAL_DEF + FT_Long CopyFloat( T1_Parser* parser, + FT_Int scale ); + + LOCAL_DEF + void CopyBBox( T1_Parser* parser, + FT_BBox* bbox ); + + LOCAL_DEF + void CopyMatrix( T1_Parser* parser, + FT_Matrix* matrix ); + + LOCAL_DEF + void CopyArray( T1_Parser* parser, + FT_Byte* num_elements, + FT_Short* elements, + FT_Int max_elements ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1PARSE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1tokens.c b/reactos/subsys/win32k/freetype/t1tokens.c new file mode 100644 index 00000000000..2953322c990 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1tokens.c @@ -0,0 +1,1101 @@ +/***************************************************************************/ +/* */ +/* t1parse.c */ +/* */ +/* Type 1 parser (body). */ +/* */ +/* Copyright 1996-2000 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 tokenizer is in charge of loading and reading a Type1 font file */ + /* (either in PFB or PFA format), and extracting successive tokens and */ + /* keywords from its two streams (i.e. the font program, and the private */ + /* dictionary). */ + /* */ + /* Eexec decryption is performed automatically when entering the private */ + /* dictionary, or when retrieving char strings. */ + /* */ + /*************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1tokens.h" +#include "t1load.h" + +#else + +#include +#include + +#endif + + +#include /* for strncmp() */ + + +#undef READ_BUFFER_INCREMENT +#define READ_BUFFER_INCREMENT 0x400 + + + /*************************************************************************/ + /* */ + /* 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 + + + /* An array of Type1 keywords supported by this engine. This table */ + /* places the keyword in lexicographical order. It should always */ + /* correspond to the enums `key_xxx'! */ + /* */ + const char* t1_keywords[key_max - key_first_] = + { + "-|", "ExpertEncoding", "ND", "NP", "RD", "StandardEncoding", "array", + "begin", "closefile", "currentdict", "currentfile", "def", "dict", "dup", + "eexec", "end", "executeonly", "false", "for", "index", "noaccess", + "put", "readonly", "true", "userdict", "|", "|-" + }; + + + const char* t1_immediates[imm_max - imm_first_] = + { + "-|", ".notdef", "BlendAxisTypes", "BlueFuzz", "BlueScale", "BlueShift", + "BlueValues", "CharStrings", "Encoding", "FamilyBlues", "FamilyName", + "FamilyOtherBlues", "FID", "FontBBox", "FontID", "FontInfo", "FontMatrix", + "FontName", "FontType", "ForceBold", "FullName", "ItalicAngle", + "LanguageGroup", "Metrics", "MinFeature", "ND", "NP", "Notice", + "OtherBlues", "OtherSubrs", "PaintType", "Private", "RD", "RndStemUp", + "StdHW", "StdVW", "StemSnapH", "StemSnapV", "StrokeWidth", "Subrs", + "UnderlinePosition", "UnderlineThickness", "UniqueID", "Weight", + "isFixedPitch", "lenIV", "password", "version", "|", "|-" + }; + + + /* lexicographic comparison of two strings */ + static + int lexico_strcmp( const char* str1, + int str1_len, + const char* str2 ) + { + int c2 = 0; + + + for ( ; str1_len > 0; str1_len-- ) + { + int c1, diff; + + + c1 = *str1++; + c2 = *str2++; + + diff = c1 - c2; + if ( diff ) + return diff; + }; + + return -*str2; + } + + + /* find a given token/name, performing binary search */ + static + int Find_Name( char* base, + int length, + const char** table, + int table_len ) + { + int left, right; + + + left = 0; + right = table_len - 1; + + while ( right - left > 1 ) + { + int middle = left + ( ( right - left ) >> 1 ); + int cmp; + + + cmp = lexico_strcmp( base, length, table[middle] ); + if ( !cmp ) + return middle; + + if ( cmp < 0 ) + right = middle; + else + left = middle; + } + + if ( !lexico_strcmp( base, length, table[left ] ) ) + return left; + if ( !lexico_strcmp( base, length, table[right] ) ) + return right; + + return -1; + } + + + /* read the small PFB section header */ + static + FT_Error Read_PFB_Tag( FT_Stream stream, + FT_UShort* atag, + FT_ULong* asize ) + { + FT_UShort tag; + FT_ULong size; + FT_Error error; + + + FT_TRACE2(( "Read_PFB_Tag: reading\n" )); + + if ( ACCESS_Frame( 6L ) ) + return error; + + tag = GET_UShort(); + size = GET_ULong(); + + FORGET_Frame(); + + *atag = tag; + *asize = ( ( size & 0xFF ) << 24 ) | + ( ( ( size >> 8 ) & 0xFF ) << 16 ) | + ( ( ( size >> 16 ) & 0xFF ) << 8 ) | + ( ( ( size >> 24 ) & 0xFF ) ); + + FT_TRACE2(( " tag = %04x\n", tag )); + FT_TRACE4(( " asze = %08x\n", size )); + FT_TRACE2(( " size = %08x\n", *asize )); + + return T1_Err_Ok; + } + + + static + FT_Error grow( T1_Tokenizer tokzer ) + { + FT_Error error; + FT_Long left_bytes; + FT_Memory memory = tokzer->memory; + + + left_bytes = tokzer->max - tokzer->limit; + + if ( left_bytes > 0 ) + { + FT_Stream stream = tokzer->stream; + + + if ( left_bytes > READ_BUFFER_INCREMENT ) + left_bytes = READ_BUFFER_INCREMENT; + + FT_TRACE2(( "Growing tokenizer buffer by %d bytes\n", left_bytes )); + + if ( !REALLOC( tokzer->base, tokzer->limit, + tokzer->limit + left_bytes ) && + !FILE_Read( tokzer->base + tokzer->limit, left_bytes ) ) + tokzer->limit += left_bytes; + } + else + { + FT_ERROR(( "Unexpected end of Type1 fragment!\n" )); + error = T1_Err_Invalid_File_Format; + } + + tokzer->error = error; + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_decrypt */ + /* */ + /* */ + /* Performs the Type 1 charstring decryption process. */ + /* */ + /* */ + /* buffer :: The base address of the data to decrypt. */ + /* length :: The number of bytes to decrypt (beginning from the base */ + /* address. */ + /* seed :: The encryption seed (4330 for charstrings). */ + /* */ + LOCAL_FUNC + void t1_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ) + { + while ( length > 0 ) + { + FT_Byte plain; + + + plain = ( *buffer ^ ( seed >> 8 ) ); + seed = ( *buffer + seed ) * 52845 + 22719; + *buffer++ = plain; + length--; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* New_Tokenizer */ + /* */ + /* */ + /* Creates a new tokenizer from a given input stream. This function */ + /* automatically recognizes `pfa' or `pfb' files. The function */ + /* Read_Token() can then be used to extract successive tokens from */ + /* the stream. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* tokenizer :: A handle to a new tokenizer object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function copies the stream handle within the object. Callers */ + /* should not discard `stream'. This is done by the Done_Tokenizer() */ + /* function. */ + /* */ + LOCAL_FUNC + FT_Error New_Tokenizer( FT_Stream stream, + T1_Tokenizer* tokenizer ) + { + FT_Memory memory = stream->memory; + T1_Tokenizer tokzer; + FT_Error error; + FT_UShort tag; + FT_ULong size; + + FT_Byte* tok_base; + FT_ULong tok_limit; + FT_ULong tok_max; + + + *tokenizer = 0; + + /* allocate object */ + if ( FILE_Seek( 0L ) || + ALLOC( tokzer, sizeof ( *tokzer ) ) ) + return error; + + tokzer->stream = stream; + tokzer->memory = stream->memory; + + tokzer->in_pfb = 0; + tokzer->in_private = 0; + + tok_base = 0; + tok_limit = 0; + tok_max = stream->size; + + error = Read_PFB_Tag( stream, &tag, &size ); + if ( error ) + goto Fail; + + if ( tag != 0x8001 ) + { + /* assume that it is a PFA file -- an error will be produced later */ + /* if a character with value > 127 is encountered */ + + /* rewind to start of file */ + if ( FILE_Seek( 0L ) ) + goto Fail; + + size = stream->size; + } + else + tokzer->in_pfb = 1; + + /* if it is a memory-based resource, set up pointer */ + if ( !stream->read ) + { + tok_base = (FT_Byte*)stream->base + stream->pos; + tok_limit = size; + tok_max = size; + + /* check that the `size' field is valid */ + if ( FILE_Skip( size ) ) + goto Fail; + } + else if ( tag == 0x8001 ) + { + /* read segment in memory */ + if ( ALLOC( tok_base, size ) ) + goto Fail; + + if ( FILE_Read( tok_base, size ) ) + { + FREE( tok_base ); + goto Fail; + } + + tok_limit = size; + tok_max = size; + } + + tokzer->base = tok_base; + tokzer->limit = tok_limit; + tokzer->max = tok_max; + tokzer->cursor = 0; + + *tokenizer = tokzer; + + /* now check font format; we must see `%!PS-AdobeFont-1' */ + /* or `%!FontType' */ + { + if ( 16 > tokzer->limit ) + grow( tokzer ); + + if ( tokzer->limit <= 16 || + ( strncmp( (const char*)tokzer->base, "%!PS-AdobeFont-1", 16 ) && + strncmp( (const char*)tokzer->base, "%!FontType", 10 ) ) ) + { + FT_TRACE2(( "[not a Type1 font]\n" )); + error = FT_Err_Unknown_File_Format; + goto Fail; + } + } + return T1_Err_Ok; + + Fail: + FREE( tokzer->base ); + FREE( tokzer ); + return error; + } + + + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Done_Tokenizer */ + /* */ + /* */ + /* Closes a given tokenizer. This function will also close the */ + /* stream embedded in the object. */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Done_Tokenizer( T1_Tokenizer tokenizer ) + { + FT_Memory memory = tokenizer->memory; + + + /* clear read buffer if needed (disk-based resources) */ + if ( tokenizer->in_private || !tokenizer->stream->base ) + FREE( tokenizer->base ); + + FREE( tokenizer ); + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Open_PrivateDict */ + /* */ + /* */ + /* This function must be called to set the tokenizer to the private */ + /* section of the Type1 file. It recognizes automatically the */ + /* the kind of eexec encryption used (ascii or binary). */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* lenIV :: The value of the `lenIV' variable. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Open_PrivateDict( T1_Tokenizer tokenizer ) + { + T1_Tokenizer tokzer = tokenizer; + FT_Stream stream = tokzer->stream; + FT_Memory memory = tokzer->memory; + FT_Error error = 0; + + FT_UShort tag; + FT_ULong size; + + FT_Byte* private_dict; + + /* are we already in the private dictionary ? */ + if ( tokzer->in_private ) + return 0; + + if ( tokzer->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_ULong private_dict_size = 0; + + + for (;;) + { + error = Read_PFB_Tag( stream, &tag, &size ); + if ( error || tag != 0x8002 ) + break; + + private_dict_size += size; + + if ( FILE_Skip( size ) ) + goto Fail; + } + + /* check that we have a private dictionary there */ + /* and allocate private dictionary buffer */ + if ( private_dict_size == 0 ) + { + FT_ERROR(( "Open_PrivateDict:" )); + FT_ERROR(( " invalid private dictionary section\n" )); + error = T1_Err_Invalid_File_Format; + goto Fail; + } + + if ( ALLOC( private_dict, private_dict_size ) ) + goto Fail; + + /* read all sections into buffer */ + if ( FILE_Seek( start_pos ) ) + goto Fail_Private; + + private_dict_size = 0; + for (;;) + { + error = Read_PFB_Tag( stream, &tag, &size ); + if ( error || tag != 0x8002 ) + { + error = 0; + break; + } + + if ( FILE_Read( private_dict + private_dict_size, size ) ) + goto Fail_Private; + + private_dict_size += size; + } + + /* we must free the field `tokzer.base' if we are in a disk-based */ + /* PFB file. */ + if ( stream->read ) + FREE( tokzer->base ); + + tokzer->base = private_dict; + tokzer->cursor = 0; + tokzer->limit = private_dict_size; + tokzer->max = private_dict_size; + } + else + { + char* base; + + + /* we are in a PFA file; read each token until we find `eexec' */ + while ( tokzer->token.kind2 != key_eexec ) + { + error = Read_Token( tokzer ); + if ( error ) + goto Fail; + } + + /* now determine whether the private dictionary is encoded in binary */ + /* or hexadecimal ASCII format. */ + + /* 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. */ + while ( tokzer->cursor + 5 > tokzer->limit ) + { + error = grow( tokzer ); + if ( error ) + goto Fail; + } + + /* skip whitespace/line feed after `eexec' */ + base = (char*)tokzer->base + tokzer->cursor + 1; + if ( ( hexa_value( base[0] ) | hexa_value( base[1] ) | + hexa_value( base[2] ) | hexa_value( base[3] ) ) < 0 ) + { + /* binary encoding -- `simply' read the stream */ + + /* if it is a memory-based resource, we need to allocate a new */ + /* storage buffer for the private dictionary, as it must be */ + /* decrypted later */ + if ( stream->base ) + { + size = stream->size - tokzer->cursor - 1; /* remaining bytes */ + + if ( ALLOC( private_dict, size ) ) /* alloc private dict buffer */ + goto Fail; + + /* copy eexec-encrypted bytes */ + MEM_Copy( private_dict, tokzer->base + tokzer->cursor + 1, size ); + + /* reset pointers - forget about file mapping */ + tokzer->base = private_dict; + tokzer->limit = size; + tokzer->max = size; + tokzer->cursor = 0; + } + /* On the opposite, for disk based resources, we simply grow */ + /* the current buffer until its completion, and decrypt the */ + /* bytes within it. In all cases, the `base' buffer will be */ + /* discarded on DoneTokenizer if we are in the private dict. */ + else + { + /* grow the read buffer to the full file */ + while ( tokzer->limit < tokzer->max ) + { + error = grow( tokenizer ); + if ( error ) + goto Fail; + } + + /* set up cursor to first encrypted byte */ + tokzer->cursor++; + } + } + else + { + /* ASCII hexadecimal encoding. This sucks... */ + FT_Byte* write; + FT_Byte* cur; + FT_Byte* limit; + FT_Int count; + + + /* allocate a buffer, read each one byte at a time */ + count = stream->size - tokzer->cursor; + size = count / 2; + + if ( ALLOC( private_dict, size ) ) /* alloc private dict buffer */ + goto Fail; + + write = private_dict; + cur = tokzer->base + tokzer->cursor; + limit = tokzer->base + tokzer->limit; + + /* read each bytes */ + while ( count > 0 ) + { + /* ensure that we can read the next 2 bytes! */ + while ( cur + 2 > limit ) + { + int cursor = cur - tokzer->base; + + + error = grow( tokzer ); + if ( error ) + goto Fail_Private; + cur = tokzer->base + cursor; + limit = tokzer->base + tokzer->limit; + } + + /* check for new line */ + if ( cur[0] == '\r' || cur[0] == '\n' ) + { + cur++; + count--; + } + else + { + int hex1 = hexa_value(cur[0]); + + + /* exit if we have a non-hexadecimal digit which isn't */ + /* a new-line character */ + if ( hex1 < 0 ) + break; + + /* otherwise, store byte */ + *write++ = ( hex1 << 4 ) | hexa_value( cur[1] ); + cur += 2; + count -= 2; + } + } + + /* get rid of old buffer in the case of disk-based resources */ + if ( !stream->base ) + FREE( tokzer->base ); + + /* set up pointers */ + tokzer->base = private_dict; + tokzer->limit = size; + tokzer->max = size; + tokzer->cursor = 0; + } + } + + /* finally, decrypt the private dictionary - and skip the lenIV bytes */ + t1_decrypt( tokzer->base, tokzer->limit, 55665 ); + tokzer->cursor += 4; + + Fail: + return error; + + Fail_Private: + FREE( private_dict ); + goto Fail; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Read_Token */ + /* */ + /* */ + /* Reads a new token from the current input stream. This function */ + /* extracts a token from the font program until Open_PrivateDict() */ + /* has been called. After this, it returns tokens from the */ + /* (eexec-encrypted) private dictionary. */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Use the function Read_CharStrings() to read the binary charstrings */ + /* from the private dict. */ + /* */ + LOCAL_FUNC + FT_Error Read_Token( T1_Tokenizer tokenizer ) + { + T1_Tokenizer tok = tokenizer; + FT_Long cur, limit; + FT_Byte* base; + char c, starter, ender; + FT_Bool token_started; + + T1_TokenType kind; + + + tok->error = T1_Err_Ok; + tok->token.kind = tok_any; + + base = tok->base; + limit = tok->limit; + cur = tok->cursor; + + token_started = 0; + + for (;;) + { + if ( cur >= limit ) + { + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + c = (char)base[cur++]; + + /* check that we have an ASCII character */ + if ( (FT_Byte)c > 127 ) + { + FT_ERROR(( "Read_Token:" )); + FT_ERROR(( " unexpected binary data in Type1 fragment!\n" )); + tok->error = T1_Err_Invalid_File_Format; + goto Exit; + } + + switch ( c ) + { + case '\r': + case '\n': + case ' ' : + case '\t': /* skip initial whitespace => skip to next */ + if ( token_started ) + { + /* possibly a name, keyword, wathever */ + tok->token.kind = tok_any; + tok->token.len = cur-tok->token.start - 1; + goto Exit; + } + /* otherwise, skip everything */ + break; + + case '%': /* this is a comment -- skip everything */ + for (;;) + { + FT_Int left = limit - cur; + + + while ( left > 0 ) + { + c = (char)base[cur++]; + if ( c == '\r' || c == '\n' ) + goto Next; + left--; + } + + if ( grow( tokenizer ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + case '(': /* a Postscript string */ + kind = tok_string; + ender = ')'; + + L1: + if ( !token_started ) + { + token_started = 1; + tok->token.start = cur - 1; + } + + { + FT_Int nest_level = 1; + + + starter = c; + for (;;) + { + FT_Int left = limit - cur; + + + while ( left > 0 ) + { + c = (char)base[cur++]; + + if ( c == starter ) + nest_level++; + + else if ( c == ender ) + { + nest_level--; + if ( nest_level <= 0 ) + { + tok->token.kind = kind; + tok->token.len = cur - tok->token.start; + goto Exit; + } + } + left--; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + } + + case '[': /* a Postscript array */ + if ( token_started ) + goto Any_Token; + + kind = tok_array; + ender = ']'; + goto L1; + break; + + case '{': /* a Postscript program */ + if ( token_started ) + goto Any_Token; + + kind = tok_program; + ender = '}'; + goto L1; + break; + + case '<': /* a Postscript hex byte array? */ + if ( token_started ) + goto Any_Token; + + kind = tok_hexarray; + ender = '>'; + goto L1; + break; + + case '0': /* any number */ + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if ( token_started ) + goto Next; + + tok->token.kind = tok_number; + token_started = 1; + tok->token.start = cur - 1; + + L2: + for (;;) + { + FT_Int left = limit-cur; + + + while ( left > 0 ) + { + c = (char)base[cur++]; + + switch ( c ) + { + case '[': /* ] */ + case '{': /* } */ + case '(': /* ) */ + case '<': + case '/': + goto Any_Token; + + case ' ': + case '\r': + case '\t': + case '\n': + tok->token.len = cur - tok->token.start - 1; + goto Exit; + + default: + ; + } + left--; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + case '.': /* maybe a number */ + case '-': + case '+': + if ( token_started ) + goto Next; + + token_started = 1; + tok->token.start = cur - 1; + + for (;;) + { + FT_Int left = limit - cur; + + + if ( left > 0 ) + { + /* test for any following digit, interpreted as number */ + c = (char)base[cur]; + tok->token.kind = ( c >= '0' && c <= '9' ? tok_number : tok_any ); + goto L2; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + case '/': /* maybe an immediate name */ + if ( !token_started ) + { + token_started = 1; + tok->token.start = cur - 1; + + for (;;) + { + FT_Int left = limit - cur; + + + if ( left > 0 ) + { + /* test for single '/', interpreted as garbage */ + c = (char)base[cur]; + tok->token.kind = ( c == ' ' || c == '\t' || + c == '\r' || c == '\n' ) ? tok_any + : tok_immediate; + goto L2; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + } + else + { + Any_Token: /* possibly a name or wathever */ + cur--; + tok->token.len = cur - tok->token.start; + goto Exit; + } + + default: + if ( !token_started ) + { + token_started = 1; + tok->token.start = cur - 1; + } + } + + Next: + ; + } + + Exit: + tok->cursor = cur; + + if ( !tok->error ) + { + /* now, tries to match keywords and immediate names */ + FT_Int index; + + + switch ( tok->token.kind ) + { + case tok_immediate: /* immediate name */ + index = Find_Name( (char*)( tok->base + tok->token.start + 1 ), + tok->token.len - 1, + t1_immediates, + imm_max - imm_first_ ); + tok->token.kind2 = ( index >= 0 ) + ? (T1_TokenType)( imm_first_ + index ) + : tok_error; + break; + + case tok_any: /* test for keyword */ + index = Find_Name( (char*)( tok->base + tok->token.start ), + tok->token.len, + t1_keywords, + key_max - key_first_ ); + if ( index >= 0 ) + { + tok->token.kind = tok_keyword; + tok->token.kind2 = (T1_TokenType)( key_first_ + index ); + } + else + tok->token.kind2 = tok_error; + break; + + default: + tok->token.kind2 = tok_error; + } + } + return tokenizer->error; + } + + +#if 0 + + /*************************************************************************/ + /* */ + /* */ + /* Read_CharStrings */ + /* */ + /* */ + /* Reads a charstrings element from the current input stream. These */ + /* are binary bytes that encode each individual glyph outline. */ + /* */ + /* The caller is responsible for skipping the `lenIV' bytes at the */ + /* start of the record. */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* num_chars :: The number of binary bytes to read. */ + /* */ + /* */ + /* buffer :: The target array of bytes. These are */ + /* eexec-decrypted. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Use the function Read_CharStrings() to read binary charstrings */ + /* from the private dict. */ + /* */ + LOCAL_FUNC + FT_Error Read_CharStrings( T1_Tokenizer tokenizer, + FT_Int num_chars, + FT_Byte* buffer ) + { + for (;;) + { + FT_Int left = tokenizer->limit - tokenizer->cursor; + + + if ( left >= num_chars ) + { + MEM_Copy( buffer, tokenizer->base + tokenizer->cursor, num_chars ); + t1_decrypt( buffer, num_chars, 4330 ); + tokenizer->cursor += num_chars; + return T1_Err_Ok; + } + + if ( grow( tokenizer ) ) + return tokenizer->error; + } + } + +#endif /* 0 */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t1tokens.h b/reactos/subsys/win32k/freetype/t1tokens.h new file mode 100644 index 00000000000..119c54ba19e --- /dev/null +++ b/reactos/subsys/win32k/freetype/t1tokens.h @@ -0,0 +1,258 @@ +/***************************************************************************/ +/* */ +/* t1tokens.h */ +/* */ +/* Type 1 tokenizer (specification). */ +/* */ +/* Copyright 1996-2000 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 T1TOKENS_H +#define T1TOKENS_H + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* enum value of first keyword */ +#define key_first_ 100 + + /* enum value of first immediate name */ +#define imm_first_ 200 + + + typedef enum T1_TokenType_ + { + tok_error = 0, + + tok_eof, /* end of file */ + + /* simple token types */ + + tok_keyword, /* keyword */ + tok_number, /* number (integer or real) */ + tok_string, /* postscript string */ + tok_program, /* postscript program */ + tok_immediate, /* any immediate name */ + tok_array, /* matrix, array, etc.. */ + tok_hexarray, /* array of hexadecimal nibbles */ + tok_any, /* anything else */ + + /* Postscript keywords -- placed in lexicographical order */ + + key_RD_alternate = key_first_, /* `-|' = alternate form of RD */ + key_ExpertEncoding, + key_ND, + key_NP, + key_RD, + key_StandardEncoding, + key_array, + key_begin, + key_closefile, + key_currentdict, + key_currentfile, + key_def, + key_dict, + key_dup, + key_eexec, + key_end, + key_execonly, + key_false, + key_for, + key_index, + key_noaccess, + key_put, + key_readonly, + key_true, + key_userdict, + key_NP_alternate, /* `|' = alternate form of NP */ + key_ND_alternate, /* `|-' = alternate form of ND */ + + key_max, /* always keep this value there */ + + /* Postscript immediate names -- other names will be ignored, except */ + /* in charstrings */ + + imm_RD_alternate = imm_first_, /* `-|' = alternate form of RD */ + imm_notdef, /* `/.notdef' immediate */ + imm_BlendAxisTypes, + imm_BlueFuzz, + imm_BlueScale, + imm_BlueShift, + imm_BlueValues, + imm_CharStrings, + imm_Encoding, + imm_FamilyBlues, + imm_FamilyName, + imm_FamilyOtherBlues, + imm_FID, + imm_FontBBox, + imm_FontID, + imm_FontInfo, + imm_FontMatrix, + imm_FontName, + imm_FontType, + imm_ForceBold, + imm_FullName, + imm_ItalicAngle, + imm_LanguageGroup, + imm_Metrics, + imm_MinFeature, + imm_ND, + imm_NP, + imm_Notice, + imm_OtherBlues, + imm_OtherSubrs, + imm_PaintType, + imm_Private, + imm_RD, + imm_RndStemUp, + imm_StdHW, + imm_StdVW, + imm_StemSnapH, + imm_StemSnapV, + imm_StrokeWidth, + imm_Subrs, + imm_UnderlinePosition, + imm_UnderlineThickness, + imm_UniqueID, + imm_Weight, + + imm_isFixedPitch, + imm_lenIV, + imm_password, + imm_version, + + imm_NP_alternate, /* `|' = alternate form of NP */ + imm_ND_alternate, /* `|-' = alternate form of ND */ + + imm_max /* always keep this value here */ + + } T1_TokenType; + + + /* these arrays are visible for debugging purposes */ + extern const char* t1_keywords[]; + extern const char* t1_immediates[]; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Token */ + /* */ + /* */ + /* A structure used to describe a token in the current input stream. */ + /* Note that the Type1 driver doesn't try to interpret tokens until */ + /* it really needs to. */ + /* */ + /* */ + /* kind :: The token type. Describes the token to the loader. */ + /* */ + /* kind2 :: Detailed token type. */ + /* */ + /* start :: The index of the first character of token in the input */ + /* stream. */ + /* */ + /* len :: The length of the token in characters. */ + /* */ + typedef struct T1_Token_ + { + T1_TokenType kind; /* simple type */ + T1_TokenType kind2; /* detailed type */ + FT_Int start; /* index of first token character */ + FT_Int len; /* length of token in chars */ + + } T1_Token; + + + typedef struct T1_TokenParser_ + { + FT_Memory memory; + FT_Stream stream; + + FT_Bool in_pfb; /* true if PFB file, PFA otherwise */ + FT_Bool in_private; /* true if in private dictionary */ + + FT_Byte* base; /* base address of current read buffer */ + FT_Long cursor; /* current position in read buffer */ + FT_Long limit; /* limit of current read buffer */ + FT_Long max; /* maximum size of read buffer */ + + FT_Error error; /* last error */ + T1_Token token; /* last token read */ + + } T1_TokenParser; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Tokenizer */ + /* */ + /* */ + /* A handle to an object used to extract tokens from the input. The */ + /* object is able to perform PFA/PFB recognition, eexec decryption of */ + /* the private dictionary, as well as eexec decryption of the */ + /* charstrings. */ + /* */ + typedef T1_TokenParser* T1_Tokenizer; + + + LOCAL_DEF + FT_Error New_Tokenizer( FT_Stream stream, + T1_Tokenizer* tokenizer ); + + LOCAL_DEF + FT_Error Done_Tokenizer( T1_Tokenizer tokenizer ); + + LOCAL_DEF + FT_Error Open_PrivateDict( T1_Tokenizer tokenizer ); + + LOCAL_DEF + FT_Error Read_Token( T1_Tokenizer tokenizer ); + + +#if 0 + LOCAL_DEF + FT_Error Read_CharStrings( T1_Tokenizer tokenizer, + FT_Int num_chars, + FT_Byte* buffer ); +#endif /* 0 */ + + LOCAL_DEF + void t1_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1TOKENS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t2driver.c b/reactos/subsys/win32k/freetype/t2driver.c new file mode 100644 index 00000000000..d1e1b188d23 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2driver.c @@ -0,0 +1,377 @@ +/***************************************************************************/ +/* */ +/* t2driver.c */ +/* */ +/* OpenType font driver implementation (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2driver.h" +#include "t2gload.h" + +#else + +#include +#include + +#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_t2driver + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F A C E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#undef PAIR_TAG +#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ + (FT_ULong)right ) + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 T2_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 T2_Err_Ok; + + Found: + kerning->x = pair->value; + goto Exit; + } + + +#undef PAIR_TAG + + + /*************************************************************************/ + /* */ + /* */ + /* Load_Glyph */ + /* */ + /* */ + /* A driver method used to load a glyph within a given glyph slot. */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Load_Glyph( T2_GlyphSlot slot, + T2_Size size, + FT_UShort glyph_index, + FT_UInt load_flags ) + { + FT_Error error; + + + if ( !slot ) + return T2_Err_Invalid_Glyph_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 T2_Err_Invalid_Face_Handle; + } + + /* now load the glyph outline if necessary */ + error = T2_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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Glyph index. 0 means `undefined character code'. */ + /* */ + static + FT_UInt t2_get_char_index( TT_CharMap charmap, + FT_Long charcode ) + { + FT_Error error; + T2_Face face; + TT_CMapTable* cmap; + + + cmap = &charmap->cmap; + face = (T2_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 ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** D R I V E R I N T E R F A C E ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Module_Interface t2_get_interface( T2_Driver driver, + const char* interface ) + { + FT_Module sfnt; + + + /* 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. */ + + const FT_Driver_Class cff_driver_class = + { + /* begin with the FT_Module_Class fields */ + { + ft_module_font_driver | ft_module_driver_scalable, + sizeof( T2_DriverRec ), + "cff", + 0x10000L, + 0x20000L, + + 0, /* module-specific interface */ + + (FT_Module_Constructor)T2_Init_Driver, + (FT_Module_Destructor) T2_Done_Driver, + (FT_Module_Requester) t2_get_interface, + }, + + /* now the specific driver fields */ + sizeof( TT_FaceRec ), + sizeof( FT_SizeRec ), + sizeof( T2_GlyphSlotRec ), + + (FTDriver_initFace) T2_Init_Face, + (FTDriver_doneFace) T2_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) t2_get_char_index, + + (FTDriver_getKerning) Get_Kerning, + (FTDriver_attachFile) 0, + (FTDriver_getAdvances) 0 + }; + + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverClass */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ + EXPORT_FUNC( FT_Driver_Class* ) getDriverClass( void ) + { + return &cff_driver_class; + } + + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t2driver.h b/reactos/subsys/win32k/freetype/t2driver.h new file mode 100644 index 00000000000..e0b0afd3ac3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2driver.h @@ -0,0 +1,30 @@ +/***************************************************************************/ +/* */ +/* t2driver.h */ +/* */ +/* High-level OpenType driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 T2DRIVER_H +#define T2DRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Driver_Class ) cff_driver_class; + + +#endif /* T2DRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t2gload.c b/reactos/subsys/win32k/freetype/t2gload.c new file mode 100644 index 00000000000..1023e3cf481 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2gload.c @@ -0,0 +1,2045 @@ +/***************************************************************************/ +/* */ +/* t2gload.c */ +/* */ +/* OpenType Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2load.h" +#include "t2gload.h" + +#else + +#include +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* 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_t2gload + + + typedef enum T2_Operator_ + { + t2_op_unknown = 0, + + t2_op_rmoveto, + t2_op_hmoveto, + t2_op_vmoveto, + + t2_op_rlineto, + t2_op_hlineto, + t2_op_vlineto, + + t2_op_rrcurveto, + t2_op_hhcurveto, + t2_op_hvcurveto, + t2_op_rcurveline, + t2_op_rlinecurve, + t2_op_vhcurveto, + t2_op_vvcurveto, + + t2_op_flex, + t2_op_hflex, + t2_op_hflex1, + t2_op_flex1, + + t2_op_endchar, + + t2_op_hstem, + t2_op_vstem, + t2_op_hstemhm, + t2_op_vstemhm, + + t2_op_hintmask, + t2_op_cntrmask, + + t2_op_abs, + t2_op_add, + t2_op_sub, + t2_op_div, + t2_op_neg, + t2_op_random, + t2_op_mul, + t2_op_sqrt, + + t2_op_blend, + + t2_op_drop, + t2_op_exch, + t2_op_index, + t2_op_roll, + t2_op_dup, + + t2_op_put, + t2_op_get, + t2_op_store, + t2_op_load, + + t2_op_and, + t2_op_or, + t2_op_not, + t2_op_eq, + t2_op_ifelse, + + t2_op_callsubr, + t2_op_callgsubr, + t2_op_return, + + /* do not remove */ + t2_op_max + + } T2_Operator; + + +#define T2_COUNT_CHECK_WIDTH 0x80 +#define T2_COUNT_EXACT 0x40 +#define T2_COUNT_CLEAR_STACK 0x20 + + + static const FT_Byte t2_argument_counts[] = + { + 0, /* unknown */ + + 2 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, /* rmoveto */ + 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, + 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, + + 0 | T2_COUNT_CLEAR_STACK, /* rlineto */ + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + + 0 | T2_COUNT_CLEAR_STACK, /* rrcurveto */ + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + + 13, /* flex */ + 7, + 9, + 11, + + 0, /* endchar */ + + 2 | T2_COUNT_CHECK_WIDTH, /* hstem */ + 2 | T2_COUNT_CHECK_WIDTH, + 2 | T2_COUNT_CHECK_WIDTH, + 2 | T2_COUNT_CHECK_WIDTH, + + 0, /* hintmask */ + 0, /* cntrmask */ + + 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 *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + static + void T2_Init_Builder( T2_Builder* builder, + TT_Face face, + T2_Size size, + T2_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.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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Done_Builder */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + static + void T2_Done_Builder( T2_Builder* builder ) + { + T2_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t2_compute_bias */ + /* */ + /* */ + /* Computes the bias value in dependence of the number of glyph */ + /* subroutines. */ + /* */ + /* */ + /* num_subrs :: The number of glyph subroutines. */ + /* */ + /* */ + /* The bias value. */ + static + FT_Int t2_compute_bias( FT_UInt num_subrs ) + { + FT_Int result; + + + if ( num_subrs < 1240 ) + result = 107; + else if ( num_subrs < 33900 ) + result = 1131; + else + result = 32768; + + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* slot :: The current glyph object. */ + /* */ + LOCAL_FUNC + void T2_Init_Decoder( T2_Decoder* decoder, + TT_Face face, + T2_Size size, + T2_GlyphSlot slot ) + { + CFF_Font* cff = (CFF_Font*)face->extra.data; + + + /* clear everything */ + MEM_Set( decoder, 0, sizeof ( *decoder ) ); + + /* initialize builder */ + T2_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 = t2_compute_bias( decoder->num_globals ); + } + + + /* this function is used to select the locals subrs array */ + LOCAL_DEF + void T2_Prepare_Decoder( T2_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 = t2_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( T2_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( T2_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 = 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( T2_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( T2_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return T2_Err_Ok; + } + + error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = 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( T2_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( T2_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; + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + } + + +#define USE_ARGS( n ) do \ + { \ + top -= n; \ + if ( top < decoder->stack ) \ + goto Stack_Underflow; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given Type 2 charstrings program. */ + /* */ + /* */ + /* decoder :: The current Type 1 decoder. */ + /* */ + /* */ + /* charstring_base :: The base of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T2_Parse_CharStrings( T2_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ) + { + FT_Error error; + T2_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + T2_Builder* builder = &decoder->builder; + FT_Outline* outline; + 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 = T2_Err_Ok; + outline = builder->current; + + x = builder->pos_x; + y = builder->pos_y; + + /* now, execute loop */ + while ( ip < limit ) + { + T2_Operator op; + FT_Byte v; + FT_Byte count; + + + /********************************************************************/ + /* */ + /* 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 >= T2_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 = t2_op_unknown; + + switch ( v ) + { + case 1: + op = t2_op_hstem; + break; + case 3: + op = t2_op_vstem; + break; + case 4: + op = t2_op_vmoveto; + break; + case 5: + op = t2_op_rlineto; + break; + case 6: + op = t2_op_hlineto; + break; + case 7: + op = t2_op_vlineto; + break; + case 8: + op = t2_op_rrcurveto; + break; + case 10: + op = t2_op_callsubr; + break; + case 11: + op = t2_op_return; + break; + case 12: + { + if ( ip >= limit ) + goto Syntax_Error; + v = *ip++; + + switch ( v ) + { + case 3: + op = t2_op_and; + break; + case 4: + op = t2_op_or; + break; + case 5: + op = t2_op_not; + break; + case 8: + op = t2_op_store; + break; + case 9: + op = t2_op_abs; + break; + case 10: + op = t2_op_add; + break; + case 11: + op = t2_op_sub; + break; + case 12: + op = t2_op_div; + break; + case 13: + op = t2_op_load; + break; + case 14: + op = t2_op_neg; + break; + case 15: + op = t2_op_eq; + break; + case 18: + op = t2_op_drop; + break; + case 20: + op = t2_op_put; + break; + case 21: + op = t2_op_get; + break; + case 22: + op = t2_op_ifelse; + break; + case 23: + op = t2_op_random; + break; + case 24: + op = t2_op_mul; + break; + case 26: + op = t2_op_sqrt; + break; + case 27: + op = t2_op_dup; + break; + case 28: + op = t2_op_exch; + break; + case 29: + op = t2_op_index; + break; + case 30: + op = t2_op_roll; + break; + case 34: + op = t2_op_hflex; + break; + case 35: + op = t2_op_flex; + break; + case 36: + op = t2_op_hflex1; + break; + case 37: + op = t2_op_flex1; + break; + default: + /* decrement ip for syntax error message */ + ip--; + } + } + break; + case 14: + op = t2_op_endchar; + break; + case 16: + op = t2_op_blend; + break; + case 18: + op = t2_op_hstemhm; + break; + case 19: + op = t2_op_hintmask; + break; + case 20: + op = t2_op_cntrmask; + break; + case 21: + op = t2_op_rmoveto; + break; + case 22: + op = t2_op_hmoveto; + break; + case 23: + op = t2_op_vstemhm; + break; + case 24: + op = t2_op_rcurveline; + break; + case 25: + op = t2_op_rlinecurve; + break; + case 26: + op = t2_op_vvcurveto; + break; + case 27: + op = t2_op_hhcurveto; + break; + case 29: + op = t2_op_callgsubr; + break; + case 30: + op = t2_op_vhcurveto; + break; + case 31: + op = t2_op_hvcurveto; + break; + default: + ; + } + if ( op == t2_op_unknown ) + goto Syntax_Error; + + /* check arguments */ + req_args = count = t2_argument_counts[op]; + if ( req_args & T2_COUNT_CHECK_WIDTH ) + { + args = stack; + if ( num_args & 1 && decoder->read_width ) + { + decoder->glyph_width = decoder->nominal_width + + ( stack[0] >> 16 ); + 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 t2_op_hstem: + case t2_op_vstem: + case t2_op_hstemhm: + case t2_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 == t2_op_hstem ? " hstem" : + op == t2_op_vstem ? " vstem" : + op == t2_op_hstemhm ? " hstemhm" : + " vstemhm" )); + decoder->num_hints += num_args / 2; + args = stack; + break; + + case t2_op_hintmask: + case t2_op_cntrmask: + FT_TRACE4(( op == t2_op_hintmask ? " hintmask" + : " cntrmask" )); + + decoder->num_hints += num_args / 2; + ip += ( decoder->num_hints + 7 ) >> 3; + if ( ip >= limit ) + goto Syntax_Error; + args = stack; + break; + + case t2_op_rmoveto: + FT_TRACE4(( " rmoveto" )); + + close_contour( builder ); + builder->path_begun = 0; + x += args[0]; + y += args[1]; + args = stack; + break; + + case t2_op_vmoveto: + FT_TRACE4(( " vmoveto" )); + + close_contour( builder ); + builder->path_begun = 0; + y += args[0]; + args = stack; + break; + + case t2_op_hmoveto: + FT_TRACE4(( " hmoveto" )); + + close_contour( builder ); + builder->path_begun = 0; + x += args[0]; + args = stack; + break; + + case t2_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 t2_op_hlineto: + case t2_op_vlineto: + { + FT_Int phase = ( op == t2_op_hlineto ); + + + FT_TRACE4(( op == t2_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 t2_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 t2_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 t2_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 t2_op_vhcurveto: + case t2_op_hvcurveto: + { + FT_Int phase; + + + FT_TRACE4(( op == t2_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 == t2_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 t2_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 t2_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 t2_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 t2_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 t2_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 t2_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 t2_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 T2_Err_Ok; + + case t2_op_abs: + FT_TRACE4(( " abs" )); + + if ( args[0] < 0 ) + args[0] = -args[0]; + args++; + break; + + case t2_op_add: + FT_TRACE4(( " add" )); + + args[0] += args[1]; + args++; + break; + + case t2_op_sub: + FT_TRACE4(( " sub" )); + + args[0] -= args[1]; + args++; + break; + + case t2_op_div: + FT_TRACE4(( " div" )); + + args[0] = FT_DivFix( args[0], args[1] ); + args++; + break; + + case t2_op_neg: + FT_TRACE4(( " neg" )); + + args[0] = -args[0]; + args++; + break; + + case t2_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 t2_op_mul: + FT_TRACE4(( " mul" )); + + args[0] = FT_MulFix( args[0], args[1] ); + args++; + break; + + case t2_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 t2_op_drop: + /* nothing */ + FT_TRACE4(( " drop" )); + + break; + + case t2_op_exch: + { + FT_Fixed tmp; + + + FT_TRACE4(( " exch" )); + + tmp = args[0]; + args[0] = args[1]; + args[1] = tmp; + args += 2; + } + break; + + case t2_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 t2_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 t2_op_dup: + FT_TRACE4(( " dup" )); + + args[1] = args[0]; + args++; + break; + + case t2_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 t2_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 t2_op_store: + FT_TRACE4(( " store ")); + + goto Unimplemented; + + case t2_op_load: + FT_TRACE4(( " load" )); + + goto Unimplemented; + + case t2_op_and: + { + FT_Fixed cond = args[0] && args[1]; + + + FT_TRACE4(( " and" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case t2_op_or: + { + FT_Fixed cond = args[0] || args[1]; + + + FT_TRACE4(( " or" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case t2_op_eq: + { + FT_Fixed cond = !args[0]; + + + FT_TRACE4(( " eq" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case t2_op_ifelse: + { + FT_Fixed cond = (args[2] <= args[3]); + + + FT_TRACE4(( " ifelse" )); + + if ( !cond ) + args[0] = args[1]; + args++; + } + break; + + case t2_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(( "T2_Parse_CharStrings:" )); + FT_ERROR(( " invalid local subr index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "T2_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(( "T2_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case t2_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(( "T2_Parse_CharStrings:" )); + FT_ERROR(( " invalid global subr index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "T2_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(( "T2_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case t2_op_return: + FT_TRACE4(( " return" )); + + if ( decoder->zone <= decoder->zones ) + { + FT_ERROR(( "T2_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 T2_Err_Unimplemented_Feature; + } + + decoder->top = args; + + } /* general operator processing */ + + } /* while ip < limit */ + + FT_TRACE4(( "..end..\n\n" )); + + return error; + + Syntax_Error: + FT_TRACE4(( "T2_Parse_CharStrings: syntax error!" )); + return T2_Err_Invalid_File_Format; + + Stack_Underflow: + FT_TRACE4(( "T2_Parse_CharStrings: stack underflow!" )); + return T2_Err_Too_Few_Arguments; + + Stack_Overflow: + FT_TRACE4(( "T2_Parse_CharStrings: stack overflow!" )); + return T2_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 */ + + + LOCAL_FUNC + FT_Error T2_Compute_Max_Advance( TT_Face face, + FT_Int* max_advance ) + { + FT_Error error = 0; + T2_Decoder decoder; + FT_Int glyph_index; + CFF_Font* cff = (CFF_Font*)face->other; + + + *max_advance = 0; + + /* Initialize load decoder */ + T2_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 = T2_Access_Element( &cff->charstrings_index, glyph_index, + &charstring, &charstring_len ); + if ( !error ) + { + T2_Prepare_Decoder( &decoder, glyph_index ); + error = T2_Parse_CharStrings( &decoder, charstring, charstring_len ); + + T2_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 T2_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. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error T2_Load_Glyph( T2_GlyphSlot glyph, + T2_Size size, + FT_Int glyph_index, + FT_Int load_flags ) + { + FT_Error error; + T2_Decoder decoder; + TT_Face face = (TT_Face)glyph->root.face; + FT_Bool hinting; + CFF_Font* cff = (CFF_Font*)face->extra.data; + + + 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 = ( 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; + + + T2_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 = T2_Access_Element( &cff->charstrings_index, glyph_index, + &charstring, &charstring_len ); + if ( !error ) + { + T2_Prepare_Decoder( &decoder, glyph_index ); + error = T2_Parse_CharStrings( &decoder, charstring, charstring_len ); + + T2_Forget_Element( &cff->charstrings_index, &charstring ); + } + + /* save new glyph tables */ + T2_Done_Builder( &decoder.builder ); + } + + /* 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 ( glyph->root.format == ft_glyph_format_composite ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.glyph_width; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.glyph_width; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 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; + + 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 ); + } + +#if 0 + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, cff->font_matrix ); +#endif + + /* 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/reactos/subsys/win32k/freetype/t2gload.h b/reactos/subsys/win32k/freetype/t2gload.h new file mode 100644 index 00000000000..2654d4b5636 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2gload.h @@ -0,0 +1,213 @@ +/***************************************************************************/ +/* */ +/* t2gload.h */ +/* */ +/* OpenType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 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 T2GLOAD_H +#define T2GLOAD_H + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + +#define T2_MAX_OPERANDS 48 +#define T2_MAX_SUBRS_CALLS 32 + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* 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 T2_Builder_ + { + FT_Memory memory; + TT_Face face; + T2_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; + + } T2_Builder; + + + /* execution context charstring zone */ + + typedef struct T2_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } T2_Decoder_Zone; + + + typedef struct T2_Decoder_ + { + T2_Builder builder; + CFF_Font* cff; + + FT_Fixed stack[T2_MAX_OPERANDS + 1]; + FT_Fixed* top; + + T2_Decoder_Zone zones[T2_MAX_SUBRS_CALLS + 1]; + T2_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; + + } T2_Decoder; + + + LOCAL_DEF + void T2_Init_Decoder( T2_Decoder* decoder, + TT_Face face, + T2_Size size, + T2_GlyphSlot slot ); + + LOCAL_DEF + void T2_Prepare_Decoder( T2_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 */ + LOCAL_DEF + FT_Error T2_Compute_Max_Advance( TT_Face face, + FT_Int* max_advance ); + +#endif /* 0 */ + + LOCAL_DEF + FT_Error T2_Parse_CharStrings( T2_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ); + + LOCAL_DEF + FT_Error T2_Load_Glyph( T2_GlyphSlot glyph, + T2_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2GLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t2load.c b/reactos/subsys/win32k/freetype/t2load.c new file mode 100644 index 00000000000..4a776933181 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2load.c @@ -0,0 +1,757 @@ +/***************************************************************************/ +/* */ +/* t2load.c */ +/* */ +/* TrueType glyph data/program tables loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2load.h" +#include "t2parse.h" + +#else + +#include +#include + +#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_t2load + + + /* read a CFF offset from memory */ + static + FT_ULong t2_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 t2_new_cff_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] = t2_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 */ + (void)FILE_Skip( data_size ); + } + } + + Exit: + if ( error ) + FREE( index->offsets ); + + return error; + } + + + static + void t2_done_cff_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 t2_explicit_cff_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; + } + + + LOCAL_FUNC + FT_Error T2_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; + + + 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 = T2_Err_Invalid_Argument; + + Exit: + return error; + } + + + LOCAL_FUNC + void T2_Forget_Element( CFF_Index* index, + FT_Byte** pbytes ) + { + if ( index->bytes == 0 ) + { + FT_Stream stream = index->stream; + + + RELEASE_Frame( *pbytes ); + } + } + + + LOCAL_FUNC + FT_String* T2_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 = T2_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; + } + T2_Forget_Element( index, &bytes ); + + Exit: + return name; + } + + + LOCAL_FUNC + FT_String* T2_Get_String( CFF_Index* index, + FT_UInt sid, + PSNames_Interface* interface ) + { + /* if it is not a standard string, return it */ + if ( sid > 390 ) + return T2_Get_Name( index, sid - 390 ); + + /* 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 = T2_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + LOCAL_FUNC + 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 + 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; + T2_Parser parser; + FT_Byte* dict; + FT_ULong dict_len; + CFF_Font_Dict* top = &font->font_dict; + CFF_Private* priv = &font->private_dict; + + + T2_Parser_Init( &parser, T2CODE_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 = T2_Access_Element( index, font_index, &dict, &dict_len ) || + T2_Parser_Run( &parser, dict, dict + dict_len ); + + T2_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; + + T2_Parser_Init( &parser, T2CODE_PRIVATE, priv ); + + if ( FILE_Seek( base_offset + font->font_dict.private_offset ) || + ACCESS_Frame( font->font_dict.private_size ) ) + goto Exit; + + error = T2_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 = t2_new_cff_index( &font->local_subrs_index, stream, 1 ); + if ( error ) + goto Exit; + + font->num_local_subrs = font->local_subrs_index.count; + error = t2_explicit_cff_index( &font->local_subrs_index, + &font->local_subrs ); + } + + Exit: + return error; + } + + + static + void CFF_Done_SubFont( FT_Memory memory, + CFF_SubFont* subfont ) + { + if ( subfont ) + { + t2_done_cff_index( &subfont->local_subrs_index ); + FREE( subfont->local_subrs ); + } + } + + + LOCAL_FUNC + FT_Error T2_Load_CFF_Font( FT_Stream stream, + FT_Int face_index, + CFF_Font* font ) + { + static const FT_Frame_Field cff_header_fields[] = + { + FT_FRAME_START( 4 ), + FT_FRAME_BYTE( CFF_Font, version_major ), + FT_FRAME_BYTE( CFF_Font, version_minor ), + FT_FRAME_BYTE( CFF_Font, header_size ), + FT_FRAME_BYTE( CFF_Font, 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 = FT_Err_Unknown_File_Format; + goto Exit; + } + + /* skip the rest of the header */ + (void)FILE_Skip( font->header_size - 4 ); + + /* read the name, top dict, string and global subrs index */ + error = t2_new_cff_index( &font->name_index, stream, 0 ) || + t2_new_cff_index( &font->font_dict_index, stream, 0 ) || + t2_new_cff_index( &font->string_index, stream, 0 ) || + t2_new_cff_index( &font->global_subrs_index, stream, 1 ); + if ( error ) + 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(( "T2_Load_CFF_Font: incorrect face index = %d\n", + face_index )); + error = T2_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 = t2_new_cff_index( &fd_index, stream, 0 ); + if ( error ) + goto Exit; + + if ( fd_index.count > CFF_MAX_CID_FONTS ) + { + FT_ERROR(( "T2_Load_CFF_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: + t2_done_cff_index( &fd_index ); + + if ( error ) + goto Exit; + } + else + font->num_subfonts = 0; + + /* read the charstrings index now */ + if ( dict->charstrings_offset == 0 ) + { + FT_ERROR(( "T2_Load_CFF_Font: no charstrings offset!\n" )); + error = FT_Err_Unknown_File_Format; + goto Exit; + } + + if ( FILE_Seek( base_offset + dict->charstrings_offset ) ) + goto Exit; + + error = t2_new_cff_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 = t2_explicit_cff_index( &font->global_subrs_index, + &font->global_subrs ) ; + + if ( error ) + goto Exit; + + /* get the font name */ + font->font_name = T2_Get_Name( &font->name_index, face_index ); + + Exit: + return error; + } + + + LOCAL_FUNC + void T2_Done_CFF_Font( CFF_Font* font ) + { + FT_Memory memory = font->memory; + FT_UInt index; + + + t2_done_cff_index( &font->global_subrs_index ); + t2_done_cff_index( &font->string_index ); + t2_done_cff_index( &font->font_dict_index ); + t2_done_cff_index( &font->name_index ); + t2_done_cff_index( &font->charstrings_index ); + + /* release font dictionaries */ + for ( index = 0; index < font->num_subfonts; index++ ) + CFF_Done_SubFont( memory, font->subfonts[index] ); + + 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/reactos/subsys/win32k/freetype/t2load.h b/reactos/subsys/win32k/freetype/t2load.h new file mode 100644 index 00000000000..7ebc76d27d3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2load.h @@ -0,0 +1,69 @@ +/***************************************************************************/ +/* */ +/* t2load.h */ +/* */ +/* OpenType glyph data/program tables loader (specification). */ +/* */ +/* Copyright 1996-2000 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 T2LOAD_H +#define T2LOAD_H + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + LOCAL_DEF + FT_String* T2_Get_Name( CFF_Index* index, + FT_UInt element ); + + LOCAL_DEF + FT_String* T2_Get_String( CFF_Index* index, + FT_UInt sid, + PSNames_Interface* interface ); + + LOCAL_DEF + FT_Error T2_Access_Element( CFF_Index* index, + FT_UInt element, + FT_Byte** pbytes, + FT_ULong* pbyte_len ); + + LOCAL_DEF + void T2_Forget_Element( CFF_Index* index, + FT_Byte** pbytes ); + + LOCAL_DEF + FT_Error T2_Load_CFF_Font( FT_Stream stream, + FT_Int face_index, + CFF_Font* font ); + + LOCAL_DEF + void T2_Done_CFF_Font( CFF_Font* font ); + + LOCAL_DEF + FT_Byte CFF_Get_FD( CFF_FD_Select* select, + FT_UInt glyph_index ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2LOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t2objs.c b/reactos/subsys/win32k/freetype/t2objs.c new file mode 100644 index 00000000000..1d59a585f7e --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2objs.c @@ -0,0 +1,600 @@ +/***************************************************************************/ +/* */ +/* t2objs.c */ +/* */ +/* OpenType objects manager (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2objs.h" +#include "t2load.h" + +#else + +#include +#include + +#endif + + +#include + +#include /* 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_t2objs + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + static + FT_String* T2_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( T2_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 = T2_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] = T2_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] = T2_Get_String( &font->string_index, + first, + psnames ); + gname++; + first++; + } + } + break; + } + + default: /* unknown charset format! */ + FT_ERROR(( "CFF: unknown charset format!\n" )); + error = T2_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Face */ + /* */ + /* */ + /* Initializes a given OpenType face object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_DEF + FT_Error T2_Init_Face( FT_Stream stream, + T2_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 T2_Err_Ok; + + sfnt_format = 1; + + /* now, the font can be either an OpenType/CFF font, or a 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: for now, we don't load the GPOS table, as OpenType Layout */ + /* support will be added later to FreeType 2 as a separate module */ + } + + /* 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 */ + (void)FILE_Seek( 0 ); + error = FT_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; + FT_ULong base_offset; + + + if ( ALLOC( cff, sizeof ( *cff ) ) ) + goto Exit; + + base_offset = FILE_Pos(); + + face->extra.data = cff; + error = T2_Load_CFF_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(( "T2_Init_Face:" )); + FT_ERROR(( " cannot open CFF & CEF fonts\n" )); + FT_ERROR(( " " )); + FT_ERROR(( " without the `PSNames' module\n" )); + goto Bad_Format; + } + + /* 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->units_per_EM = (FT_UInt)FT_DivFix( 1000L << 16, + dict->font_matrix.yy ) >> 16; + root->bbox = dict->font_bbox; + root->ascender = (FT_Short)root->bbox.yMax; + root->descender = (FT_Short)root->bbox.yMin; + + /* retrieve font family & style name */ + root->family_name = T2_Get_Name( &cff->name_index, face_index ); + if ( dict->cid_registry ) + { + root->style_name = T2_StrCopy( memory, "Regular" ); /* XXXX */ + } + else + { + root->style_name = T2_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; + +/* XXXX: 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 + + 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 = platform; + charmap->root.encoding_id = 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 = FT_Err_Unknown_File_Format; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Done_Face */ + /* */ + /* */ + /* Finalizes a given face object. */ + /* */ + /* */ + /* face :: A pointer to the face object to destroy. */ + /* */ + LOCAL_DEF + void T2_Done_Face( T2_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 ) + { + T2_Done_CFF_Font( cff ); + FREE( face->extra.data ); + } + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Driver */ + /* */ + /* */ + /* Initializes a given OpenType driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T2_Init_Driver( T2_Driver driver ) + { + /* init extension registry if needed */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + + return TT_Init_Extensions( driver ); + +#else + + FT_UNUSED( driver ); + + return T2_Err_Ok; + +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Done_Driver */ + /* */ + /* */ + /* Finalizes a given OpenType driver. */ + /* */ + /* */ + /* driver :: A handle to the target OpenType driver. */ + /* */ + LOCAL_FUNC + void T2_Done_Driver( T2_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/reactos/subsys/win32k/freetype/t2objs.h b/reactos/subsys/win32k/freetype/t2objs.h new file mode 100644 index 00000000000..2602862751f --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2objs.h @@ -0,0 +1,148 @@ +/***************************************************************************/ +/* */ +/* t2objs.h */ +/* */ +/* OpenType objects manager (specification). */ +/* */ +/* Copyright 1996-2000 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 T2OBJS_H +#define T2OBJS_H + + +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Driver */ + /* */ + /* */ + /* A handle to an OpenType driver object. */ + /* */ + typedef struct T2_DriverRec_* T2_Driver; + + typedef TT_Face T2_Face; + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Size */ + /* */ + /* */ + /* A handle to an OpenType size object. */ + /* */ + typedef FT_Size T2_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* T2_GlyphSlot */ + /* */ + /* */ + /* A handle to an OpenType glyph slot object. */ + /* */ + typedef struct T2_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + + FT_Bool hint; + FT_Bool scaled; + + FT_Fixed x_scale; + FT_Fixed y_scale; + + } T2_GlyphSlotRec, *T2_GlyphSlot; + + + + /*************************************************************************/ + /* */ + /* Subglyph transformation record. */ + /* */ + typedef struct T2_Transform_ + { + FT_Fixed xx, xy; /* transformation matrix coefficients */ + FT_Fixed yx, yy; + FT_F26Dot6 ox, oy; /* offsets */ + + } T2_Transform; + + + /* this is only used in the case of a pure CFF font with no charmap */ + typedef struct T2_CharMapRec_ + { + TT_CharMapRec root; + PS_Unicodes unicodes; + + } T2_CharMapRec, *T2_CharMap; + + + /***********************************************************************/ + /* */ + /* TrueType driver class. */ + /* */ + typedef struct T2_DriverRec_ + { + FT_DriverRec root; + + void* extension_component; + + } T2_DriverRec; + + + /*************************************************************************/ + /* */ + /* Face functions */ + /* */ + LOCAL_DEF + FT_Error T2_Init_Face( FT_Stream stream, + T2_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void T2_Done_Face( T2_Face face ); + + + /*************************************************************************/ + /* */ + /* Driver functions */ + /* */ + LOCAL_DEF + FT_Error T2_Init_Driver( T2_Driver driver ); + + LOCAL_DEF + void T2_Done_Driver( T2_Driver driver ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2OBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t2parse.c b/reactos/subsys/win32k/freetype/t2parse.c new file mode 100644 index 00000000000..7d62fef5b67 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2parse.c @@ -0,0 +1,641 @@ +/***************************************************************************/ +/* */ +/* t2parse.c */ +/* */ +/* OpenType parser (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t2parse.h" + +#else + +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* 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_t2parse + + +#define T2_Err_Stack_Underflow FT_Err_Invalid_Argument +#define T2_Err_Syntax_Error FT_Err_Invalid_Argument + + + enum + { + t2_kind_none = 0, + t2_kind_num, + t2_kind_fixed, + t2_kind_string, + t2_kind_bool, + t2_kind_delta, + t2_kind_callback, + + t2_kind_max /* do not remove */ + }; + + + /* now generate handlers for the most simple fields */ + typedef FT_Error (*T2_Field_Reader)( T2_Parser* parser ); + + typedef struct T2_Field_Handler_ + { + int kind; + int code; + FT_UInt offset; + FT_Byte size; + T2_Field_Reader reader; + FT_UInt array_max; + FT_UInt count_offset; + + } T2_Field_Handler; + + + LOCAL_FUNC + void T2_Parser_Init( T2_Parser* parser, + FT_UInt code, + void* object ) + { + MEM_Set( parser, 0, sizeof ( *parser ) ); + + parser->top = parser->stack; + parser->object_code = code; + parser->object = object; + } + + + /* reads an integer */ + static + FT_Long parse_t2_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 parse_t2_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_Byte nib; + FT_Byte phase; + + + result = 0; + num = 0; + divider = 1; + + /* first of all, read the integer part */ + phase = 4; + p--; + + for (;;) + { + /* read one nibble at a time */ + if ( phase && ++p >= limit ) + goto Bad; + + 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 (;;) + { + /* read one nibble at a time */ + if ( !phase && ++p >= limit ) + goto Bad; + + phase = 4 - phase; + nib = ( p[0] >> phase ) & 0xF; + + 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 (;;) + { + /* read one nibble at a time */ + if ( !phase && ++p >= limit ) + goto Bad; + + phase = 4 - phase; + nib = ( p[0] >> phase ) & 0xF; + + 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++; + } + + 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 t2_parse_num( FT_Byte** d ) + { + return ( **d == 30 ? ( parse_t2_real( d[0], d[1], 0 ) >> 16 ) + : parse_t2_integer( d[0], d[1] ) ); + } + + + /* reads a floating point number, either integer or real */ + static + FT_Fixed t2_parse_fixed( FT_Byte** d ) + { + return ( **d == 30 ? parse_t2_real( d[0], d[1], 0 ) + : parse_t2_integer( d[0], d[1] ) << 16 ); + } + + + static + FT_Error parse_font_matrix( T2_Parser* parser ) + { + CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; + FT_Matrix* matrix = &dict->font_matrix; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 4 ) + { + matrix->xx = t2_parse_fixed( data++ ); + matrix->yx = t2_parse_fixed( data++ ); + matrix->xy = t2_parse_fixed( data++ ); + matrix->yy = t2_parse_fixed( data ); + error = T2_Err_Ok; + } + + return error; + } + + + static + FT_Error parse_font_bbox( T2_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 = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 4 ) + { + bbox->xMin = t2_parse_num( data++ ); + bbox->yMin = t2_parse_num( data++ ); + bbox->xMax = t2_parse_num( data++ ); + bbox->yMax = t2_parse_num( data ); + error = T2_Err_Ok; + } + + return error; + } + + + static + FT_Error parse_private_dict( T2_Parser* parser ) + { + CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 2 ) + { + dict->private_size = t2_parse_num( data++ ); + dict->private_offset = t2_parse_num( data ); + error = T2_Err_Ok; + } + + return error; + } + + + static + FT_Error parse_cid_ros( T2_Parser* parser ) + { + CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 3 ) + { + dict->cid_registry = (FT_UInt)t2_parse_num( data++ ); + dict->cid_ordering = (FT_UInt)t2_parse_num( data++ ); + dict->cid_supplement = (FT_ULong)t2_parse_num( data ); + error = T2_Err_Ok; + } + + return error; + } + + +#define T2_FIELD_NUM( code, name ) \ + T2_FIELD( code, name, t2_kind_num ) +#define T2_FIELD_FIXED( code, name ) \ + T2_FIELD( code, name, t2_kind_fixed ) +#define T2_FIELD_STRING( code, name ) \ + T2_FIELD( code, name, t2_kind_string ) +#define T2_FIELD_BOOL( code, name ) \ + T2_FIELD( code, name, t2_kind_bool ) +#define T2_FIELD_DELTA( code, name,max ) \ + T2_FIELD( code, name, t2_kind_delta ) + +#define T2_REF( s, f ) ( ((s*)0)->f ) + +#define T2_FIELD_CALLBACK( code, name ) \ + { \ + t2_kind_callback, \ + code | T2CODE, \ + 0, 0, \ + parse_ ## name, \ + 0, 0 \ + }, + +#undef T2_FIELD +#define T2_FIELD( code, name, kind ) \ + { \ + kind, \ + code | T2CODE, \ + (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \ + sizeof( T2_REF( T2TYPE, name ) ), \ + 0, 0, 0 \ + }, + +#undef T2_FIELD_DELTA +#define T2_FIELD_DELTA( code, name, max ) \ + { \ + t2_kind_delta, \ + code | T2CODE, \ + (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \ + sizeof( T2_REF( T2TYPE, name )[0] ), \ + 0, \ + max, \ + (FT_UInt)(char*)&T2_REF( T2TYPE, num_ ## name ) \ + }, + +#define T2CODE_TOPDICT 0x1000 +#define T2CODE_PRIVATE 0x2000 + + static const T2_Field_Handler t2_field_handlers[] = + { + +#ifdef FT_FLAT_COMPILE + +#include "t2tokens.h" + +#else + +#include + +#endif + + { 0, 0, 0, 0, 0, 0, 0 } + }; + + + LOCAL_FUNC + FT_Error T2_Parser_Run( T2_Parser* parser, + FT_Byte* start, + FT_Byte* limit ) + { + FT_Byte* p = start; + FT_Error error = T2_Err_Ok; + + + parser->top = parser->stack; + parser->start = start; + parser->limit = limit; + parser->cursor = start; + + while ( p < limit ) + { + FT_Byte v = *p; + + + if ( v >= 27 && v != 31 ) + { + /* it's a number; we will push its position on the stack */ + if ( parser->top - parser->stack >= T2_MAX_STACK_DEPTH ) + goto Stack_Overflow; + + *parser->top ++ = p; + + /* now, skip it */ + if ( v == 30 ) + { + /* skip real number */ + for (;;) + { + if ( p >= limit ) + goto Syntax_Error; + v = p[0] >> 4; + if ( v == 15 ) + break; + v = p[0] & 0xF; + if ( v == 15 ) + break; + p++; + } + 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 T2_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 = t2_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 t2_kind_bool: + case t2_kind_string: + case t2_kind_num: + val = t2_parse_num( parser->stack ); + goto Store_Number; + + case t2_kind_fixed: + val = t2_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 t2_kind_delta: + { + FT_Byte* qcount = (FT_Byte*)parser->object + + field->count_offset; + + FT_Long val; + 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 += t2_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 = T2_Err_Invalid_Argument; + goto Exit; + + Stack_Underflow: + error = T2_Err_Invalid_Argument; + goto Exit; + + Syntax_Error: + error = T2_Err_Invalid_Argument; + goto Exit; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t2parse.h b/reactos/subsys/win32k/freetype/t2parse.h new file mode 100644 index 00000000000..2238444b7a1 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2parse.h @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* t2parse.h */ +/* */ +/* OpenType parser (specification). */ +/* */ +/* Copyright 1996-2000 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 T2PARSE_H +#define T2PARSE_H + +#include +#include + +#define T2_MAX_STACK_DEPTH 96 + +#define T2CODE_TOPDICT 0x1000 +#define T2CODE_PRIVATE 0x2000 + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct T2_Parser_ + { + FT_Byte* start; + FT_Byte* limit; + FT_Byte* cursor; + + FT_Byte* stack[T2_MAX_STACK_DEPTH + 1]; + FT_Byte** top; + + FT_UInt object_code; + void* object; + + } T2_Parser; + + + LOCAL_DEF + void T2_Parser_Init( T2_Parser* parser, + FT_UInt code, + void* object ); + + LOCAL_DEF + FT_Error T2_Parser_Run( T2_Parser* parser, + FT_Byte* start, + FT_Byte* limit ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2PARSE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/t2tokens.h b/reactos/subsys/win32k/freetype/t2tokens.h new file mode 100644 index 00000000000..13a15e43df3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/t2tokens.h @@ -0,0 +1,96 @@ +/***************************************************************************/ +/* */ +/* t2tokens.h */ +/* */ +/* OpenType token definitions (specification only). */ +/* */ +/* Copyright 1996-2000 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 T2TYPE +#undef T2CODE +#define T2TYPE CFF_Font_Dict +#define T2CODE T2CODE_TOPDICT + + T2_FIELD_STRING ( 0, version ) + T2_FIELD_STRING ( 1, notice ) + T2_FIELD_STRING ( 0x100, copyright ) + T2_FIELD_STRING ( 2, full_name ) + T2_FIELD_STRING ( 3, family_name ) + T2_FIELD_STRING ( 4, weight ) + T2_FIELD_BOOL ( 0x101, is_fixed_pitch ) + T2_FIELD_FIXED ( 0x102, italic_angle ) + T2_FIELD_NUM ( 0x103, underline_position ) + T2_FIELD_NUM ( 0x104, underline_thickness ) + T2_FIELD_NUM ( 0x105, paint_type ) + T2_FIELD_NUM ( 0x106, charstring_type ) + T2_FIELD_CALLBACK( 0x107, font_matrix ) + T2_FIELD_NUM ( 13, unique_id ) + T2_FIELD_CALLBACK( 5, font_bbox ) + T2_FIELD_NUM ( 0x108, stroke_width ) + T2_FIELD_NUM ( 15, charset_offset ) + T2_FIELD_NUM ( 16, encoding_offset ) + T2_FIELD_NUM ( 17, charstrings_offset ) + T2_FIELD_CALLBACK( 18, private_dict ) + T2_FIELD_NUM ( 0x114, synthetic_base ) + T2_FIELD_STRING ( 0x115, postscript ) + T2_FIELD_STRING ( 0x116, base_font_name ) + +#if 0 + T2_FIELD_DELTA ( 0x117, base_font_blend, 16 ) + T2_FIELD_CALLBACK( 0x118, multiple_master ) + T2_FIELD_CALLBACK( 0x119, blend_axit_types ) +#endif + + T2_FIELD_CALLBACK( 0x11E, cid_ros ) + T2_FIELD_NUM ( 0x11F, cid_font_version ) + T2_FIELD_NUM ( 0x120, cid_font_revision ) + T2_FIELD_NUM ( 0x121, cid_font_type ) + T2_FIELD_NUM ( 0x122, cid_count ) + T2_FIELD_NUM ( 0x123, cid_uid_base ) + T2_FIELD_NUM ( 0x124, cid_fd_array_offset ) + T2_FIELD_NUM ( 0x125, cid_fd_select_offset ) + T2_FIELD_STRING ( 0x126, cid_font_name ) + +#if 0 + T2_FIELD_NUM ( 0x127, chameleon ) +#endif + + +#undef T2TYPE +#undef T2CODE +#define T2TYPE CFF_Private +#define T2CODE T2CODE_PRIVATE + + T2_FIELD_DELTA( 6, blue_values, 14 ) + T2_FIELD_DELTA( 7, other_blues, 10 ) + T2_FIELD_DELTA( 8, family_blues, 14 ) + T2_FIELD_DELTA( 9, family_other_blues, 10 ) + T2_FIELD_FIXED( 0x109, blue_scale ) + T2_FIELD_NUM ( 0x10A, blue_shift ) + T2_FIELD_NUM ( 0x10B, blue_fuzz ) + T2_FIELD_NUM ( 10, standard_width ) + T2_FIELD_NUM ( 11, standard_height ) + T2_FIELD_DELTA( 0x10C, snap_widths, 13 ) + T2_FIELD_DELTA( 0x10D, snap_heights, 13 ) + T2_FIELD_BOOL ( 0x10E, force_bold ) + T2_FIELD_FIXED( 0x10F, force_bold_threshold ) + T2_FIELD_NUM ( 0x110, lenIV ) + T2_FIELD_NUM ( 0x111, language_group ) + T2_FIELD_FIXED( 0x112, expansion_factor ) + T2_FIELD_NUM ( 0x113, initial_random_seed ) + T2_FIELD_NUM ( 19, local_subrs_offset ) + T2_FIELD_NUM ( 20, default_width ) + T2_FIELD_NUM ( 21, nominal_width ) + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/truetype.c b/reactos/subsys/win32k/freetype/truetype.c new file mode 100644 index 00000000000..2a311dc3267 --- /dev/null +++ b/reactos/subsys/win32k/freetype/truetype.c @@ -0,0 +1,49 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* truetype.c */ +/* */ +/* FreeType TrueType driver component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#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" /* bytecode interpreter */ +#endif + +#else /* FT_FLAT_COMPILE */ + +#include /* driver interface */ +#include /* tables loader */ +#include /* glyph loader */ +#include /* object manager */ + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include /* bytecode interpreter */ +#endif + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttcmap.c b/reactos/subsys/win32k/freetype/ttcmap.c new file mode 100644 index 00000000000..87ad04f0148 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttcmap.c @@ -0,0 +1,550 @@ +/***************************************************************************/ +/* */ +/* ttcmap.c */ +/* */ +/* TrueType character mapping table (cmap) support (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.h" +#include "ttcmap.h" + +#else + +#include +#include + +#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_ttcmap + + + static FT_UInt code_to_index0( TT_CMapTable* charmap, + FT_ULong char_code ); + static FT_UInt code_to_index2( TT_CMapTable* charmap, + FT_ULong char_code ); + static FT_UInt code_to_index4( TT_CMapTable* charmap, + FT_ULong char_code ); + static FT_UInt code_to_index6( TT_CMapTable* charmap, + FT_ULong char_code ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Load */ + /* */ + /* */ + /* Loads a given TrueType character map into memory. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* stream :: A handle to the current stream object. */ + /* */ + /* */ + /* table :: A pointer to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The function assumes that the stream is already in use (i.e., */ + /* opened). In case of error, all partially allocated tables are */ + /* released. */ + /* */ + LOCAL_FUNC + 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_UShort u, l; + + TT_CMap0* cmap0; + TT_CMap2* cmap2; + TT_CMap4* cmap4; + TT_CMap6* cmap6; + + TT_CMap2SubHeader* cmap2sub; + TT_CMap4Segment* segments; + + + if ( cmap->loaded ) + return TT_Err_Ok; + + memory = stream->memory; + + if ( FILE_Seek( cmap->offset ) ) + return error; + + switch ( cmap->format ) + { + case 0: + cmap0 = &cmap->c.cmap0; + + if ( 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( 512L ) ) + goto Fail; + + for ( i = 0; i < 256; i++ ) + { + u = GET_UShort() / 8; + cmap2->subHeaderKeys[i] = u; + + if ( num_SH < u ) + num_SH = u; + } + + FORGET_Frame(); + + /* load subheaders */ + + cmap2->numGlyphId = l = + ( ( 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 ) ) + 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 = 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 ) ) + 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( 8L ) ) + goto Fail; + + cmap4->segCountX2 = GET_UShort(); + cmap4->searchRange = GET_UShort(); + cmap4->entrySelector = GET_UShort(); + cmap4->rangeShift = GET_UShort(); + + num_Seg = 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 = + ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFF ) / 2; + + /* load IDs */ + + if ( ALLOC_ARRAY( cmap4->glyphIdArray, l, FT_UShort ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap4->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + + cmap->get_index = code_to_index4; + + cmap4->last_segment = cmap4->segments; + break; + + case 6: + cmap6 = &cmap->c.cmap6; + + if ( ACCESS_Frame( 4L ) ) + goto Fail; + + cmap6->firstCode = GET_UShort(); + cmap6->entryCount = GET_UShort(); + + FORGET_Frame(); + + l = cmap6->entryCount; + + if ( ALLOC_ARRAY( cmap6->glyphIdArray, + cmap6->entryCount, + 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; + + default: /* corrupt character mapping table */ + return TT_Err_Invalid_CharMap_Format; + + } + + return TT_Err_Ok; + + Fail: + TT_CharMap_Free( face, cmap ); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Free */ + /* */ + /* */ + /* Destroys a character mapping table. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* cmap :: A handle to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_CharMap_Free( TT_Face face, + TT_CMapTable* cmap ) + { + FT_Memory memory; + + + if ( !cmap ) + return TT_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; + + default: + /* invalid table format, do nothing */ + ; + } + + cmap->loaded = FALSE; + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index0 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 0. */ + /* `charCode' must be in the range 0x00-0xFF (otherwise 0 is */ + /* returned). */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap0 :: A pointer to a cmap table in format 0. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + FT_UInt code_to_index0( TT_CMapTable* cmap, + FT_ULong charCode ) + { + TT_CMap0* cmap0 = &cmap->c.cmap0; + + + return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index2 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 2. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap2 :: A pointer to a cmap table in format 2. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + 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 */ + if ( cmap2->subHeaderKeys[char_lo] == 0 ) + result = cmap2->glyphIdArray[char_lo]; + } + else + { + /* a 16-bit character code */ + index1 = cmap2->subHeaderKeys[char_hi & 0xFF]; + if ( index1 ) + { + sh2 = cmap2->subHeaders + index1; + char_lo -= sh2->firstCode; + + if ( char_lo < sh2->entryCount ) + { + offset = sh2->idRangeOffset / 2 + char_lo; + if ( offset < cmap2->numGlyphId ) + { + result = cmap2->glyphIdArray[offset]; + if ( result ) + result = ( result + sh2->idDelta ) & 0xFFFF; + } + } + } + } + + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index4 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 4. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap4 :: A pointer to a cmap table in format 4. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + 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; + seg4 = cmap4->segments; + limit = seg4 + segCount; + + /* check against the last segment */ + seg4 = cmap4->last_segment; + + /* the following is equivalent to performing two tests, as in */ + /* */ + /* if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */ + /* */ + /* Yes, that's a bit strange, but it's 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 Found; + + 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 > seg4->endCount ) + continue; + + if ( charCode >= seg4->startCount ) + goto Found; + } + return 0; + + Found: + cmap4->last_segment = seg4; + + /* 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 = seg4->idRangeOffset / 2 + + ( charCode - seg4->startCount ) + + ( seg4 - cmap4->segments ) + - segCount; + + if ( index1 < cmap4->numGlyphId && + cmap4->glyphIdArray[index1] != 0 ) + result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFF; + } + + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index6 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 6. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap6 :: A pointer to a cmap table in format 6. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + FT_UInt code_to_index6( TT_CMapTable* cmap, + FT_ULong charCode ) + { + TT_CMap6* cmap6; + FT_UInt result = 0; + + + cmap6 = &cmap->c.cmap6; + result = 0; + charCode -= cmap6->firstCode; + + if ( charCode < cmap6->entryCount ) + result = cmap6->glyphIdArray[charCode]; + + return result; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttcmap.h b/reactos/subsys/win32k/freetype/ttcmap.h new file mode 100644 index 00000000000..609972a901e --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttcmap.h @@ -0,0 +1,45 @@ +/***************************************************************************/ +/* */ +/* ttcmap.h */ +/* */ +/* TrueType character mapping table (cmap) support (specification). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error TT_CharMap_Load( TT_Face face, + TT_CMapTable* cmap, + FT_Stream input ); + + LOCAL_DEF + FT_Error TT_CharMap_Free( TT_Face face, + TT_CMapTable* cmap ); + +#ifdef __cplusplus + } +#endif + +#endif /* TTCMAP_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttdriver.c b/reactos/subsys/win32k/freetype/ttdriver.c new file mode 100644 index 00000000000..0b3cb480c59 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttdriver.c @@ -0,0 +1,511 @@ +/***************************************************************************/ +/* */ +/* ttdriver.c */ +/* */ +/* TrueType font driver implementation (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttdriver.h" +#include "ttgload.h" + +#else + +#include +#include + +#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_ttdriver + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F A C E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#undef PAIR_TAG +#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ + (FT_ULong)right ) + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Char_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in fractional points. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* 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; + + return TT_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Pixel_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in integer pixels. */ + /* */ + /* */ + /* pixel_width :: The character width expressed in integer pixels. */ + /* */ + /* pixel_height :: The character height expressed in integer pixels. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* 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; + + return TT_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Load_Glyph */ + /* */ + /* */ + /* A driver method used to load a glyph within a given glyph slot. */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* 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_Glyph_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 ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* 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. */ + + 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 + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverInterface */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ + EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void ) + { + return &tt_driver_class; + } + + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttdriver.h b/reactos/subsys/win32k/freetype/ttdriver.h new file mode 100644 index 00000000000..9867fbc3095 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttdriver.h @@ -0,0 +1,31 @@ +/***************************************************************************/ +/* */ +/* ttdriver.h */ +/* */ +/* High-level TrueType driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 + + + FT_EXPORT_VAR( const FT_Driver_Class ) tt_driver_class; + + +#endif /* TTDRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttgload.c b/reactos/subsys/win32k/freetype/ttgload.c new file mode 100644 index 00000000000..e9b87fa67ed --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttgload.c @@ -0,0 +1,1477 @@ +/***************************************************************************/ +/* */ +/* ttgload.c */ +/* */ +/* TrueType Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttgload.h" + +#else + +#include + +#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_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 + + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_Metrics */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* header :: A pointer to either the horizontal or vertical metrics */ + /* structure. */ + /* */ + /* index :: The glyph index. */ + /* */ + /* */ + /* bearing :: The bearing, either left side or top side. */ + /* */ + /* advance :: The advance width resp. advance height. */ + /* */ + /* */ + /* This function will much probably move to another component in the */ + /* near future, but I haven't decided which yet. */ + /* */ + LOCAL_FUNC + 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 < 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 = load->outline.n_points - start_point; + zone->n_contours = 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. */ + /* */ + /*************************************************************************/ + + static + 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; + + + /* the following line sets the `error' variable through macros! */ + (void)( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) ); + + FT_TRACE5(( "Glyph %ld\n", glyph_index )); + return error; + } + + + static + void TT_Forget_Glyph_Frame( TT_Loader* loader ) + { + FT_Stream stream = loader->stream; + + + FORGET_Frame(); + } + + + static + 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 FT_Err_Ok; + } + + + static + 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_Ins; + goto Fail; + } + + if ( stream->cursor + n_ins > stream->limit ) + { + FT_TRACE0(( "ERROR: Instruction count mismatch!\n" )); + error = TT_Err_Too_Many_Ins; + 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 = n_points; + outline->n_contours = n_contours; + + Fail: + return error; + } + + + static + 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 = FILE_Pos() + stream->cursor - stream->limit; + } +#endif + + Fail: + return error; + } + + + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Process_Simple_Glyph */ + /* */ + /* */ + /* 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 = FT_Err_Ok; + + + 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 = FT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* load_truetype_glyph */ + /* */ + /* */ + /* 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 ) + { + FT_Stream stream = loader->stream; + FT_Error error; + TT_Face face = (TT_Face)loader->face; + FT_ULong offset; + FT_Int contours_count; + FT_UInt index, num_points, num_contours, count; + FT_Fixed x_scale, y_scale; + FT_ULong ins_offset; + 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_contours = 0; + num_points = 0; + ins_offset = 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; + } + + 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 = FT_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; + + 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; + } + } + } + + translate_array( num_new_points, loader->zone.cur, x, y ); + cur_to_org( num_new_points, &loader->zone ); + } + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + + /* 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_Ins; + } + + /* 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 = 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 x_scale, y_scale; + TT_GlyphSlot glyph = loader->glyph; + TT_Size size = (TT_Size)loader->size; + + + x_scale = 0x10000L; + y_scale = 0x10000L; + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + x_scale = size->root.metrics.x_scale; + 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->loader, loader->gloader ); + glyph->outline = glyph->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->advance; + + + /* 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 original vertical top 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 = face->os2.sTypoLineGap / 2; + advance_height = (FT_UShort)( face->os2.sTypoAscender - + face->os2.sTypoDescender + + face->os2.sTypoLineGap ); + } + else + { + top_bearing = 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, y_scale ); + top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale ) + - bbox.yMax; + advance = FT_MulFix( advance_height, y_scale ); + } + else + { + Top = top_bearing; + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Glyph */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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_Memory memory; + FT_Error error; + TT_Loader loader; + + + face = (TT_Face)glyph->face; + sfnt = (SFNT_Interface*)face->sfnt; + stream = face->root.stream; + memory = face->root.memory; + 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 */ + if ( size && + ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && + sfnt->load_sbits ) + { + TT_SBit_Metrics metrics; + + + error = sfnt->load_sbit_image( face, + size->root.metrics.x_ppem, + size->root.metrics.y_ppem, + 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/reactos/subsys/win32k/freetype/ttgload.h b/reactos/subsys/win32k/freetype/ttgload.h new file mode 100644 index 00000000000..2f3e96b7b04 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttgload.h @@ -0,0 +1,69 @@ +/***************************************************************************/ +/* */ +/* ttgload.h */ +/* */ +/* TrueType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ttobjs.h" + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include "ttinterp.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + void TT_Get_Metrics( TT_HoriHeader* header, + FT_UInt index, + FT_Short* bearing, + FT_UShort* advance ); + + LOCAL_DEF + void TT_Init_Glyph_Loading( TT_Face face ); + + LOCAL_DEF + FT_Error TT_Load_Glyph( TT_Size size, + TT_GlyphSlot glyph, + FT_UShort glyph_index, + FT_UInt load_flags ); + +#ifdef __cplusplus + } +#endif + +#endif /* TTGLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttinterp.c b/reactos/subsys/win32k/freetype/ttinterp.c new file mode 100644 index 00000000000..9dc0c190a70 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttinterp.c @@ -0,0 +1,7544 @@ +/***************************************************************************/ +/* */ +/* ttinterp.c */ +/* */ +/* TrueType bytecode interpreter (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttinterp.h" + +#else + +#include + +#endif + + +#include + + +#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 CALC_Length() \ + Calc_Length( 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 */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Goto_CodeRange */ + /* */ + /* */ + /* Switches to a new code range (updates the code related elements in */ + /* `exec', and `IP'). */ + /* */ + /* */ + /* range :: The new execution code range. */ + /* */ + /* IP :: The new IP in the new code range. */ + /* */ + /* */ + /* exec :: The target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Set_CodeRange */ + /* */ + /* */ + /* Sets a code range. */ + /* */ + /* */ + /* range :: The code range index. */ + /* */ + /* base :: The new code base. */ + /* */ + /* length :: The range size in bytes. */ + /* */ + /* */ + /* exec :: The target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Clear_CodeRange */ + /* */ + /* */ + /* Clears a code range. */ + /* */ + /* */ + /* range :: The code range index. */ + /* */ + /* */ + /* exec :: The target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Does not set the Error variable. */ + /* */ + LOCAL_FUNC + 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 */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Destroy_Context */ + /* */ + /* */ + /* Destroys a given context. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Init_Context */ + /* */ + /* */ + /* Initializes a context object. */ + /* */ + /* */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* face :: A handle to the source TrueType face object. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Update_Max */ + /* */ + /* */ + /* Checks the size of a buffer and reallocates it if necessary. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* size :: The address of the buffer's current size expressed */ + /* in elements. */ + /* */ + /* buff :: The address of the buffer base pointer. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Context */ + /* */ + /* */ + /* Prepare an execution context for glyph hinting. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* size :: A handle to the source size object. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Save_Context */ + /* */ + /* */ + /* Saves the code ranges in a `size' object. */ + /* */ + /* */ + /* exec :: A handle to the source execution context. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Run_Context */ + /* */ + /* */ + /* Executes one or more instructions in the execution context. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* TrueTyoe error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + 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 + }; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_New_Context */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* A handle to the execution context. Initialized for `face'. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + FT_EXPORT_FUNC( 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Context */ + /* */ + /* */ + /* Discards an execution context. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + FT_Error TT_Done_Context( TT_ExecContext exec ) + { + /* Nothing at all for now */ + FT_UNUSED( exec ); + + return TT_Err_Ok; + } + + +#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 ); + } + +#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 + + + /*************************************************************************/ + /* */ + /* */ + /* Current_Ratio */ + /* */ + /* */ + /* Returns the current aspect ratio scaling factor depending on the */ + /* projection vector's state and device resolutions. */ + /* */ + /* */ + /* 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; + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + 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 ); + +#else + + x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x8000 ); + y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x8000 ); + CUR.tt_metrics.ratio = FT_Sqrt32( x * x + y * y ) << 1; + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + } + + 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). */ + /* */ + /*************************************************************************/ + + + static + FT_F26Dot6 Read_CVT( EXEC_OP_ FT_ULong index ) + { + return CUR.cvt[index]; + } + + + static + FT_F26Dot6 Read_CVT_Stretched( EXEC_OP_ FT_ULong index ) + { + return TT_MULFIX( CUR.cvt[index], CURRENT_Ratio() ); + } + + + static + void Write_CVT( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] = value; + } + + + static + void Write_CVT_Stretched( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] = FT_DivFix( value, CURRENT_Ratio() ); + } + + + static + void Move_CVT( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] += value; + } + + + static + void Move_CVT_Stretched( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] += FT_DivFix( value, CURRENT_Ratio() ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* GetShortIns */ + /* */ + /* */ + /* Returns a short integer taken from the instruction stream at */ + /* address IP. */ + /* */ + /* */ + /* Short read at code[IP]. */ + /* */ + /* */ + /* 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] ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Ins_Goto_CodeRange */ + /* */ + /* */ + /* Goes to a certain code range in the instruction stream. */ + /* */ + /* */ + /* aRange :: The index of the code range. */ + /* */ + /* aIP :: The new IP address in the code range. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Direct_Move */ + /* */ + /* */ + /* Moves a point by a given distance along the freedom vector. The */ + /* point will be `touched'. */ + /* */ + /* */ + /* point :: The index of the point to move. */ + /* */ + /* distance :: The distance to apply. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_None */ + /* */ + /* */ + /* Does not round, but adds engine compensation. */ + /* */ + /* */ + /* distance :: The distance (not) to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* The compensated distance. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_To_Grid */ + /* */ + /* */ + /* Rounds value to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_To_Half_Grid */ + /* */ + /* */ + /* Rounds value to half grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Down_To_Grid */ + /* */ + /* */ + /* Rounds value down to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Up_To_Grid */ + /* */ + /* */ + /* Rounds value up to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_To_Double_Grid */ + /* */ + /* */ + /* Rounds value to double grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Super */ + /* */ + /* */ + /* Super-rounds value to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Super_45 */ + /* */ + /* */ + /* Super-rounds value to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Compute_Round */ + /* */ + /* */ + /* Sets the rounding mode. */ + /* */ + /* */ + /* 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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* SetSuperRound */ + /* */ + /* */ + /* Sets Super Round parameters. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Project */ + /* */ + /* */ + /* Computes the projection of vector given by (v2-v1) along the */ + /* current projection vector. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Dual_Project */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* current dual vector. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Free_Project */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* current freedom vector. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Project_x */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* horizontal axis. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Project_y */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* vertical axis. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Compute_Funcs */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Normalize */ + /* */ + /* */ + /* Norms a vector. */ + /* */ + /* */ + /* Vx :: The horizontal input vector coordinate. */ + /* Vy :: The vertical input vector coordinate. */ + /* */ + /* */ + /* R :: The normed unit vector. */ + /* */ + /* */ + /* Returns FAILURE if a vector parameter is zero. */ + /* */ + /* */ + /* 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_F26Dot6 u, v, d; + FT_Int shift; + FT_ULong H, L, L2, hi, lo, med; + + + u = ABS( Vx ); + v = ABS( Vy ); + + if ( u < v ) + { + d = u; + u = v; + v = d; + } + + R->x = 0; + R->y = 0; + + /* check that we are not trying to normalise zero! */ + if ( u == 0 ) + return SUCCESS; + + /* 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 */ + if ( H == 0 ) + { + shift = 0; + while ( ( L & 0xC0000000L ) == 0 ) + { + L <<= 2; + shift++; + } + + d = FT_Sqrt32( L ); + R->x = (FT_F2Dot14)TT_MULDIV( Vx << shift, 0x4000, d ); + R->y = (FT_F2Dot14)TT_MULDIV( Vy << shift, 0x4000, d ); + } + /* if the value is greater than 64-bits */ + else + { + shift = 0; + while ( H ) + { + L = ( L >> 2 ) | ( H << 30 ); + H >>= 2; + shift++; + } + + d = FT_Sqrt32( L ); + R->x = (FT_F2Dot14)TT_MULDIV( Vx >> shift, 0x4000, d ); + R->y = (FT_F2Dot14)TT_MULDIV( Vy >> shift, 0x4000, d ); + } + + { + FT_ULong x, y, w; + FT_Int sx, sy; + + + sx = R->x >= 0 ? 1 : -1; + sy = R->y >= 0 ? 1 : -1; + x = (FT_ULong)sx * R->x; + y = (FT_ULong)sy * R->y; + + w = x * x + y * y; + + /* we now want to adjust (x,y) in order to have sqrt(w) == 0x4000 */ + /* which means 0x1000000 <= w < 0x1004000 */ + while ( w <= 0x10000000L ) + { + /* increment the smallest coordinate */ + if ( x < y ) + x++; + else + y++; + + w = x * x + y * y; + } + + while ( w >= 0x10040000L ) + { + /* decrement the smallest coordinate */ + if ( x < y ) + x--; + else + y--; + + w = x * x + y * y; + } + + R->x = sx * x; + R->y = sy * y; + } + + 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 = ( nIfs == 1 ); + break; + + case 0x59: /* EIF */ + nIfs--; + Out = ( 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_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 = 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 = 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 = 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 ( 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. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_RunIns */ + /* */ + /* */ + /* Executes one or more instruction in the execution context. This */ + /* is the main function of the TrueType opcode interpreter. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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_FUNC( 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 = AA ^ (FT_Short)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 == 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/reactos/subsys/win32k/freetype/ttinterp.h b/reactos/subsys/win32k/freetype/ttinterp.h new file mode 100644 index 00000000000..6e92699cdca --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttinterp.h @@ -0,0 +1,278 @@ +/***************************************************************************/ +/* */ +/* ttinterp.h */ +/* */ +/* TrueType bytecode interpreter (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ttobjs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + +#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_UInt 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; + + + LOCAL_DEF + FT_Error TT_Goto_CodeRange( TT_ExecContext exec, + FT_Int range, + FT_Long IP ); + + LOCAL_DEF + FT_Error TT_Set_CodeRange( TT_ExecContext exec, + FT_Int range, + void* base, + FT_Long length ); + + LOCAL_DEF + FT_Error TT_Clear_CodeRange( TT_ExecContext exec, + FT_Int range ); + + FT_EXPORT_DEF( TT_ExecContext ) TT_New_Context( TT_Face face ); + + LOCAL_DEF + FT_Error TT_Done_Context( TT_ExecContext exec ); + + LOCAL_DEF + FT_Error TT_Destroy_Context( TT_ExecContext exec, + FT_Memory memory ); + + LOCAL_DEF + FT_Error TT_Load_Context( TT_ExecContext exec, + TT_Face face, + TT_Size size ); + + LOCAL_DEF + FT_Error TT_Save_Context( TT_ExecContext exec, + TT_Size ins ); + + LOCAL_DEF + FT_Error TT_Run_Context( TT_ExecContext exec, + FT_Bool debug ); + + FT_EXPORT_DEF( FT_Error ) TT_RunIns( TT_ExecContext exec ); + + +#ifdef __cplusplus + } +#endif + +#endif /* TTINTERP_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttload.c b/reactos/subsys/win32k/freetype/ttload.c new file mode 100644 index 00000000000..e7871874df1 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttload.c @@ -0,0 +1,1676 @@ +/***************************************************************************/ +/* */ +/* ttload.c */ +/* */ +/* Load the basic TrueType tables, i.e., tables that can be either in */ +/* TTF or OTF fonts (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.h" +#include "ttcmap.h" + +#else + +#include +#include + +#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_ttload + + + /*************************************************************************/ + /* */ + /* */ + /* TT_LookUp_Table */ + /* */ + /* */ + /* Looks for a TrueType table by name. */ + /* */ + /* */ + /* face :: A face object handle. */ + /* tag :: The searched tag. */ + /* */ + /* */ + /* A pointer to the table directory entry. 0 if not found. */ + /* */ + LOCAL_FUNC + 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'\n", + 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 ) + return entry; + } + + FT_TRACE3(( " Could not find table!\n" )); + return 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Goto_Table */ + /* */ + /* */ + /* Looks for a TrueType table by name, then seek a stream to it. */ + /* */ + /* */ + /* face :: A face object handle. */ + /* tag :: The searched tag. */ + /* stream :: The stream to seek when the table is found. */ + /* */ + /* */ + /* length :: The length of the table if found, undefined otherwise. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + + (void)FILE_Seek( table->Offset ); + } + else + error = TT_Err_Table_Missing; + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SFNT_Header */ + /* */ + /* */ + /* Loads the header of a SFNT font file. Supports collections. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* sfnt :: The SFNT header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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'. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_USHORT( SFNT_Header, num_tables ), + FT_FRAME_USHORT( SFNT_Header, search_range ), + FT_FRAME_USHORT( SFNT_Header, entry_selector ), + FT_FRAME_USHORT( SFNT_Header, range_shift ), + FT_FRAME_END + }; + + const FT_Frame_Field ttc_header_fields[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_LONG( TTC_Header, version ), + FT_FRAME_LONG( TTC_Header, 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 = TT_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 = FT_Err_Unknown_File_Format; + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Directory */ + /* */ + /* */ + /* Loads the table directory into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* sfnt :: The SFNT directory header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Any */ + /* */ + /* */ + /* Loads any font table into client memory. */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* buffer :: The address of target buffer. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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 = TT_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 TT_Err_Ok; + } + + if ( length ) + size = *length; + + stream = face->root.stream; + (void)FILE_Read_At( offset, buffer, size ); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Header */ + /* */ + /* */ + /* Loads the TrueType font header. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Header( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_Header* header; + + static const FT_Frame_Field header_fields[] = + { + FT_FRAME_START( 54 ), + FT_FRAME_ULONG( TT_Header, Table_Version ), + FT_FRAME_ULONG( TT_Header, Font_Revision ), + FT_FRAME_LONG( TT_Header, CheckSum_Adjust ), + FT_FRAME_LONG( TT_Header, Magic_Number ), + FT_FRAME_USHORT( TT_Header, Flags ), + FT_FRAME_USHORT( TT_Header, Units_Per_EM ), + FT_FRAME_LONG( TT_Header, Created[0] ), + FT_FRAME_LONG( TT_Header, Created[1] ), + FT_FRAME_LONG( TT_Header, Modified[0] ), + FT_FRAME_LONG( TT_Header, Modified[1] ), + FT_FRAME_SHORT( TT_Header, xMin ), + FT_FRAME_SHORT( TT_Header, yMin ), + FT_FRAME_SHORT( TT_Header, xMax ), + FT_FRAME_SHORT( TT_Header, yMax ), + FT_FRAME_USHORT( TT_Header, Mac_Style ), + FT_FRAME_USHORT( TT_Header, Lowest_Rec_PPEM ), + FT_FRAME_SHORT( TT_Header, Font_Direction ), + FT_FRAME_SHORT( TT_Header, Index_To_Loc_Format ), + FT_FRAME_SHORT( TT_Header, Glyph_Data_Format ), + FT_FRAME_END + }; + + + FT_TRACE2(( "Load_TT_Header: %08p\n", face )); + + error = face->goto_table( face, TTAG_head, stream, 0 ); + if ( error ) + { + FT_TRACE0(( "Font Header 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(( "Font Header Loaded.\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_MaxProfile */ + /* */ + /* */ + /* Loads the maximum profile into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 32 ), + FT_FRAME_ULONG( TT_MaxProfile, version ), + FT_FRAME_USHORT( TT_MaxProfile, numGlyphs ), + FT_FRAME_USHORT( TT_MaxProfile, maxPoints ), + FT_FRAME_USHORT( TT_MaxProfile, maxContours ), + FT_FRAME_USHORT( TT_MaxProfile, maxCompositePoints ), + FT_FRAME_USHORT( TT_MaxProfile, maxCompositeContours ), + FT_FRAME_USHORT( TT_MaxProfile, maxZones ), + FT_FRAME_USHORT( TT_MaxProfile, maxTwilightPoints ), + FT_FRAME_USHORT( TT_MaxProfile, maxStorage ), + FT_FRAME_USHORT( TT_MaxProfile, maxFunctionDefs ), + FT_FRAME_USHORT( TT_MaxProfile, maxInstructionDefs ), + FT_FRAME_USHORT( TT_MaxProfile, maxStackElements ), + FT_FRAME_USHORT( TT_MaxProfile, maxSizeOfInstructions ), + FT_FRAME_USHORT( TT_MaxProfile, maxComponentElements ), + FT_FRAME_USHORT( TT_MaxProfile, 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; + + /* 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.max_points = MAX( maxProfile->maxCompositePoints, + maxProfile->maxPoints ); + + face->root.max_contours = 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.max_points += 8; + face->root.max_contours += 4; + + FT_TRACE2(( "MAXP loaded.\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Metrics */ + /* */ + /* */ + /* Loads the horizontal or vertical metrics table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* */ + /* 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 = TT_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 = TT_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 ? TT_Err_Invalid_Vert_Metrics + : TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Metrics_Header */ + /* */ + /* */ + /* Loads the horizontal or vertical header in a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 36 ), + FT_FRAME_ULONG( TT_HoriHeader, Version ), + FT_FRAME_SHORT( TT_HoriHeader, Ascender ), + FT_FRAME_SHORT( TT_HoriHeader, Descender ), + FT_FRAME_SHORT( TT_HoriHeader, Line_Gap ), + FT_FRAME_USHORT( TT_HoriHeader, advance_Width_Max ), + FT_FRAME_SHORT( TT_HoriHeader, min_Left_Side_Bearing ), + FT_FRAME_SHORT( TT_HoriHeader, min_Right_Side_Bearing ), + FT_FRAME_SHORT( TT_HoriHeader, xMax_Extent ), + FT_FRAME_SHORT( TT_HoriHeader, caret_Slope_Rise ), + FT_FRAME_SHORT( TT_HoriHeader, caret_Slope_Run ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[0] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[1] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[2] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[3] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[4] ), + FT_FRAME_SHORT( TT_HoriHeader, metric_Data_Format ), + FT_FRAME_USHORT( TT_HoriHeader, 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 = TT_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 = TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Names */ + /* */ + /* */ + /* Loads the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 6 ), + FT_FRAME_USHORT( TT_NameTable, format ), + FT_FRAME_USHORT( TT_NameTable, numNameRecords ), + FT_FRAME_USHORT( TT_NameTable, storageOffset ), + FT_FRAME_END + }; + + const FT_Frame_Field name_record_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_USHORT( TT_NameRec, platformID ), + FT_FRAME_USHORT( TT_NameRec, encodingID ), + FT_FRAME_USHORT( TT_NameRec, languageID ), + FT_FRAME_USHORT( TT_NameRec, nameID ), + FT_FRAME_USHORT( TT_NameRec, stringLength ), + FT_FRAME_USHORT( TT_NameRec, 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 = TT_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; + + + (void)READ_Fields( name_record_fields, cur ); + + 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 < 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Names */ + /* */ + /* */ + /* Frees the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_CMap */ + /* */ + /* */ + /* Loads the cmap directory in a face object. The cmaps itselves are */ + /* loaded on demand in the `ttcmap.c' module. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 4 ), + FT_FRAME_USHORT( TT_CMapDir, tableVersionNumber ), + FT_FRAME_USHORT( TT_CMapDir, numCMaps ), + FT_FRAME_END + }; + + const FT_Frame_Field cmap_rec_fields[] = + { + FT_FRAME_START( 6 ), + FT_FRAME_USHORT( TT_CMapTable, format ), + FT_FRAME_USHORT( TT_CMapTable, length ), + FT_FRAME_USHORT( TT_CMapTable, version ), + FT_FRAME_END + }; + + + FT_TRACE2(( "CMaps " )); + + error = face->goto_table( face, TTAG_cmap, stream, 0 ); + if ( error ) + { + error = TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_OS2 */ + /* */ + /* */ + /* Loads the OS2 table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_OS2( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_OS2* os2; + + const FT_Frame_Field os2_fields[] = + { + FT_FRAME_START( 78 ), + FT_FRAME_USHORT( TT_OS2, version ), + FT_FRAME_SHORT( TT_OS2, xAvgCharWidth ), + FT_FRAME_USHORT( TT_OS2, usWeightClass ), + FT_FRAME_USHORT( TT_OS2, usWidthClass ), + FT_FRAME_SHORT( TT_OS2, fsType ), + FT_FRAME_SHORT( TT_OS2, ySubscriptXSize ), + FT_FRAME_SHORT( TT_OS2, ySubscriptYSize ), + FT_FRAME_SHORT( TT_OS2, ySubscriptXOffset ), + FT_FRAME_SHORT( TT_OS2, ySubscriptYOffset ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptXSize ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptYSize ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptXOffset ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptYOffset ), + FT_FRAME_SHORT( TT_OS2, yStrikeoutSize ), + FT_FRAME_SHORT( TT_OS2, yStrikeoutPosition ), + FT_FRAME_SHORT( TT_OS2, sFamilyClass ), + FT_FRAME_BYTE( TT_OS2, panose[0] ), + FT_FRAME_BYTE( TT_OS2, panose[1] ), + FT_FRAME_BYTE( TT_OS2, panose[2] ), + FT_FRAME_BYTE( TT_OS2, panose[3] ), + FT_FRAME_BYTE( TT_OS2, panose[4] ), + FT_FRAME_BYTE( TT_OS2, panose[5] ), + FT_FRAME_BYTE( TT_OS2, panose[6] ), + FT_FRAME_BYTE( TT_OS2, panose[7] ), + FT_FRAME_BYTE( TT_OS2, panose[8] ), + FT_FRAME_BYTE( TT_OS2, panose[9] ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange1 ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange2 ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange3 ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange4 ), + FT_FRAME_BYTE( TT_OS2, achVendID[0] ), + FT_FRAME_BYTE( TT_OS2, achVendID[1] ), + FT_FRAME_BYTE( TT_OS2, achVendID[2] ), + FT_FRAME_BYTE( TT_OS2, achVendID[3] ), + + FT_FRAME_USHORT( TT_OS2, fsSelection ), + FT_FRAME_USHORT( TT_OS2, usFirstCharIndex ), + FT_FRAME_USHORT( TT_OS2, usLastCharIndex ), + FT_FRAME_SHORT( TT_OS2, sTypoAscender ), + FT_FRAME_SHORT( TT_OS2, sTypoDescender ), + FT_FRAME_SHORT( TT_OS2, sTypoLineGap ), + FT_FRAME_USHORT( TT_OS2, usWinAscent ), + FT_FRAME_USHORT( TT_OS2, usWinDescent ), + FT_FRAME_END + }; + + const FT_Frame_Field os2_fields_extra[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_ULONG( TT_OS2, ulCodePageRange1 ), + FT_FRAME_ULONG( TT_OS2, ulCodePageRange2 ), + FT_FRAME_END + }; + + const FT_Frame_Field os2_fields_extra2[] = + { + FT_FRAME_START( 10 ), + FT_FRAME_SHORT( TT_OS2, sxHeight ), + FT_FRAME_SHORT( TT_OS2, sCapHeight ), + FT_FRAME_USHORT( TT_OS2, usDefaultChar ), + FT_FRAME_USHORT( TT_OS2, usBreakChar ), + FT_FRAME_USHORT( TT_OS2, 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 = TT_Err_Ok; + goto Exit; + } + + os2 = &face->os2; + + if ( READ_Fields( os2_fields, os2 ) ) + goto Exit; + + os2->ulCodePageRange1 = 0; + os2->ulCodePageRange2 = 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Postscript */ + /* */ + /* */ + /* Loads the Postscript table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + FT_FRAME_START( 32 ), + FT_FRAME_ULONG( TT_Postscript, FormatType ), + FT_FRAME_ULONG( TT_Postscript, italicAngle ), + FT_FRAME_SHORT( TT_Postscript, underlinePosition ), + FT_FRAME_SHORT( TT_Postscript, underlineThickness ), + FT_FRAME_ULONG( TT_Postscript, isFixedPitch ), + FT_FRAME_ULONG( TT_Postscript, minMemType42 ), + FT_FRAME_ULONG( TT_Postscript, maxMemType42 ), + FT_FRAME_ULONG( TT_Postscript, minMemType1 ), + FT_FRAME_ULONG( TT_Postscript, maxMemType1 ), + FT_FRAME_END + }; + + + FT_TRACE2(( "PostScript " )); + + error = face->goto_table( face, TTAG_post, stream, 0 ); + if ( error ) + return TT_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 TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_PCLT */ + /* */ + /* */ + /* Loads the PCL 5 Table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_PCLT( TT_Face face, + FT_Stream stream ) + { + static const FT_Frame_Field pclt_fields[] = + { + FT_FRAME_START( 54 ), + FT_FRAME_ULONG ( TT_PCLT, Version ), + FT_FRAME_ULONG ( TT_PCLT, FontNumber ), + FT_FRAME_USHORT( TT_PCLT, Pitch ), + FT_FRAME_USHORT( TT_PCLT, xHeight ), + FT_FRAME_USHORT( TT_PCLT, Style ), + FT_FRAME_USHORT( TT_PCLT, TypeFamily ), + FT_FRAME_USHORT( TT_PCLT, CapHeight ), + FT_FRAME_BYTES ( TT_PCLT, TypeFace, 16 ), + FT_FRAME_BYTES ( TT_PCLT, CharacterComplement, 8 ), + FT_FRAME_BYTES ( TT_PCLT, FileName, 6 ), + FT_FRAME_CHAR ( TT_PCLT, StrokeWeight ), + FT_FRAME_CHAR ( TT_PCLT, WidthType ), + FT_FRAME_BYTE ( TT_PCLT, SerifStyle ), + FT_FRAME_BYTE ( TT_PCLT, 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 TT_Err_Ok; + } + + if ( READ_Fields( pclt_fields, pclt ) ) + goto Exit; + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Gasp */ + /* */ + /* */ + /* Loads the `gasp' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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 TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Kern */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Kern( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_UInt n, num_tables, version; + + + /* the kern table is optional; exit silently if it is missing */ + error = face->goto_table( face, TTAG_kern, stream, 0 ); + if ( error ) + return TT_Err_Ok; + + if ( ACCESS_Frame( 4L ) ) + goto Exit; + + version = GET_UShort(); + 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; + + version = 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; + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Hdmx */ + /* */ + /* */ + /* Loads the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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 TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Hdmx */ + /* */ + /* */ + /* Frees the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/ttload.h b/reactos/subsys/win32k/freetype/ttload.h new file mode 100644 index 00000000000..dd0de6a4f1c --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttload.h @@ -0,0 +1,132 @@ +/***************************************************************************/ +/* */ +/* ttload.h */ +/* */ +/* Load the basic TrueType tables, i.e., tables that can be either in */ +/* TTF or OTF fonts (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + TT_Table* TT_LookUp_Table( TT_Face face, + FT_ULong tag ); + + LOCAL_DEF + FT_Error TT_Goto_Table( TT_Face face, + FT_ULong tag, + FT_Stream stream, + FT_ULong* length ); + + + LOCAL_DEF + FT_Error TT_Load_SFNT_Header( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header* sfnt ); + LOCAL_DEF + FT_Error TT_Load_Directory( TT_Face face, + FT_Stream stream, + SFNT_Header* sfnt ); + + LOCAL_DEF + FT_Error TT_Load_Any( TT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ); + + + LOCAL_DEF + FT_Error TT_Load_Header( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Metrics_Header( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + LOCAL_DEF + FT_Error TT_Load_CMap( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_MaxProfile( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Names( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_OS2( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_PostScript( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Hdmx( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + FT_Error TT_Load_PCLT( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void TT_Free_Names( TT_Face face ); + + + LOCAL_DEF + void TT_Free_Hdmx ( TT_Face face ); + + + LOCAL_DEF + FT_Error TT_Load_Kern( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Gasp( TT_Face face, + FT_Stream stream ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttobjs.c b/reactos/subsys/win32k/freetype/ttobjs.c new file mode 100644 index 00000000000..2ba715dc114 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttobjs.c @@ -0,0 +1,734 @@ +/***************************************************************************/ +/* */ +/* ttobjs.c */ +/* */ +/* Objects manager (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttgload.h" +#include "ttpload.h" + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include "ttinterp.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#include + + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* GLYPH ZONE FUNCTIONS */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_GlyphZone */ + /* */ + /* */ + /* Deallocates a glyph zone. */ + /* */ + /* */ + /* zone :: A pointer to the target glyph zone. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_New_GlyphZone */ + /* */ + /* */ + /* Allocates a new glyph zone. */ + /* */ + /* */ + /* memory :: A handle to the current memory object. */ + /* */ + /* maxPoints :: The capacity of glyph zone in points. */ + /* */ + /* maxContours :: The capacity of glyph zone in contours. */ + /* */ + /* */ + /* zone :: A pointer to the target glyph zone record. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Face */ + /* */ + /* */ + /* Initializes a given TrueType face object. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + 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; + + 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 = FT_Err_Unknown_File_Format; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Face */ + /* */ + /* */ + /* Finalizes a given face object. */ + /* */ + /* */ + /* face :: A pointer to the face object to destroy. */ + /* */ + 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 */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Size */ + /* */ + /* */ + /* Initializes a new TrueType size object. */ + /* */ + /* */ + /* size :: A handle to the size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + 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: + +#endif + + TT_Done_Size( size ); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Size */ + /* */ + /* */ + /* The TrueType size object finalizer. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Reset_Size */ + /* */ + /* */ + /* Resets a TrueType size when resolutions and character dimensions */ + /* have been changed. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_DEF + FT_Error TT_Reset_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_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 < 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 < 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Driver */ + /* */ + /* */ + /* Initializes a given TrueType driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Driver */ + /* */ + /* */ + /* Finalizes a given TrueType driver. */ + /* */ + /* */ + /* driver :: A handle to the target TrueType driver. */ + /* */ + LOCAL_FUNC + 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; + } + +#endif + + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttobjs.h b/reactos/subsys/win32k/freetype/ttobjs.h new file mode 100644 index 00000000000..3e55de3cb17 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttobjs.h @@ -0,0 +1,412 @@ +/***************************************************************************/ +/* */ +/* ttobjs.h */ +/* */ +/* Objects manager (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Driver */ + /* */ + /* */ + /* A handle to a TrueType driver object. */ + /* */ + typedef struct TT_DriverRec_* TT_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Instance */ + /* */ + /* */ + /* A handle to a TrueType size object. */ + /* */ + typedef struct TT_SizeRec_* TT_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GlyphSlot */ + /* */ + /* */ + /* A handle to a TrueType glyph slot object. */ + /* */ + /* */ + /* This is a direct typedef of FT_GlyphSlot, as there is nothing */ + /* specific about the TrueType glyph slot. */ + /* */ + typedef FT_GlyphSlot TT_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GraphicsState */ + /* */ + /* */ + /* 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; + + + LOCAL_DEF void TT_Done_GlyphZone( TT_GlyphZone* zone ); + + LOCAL_DEF FT_Error TT_New_GlyphZone( FT_Memory memory, + FT_UShort maxPoints, + FT_Short maxContours, + TT_GlyphZone* zone ); + + + /*************************************************************************/ + /* */ + /* 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_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 */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void TT_Done_Face( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* Size functions */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Size( TT_Size size ); + + LOCAL_DEF + void TT_Done_Size( TT_Size size ); + + LOCAL_DEF + FT_Error TT_Reset_Size( TT_Size size ); + + + /*************************************************************************/ + /* */ + /* Driver functions */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Driver( TT_Driver driver ); + + LOCAL_DEF + void TT_Done_Driver( TT_Driver driver ); + + +#ifdef __cplusplus + } +#endif + +#endif /* TTOBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttpload.c b/reactos/subsys/win32k/freetype/ttpload.c new file mode 100644 index 00000000000..d82dd45bea6 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttpload.c @@ -0,0 +1,273 @@ +/***************************************************************************/ +/* */ +/* ttpload.h */ +/* */ +/* TrueType glyph data/program tables loader (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include +#include + +#ifdef FT_FLAT_COMPILE +#include "ttpload.h" +#else +#include +#endif + +#include + + + /*************************************************************************/ + /* */ + /* 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 + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Locations */ + /* */ + /* */ + /* Loads the locations table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_CVT */ + /* */ + /* */ + /* Loads the control value table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Progams */ + /* */ + /* */ + /* Loads the font program and the cvt program. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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/reactos/subsys/win32k/freetype/ttpload.h b/reactos/subsys/win32k/freetype/ttpload.h new file mode 100644 index 00000000000..77802a6424a --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttpload.h @@ -0,0 +1,51 @@ +/***************************************************************************/ +/* */ +/* ttpload.h */ +/* */ +/* TrueType glyph data/program tables loader (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error TT_Load_Locations( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + FT_Error TT_Load_CVT( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + FT_Error TT_Load_Programs( TT_Face face, + FT_Stream stream ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTPLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttpost.c b/reactos/subsys/win32k/freetype/ttpost.c new file mode 100644 index 00000000000..c83205baed7 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttpost.c @@ -0,0 +1,536 @@ +/***************************************************************************/ +/* */ +/* ttpost.c */ +/* */ +/* Postcript name table processing for TrueType and OpenType fonts */ +/* (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttpost.h" +#include "ttload.h" + +#else + +#include +#include + +#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_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 + +#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_Int 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 = TT_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 = index; + } + } + } + + /* now load the name strings */ + { + FT_Int 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 = num_glyphs; + table->num_names = num_names; + table->glyph_indices = glyph_indices; + table->glyph_names = name_strings; + } + return TT_Err_Ok; + + + Fail1: + { + FT_Int 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 = TT_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 = TT_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 = num_glyphs; + table->offsets = offset_table; + } + + return TT_Err_Ok; + + Fail: + FREE( offset_table ); + + Exit: + return error; + } + + + static + FT_Error Load_Post_Names( TT_Face face ) + { + FT_Stream stream; + FT_Error error; + + /* 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; + + /* now read postscript table */ + switch ( face->postscript.FormatType ) + { + case 0x00020000L: + error = Load_Format_20( face, stream ); + break; + + case 0x00028000L: + error = Load_Format_25( face, stream ); + break; + + default: + error = TT_Err_Invalid_File_Format; + } + + face->postscript_names.loaded = 1; + + Exit: + return error; + } + + + LOCAL_FUNC + 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_UInt 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_PS_Name */ + /* */ + /* */ + /* Gets the PostScript glyph name of a glyph. */ + /* */ + /* */ + /* 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! */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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 TT_Err_Invalid_Face_Handle; + + if ( index >= (FT_UInt)face->root.num_glyphs ) + return TT_Err_Invalid_Glyph_Index; + +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + psnames = (PSNames_Interface*)face->psnames; + if ( !psnames ) + return TT_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 < 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 < table->num_glyphs ) /* paranoid checking */ + { + index += table->offsets[index]; + *PSname = MAC_NAME( index ); + } + } + break; + + case 0x00030000L: + break; /* nothing to do */ + } + + return TT_Err_Ok; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttpost.h b/reactos/subsys/win32k/freetype/ttpost.h new file mode 100644 index 00000000000..e3da83606d0 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttpost.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ttpost.h */ +/* */ +/* Postcript name table processing for TrueType and OpenType fonts */ +/* (specification). */ +/* */ +/* Copyright 1996-2000 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 +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +#define TT_Err_Invalid_Post_Table_Format 0x0B00 +#define TT_Err_Invalid_Post_Table 0x0B01 + + + LOCAL_DEF + FT_Error TT_Get_PS_Name( TT_Face face, + FT_UInt index, + FT_String** PSname ); + + LOCAL_DEF + void TT_Free_Post_Names( TT_Face face ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTPOST_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/ttsbit.c b/reactos/subsys/win32k/freetype/ttsbit.c new file mode 100644 index 00000000000..9a5455afb8d --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttsbit.c @@ -0,0 +1,1444 @@ +/***************************************************************************/ +/* */ +/* ttsbit.c */ +/* */ +/* TrueType and OpenType embedded bitmap support (body). */ +/* */ +/* Copyright 1996-2000 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 +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttsbit.h" + +#else + +#include + +#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_ttsbit + + + /*************************************************************************/ + /* */ + /* */ + /* blit_sbit */ + /* */ + /* */ + /* Blits a bitmap from an input stream into a given target. Supports */ + /* x and y offsets as well as byte padded lines. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* 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_Byte 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 = x_offset & 7; /* current write shift */ + FT_Byte space = 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 ( loaded < count ) + { + acc |= (FT_UShort)*source++ << ( 8 - loaded ); + loaded += 8; + } + + /* now write remaining bits */ + val = ( (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 = loaded = 0; /* clear accumulator on byte-padded lines */ + + line_buff += line_incr; + } + } + + + const FT_Frame_Field sbit_metrics_fields[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_BYTE( TT_SBit_Metrics, height ), + FT_FRAME_BYTE( TT_SBit_Metrics, width ), + + FT_FRAME_CHAR( TT_SBit_Metrics, horiBearingX ), + FT_FRAME_CHAR( TT_SBit_Metrics, horiBearingY ), + FT_FRAME_BYTE( TT_SBit_Metrics, horiAdvance ), + + FT_FRAME_CHAR( TT_SBit_Metrics, vertBearingX ), + FT_FRAME_CHAR( TT_SBit_Metrics, vertBearingY ), + FT_FRAME_BYTE( TT_SBit_Metrics, vertAdvance ), + FT_FRAME_END + }; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Const_Metrics */ + /* */ + /* */ + /* Loads the metrics for `EBLC' index tables format 2 and 5. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* 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 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Range_Codes */ + /* */ + /* */ + /* Loads the range codes for `EBLC' index tables format 4 and 5. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* load_offsets :: A flag whether to load the glyph offset table. */ + /* */ + /* */ + /* 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Range */ + /* */ + /* */ + /* Loads a given `EBLC' index/range table. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* 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 = ( 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 = TT_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Strikes */ + /* */ + /* */ + /* Loads the table of embedded bitmap sizes for this face. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + 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[] = + { + /* no FT_FRAME_START */ + FT_FRAME_CHAR( TT_SBit_Line_Metrics, ascender ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, descender ), + FT_FRAME_BYTE( TT_SBit_Line_Metrics, max_width ), + + FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_slope_numerator ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_slope_denominator ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_offset ), + + FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_origin_SB ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_advance_SB ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, max_before_BL ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_after_BL ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, pads[0] ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, pads[1] ), + FT_FRAME_END + }; + + const FT_Frame_Field strike_start_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_ULONG( TT_SBit_Strike, ranges_offset ), + FT_FRAME_SKIP_LONG, + FT_FRAME_ULONG( TT_SBit_Strike, num_ranges ), + FT_FRAME_ULONG( TT_SBit_Strike, color_ref ), + FT_FRAME_END + }; + + const FT_Frame_Field strike_end_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_USHORT( TT_SBit_Strike, start_glyph ), + FT_FRAME_USHORT( TT_SBit_Strike, end_glyph ), + FT_FRAME_BYTE ( TT_SBit_Strike, x_ppem ), + FT_FRAME_BYTE ( TT_SBit_Strike, y_ppem ), + FT_FRAME_BYTE ( TT_SBit_Strike, bit_depth ), + FT_FRAME_CHAR ( TT_SBit_Strike, 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 ) + { + error = 0; + 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 = TT_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 ) + { + (void)READ_Fields( strike_start_fields, strike ); + + (void)READ_Fields( sbit_line_metrics_fields, &strike->hori ); + (void)READ_Fields( sbit_line_metrics_fields, &strike->vert ); + + (void)READ_Fields( strike_end_fields, strike ); + + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_SBit_Strikes */ + /* */ + /* */ + /* Releases the embedded bitmap tables. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + LOCAL_FUNC + 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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Find_SBit_Range */ + /* */ + /* */ + /* Scans a given strike's ranges and return, for a given glyph */ + /* index, the corresponding sbit range, and `EBDT' offset. */ + /* */ + /* */ + /* glyph_index :: The glyph index. */ + /* strike :: The source/current sbit strike. */ + /* */ + /* */ + /* arange :: The sbit range containing the glyph index. */ + /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ + /* */ + /* */ + /* 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 < strike->start_glyph || + glyph_index > 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 >= range->first_glyph && + glyph_index <= range->last_glyph ) + { + FT_UShort delta = 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 ( 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 TT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Find_SBit_Image */ + /* */ + /* */ + /* Checks whether an embedded bitmap (an `sbit') exists for a given */ + /* glyph, at given x and y ppems. */ + /* */ + /* */ + /* face :: The target face object. */ + /* glyph_index :: The glyph index. */ + /* x_ppem :: The horizontal resolution in points per EM. */ + /* y_ppem :: The vertical resolution in points per EM. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. Returns */ + /* TT_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_Int x_ppem, + FT_Int y_ppem, + + TT_SBit_Range** arange, + TT_SBit_Strike** astrike, + FT_ULong* aglyph_offset ) + { + TT_SBit_Strike* strike = face->sbit_strikes; + TT_SBit_Strike* strike_limit = strike + face->num_sbit_strikes; + + + if ( !strike ) + goto Fail; + + for ( ; strike < strike_limit; strike++ ) + { + if ( strike->x_ppem == x_ppem && strike->y_ppem == y_ppem ) + { + FT_Error error; + + + error = Find_SBit_Range( glyph_index, strike, + arange, aglyph_offset ); + if ( error ) + goto Fail; + + *astrike = strike; + + return TT_Err_Ok; + } + } + + Fail: + /* no embedded bitmap for this glyph in face */ + *arange = 0; + *astrike = 0; + *aglyph_offset = 0; + + return TT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Load_SBit_Metrics */ + /* */ + /* */ + /* Gets the big metrics for a given SBit. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* range :: The SBit range containing the glyph. */ + /* */ + /* */ + /* big_metrics :: A big SBit metrics structure for the glyph. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 = TT_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[] = + { + FT_FRAME_START( 5 ), + FT_FRAME_BYTE( TT_SBit_Small_Metrics, height ), + FT_FRAME_BYTE( TT_SBit_Small_Metrics, width ), + FT_FRAME_CHAR( TT_SBit_Small_Metrics, bearingX ), + FT_FRAME_CHAR( TT_SBit_Small_Metrics, bearingY ), + FT_FRAME_BYTE( TT_SBit_Small_Metrics, 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 */ + (void)READ_Fields( sbit_metrics_fields, metrics ); + break; + + case 5: + default: /* constant metrics */ + if ( range->index_format == 2 || range->index_format == 5 ) + *metrics = range->metrics; + else + return TT_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Crop_Bitmap */ + /* */ + /* */ + /* Crops a bitmap to its tightest bounding box, and adjusts its */ + /* metrics. */ + /* */ + /* */ + /* image :: The input glyph slot. */ + /* */ + /* 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 -= count; + metrics->horiBearingY -= count; + 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 -= 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 = cur[0] << 1; + for ( n = 8; n < width; n += 8 ) + { + FT_Byte val; + + + val = cur[1]; + cur[0] = old | ( val >> 7 ); + old = 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 = 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 = TT_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 TT_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 TT_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 TT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Image */ + /* */ + /* */ + /* Loads a given glyph sbit image from the font resource. This also */ + /* returns its metrics. */ + /* */ + /* */ + /* 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. */ + /* */ + /* load_flags :: The glyph load flags (the code checks for the flag */ + /* FT_LOAD_CROP_BITMAP */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* map :: The target pixmap. */ + /* */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* */ + /* FreeType error code. 0 means success. Returns an error if no */ + /* glyph sbit exists for the index. */ + /* */ + /* */ + /* The `map.buffer' field is always freed before the glyph is loaded. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_SBit_Image( TT_Face face, + FT_Int x_ppem, + FT_Int y_ppem, + 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, x_ppem, y_ppem, + &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; + FT_Int top; + + + advance = strike->hori.ascender - strike->hori.descender; + top = advance / 10; + + /* some heuristic values */ + + metrics->vertBearingX = -metrics->width / 2; + metrics->vertBearingY = advance / 10; + metrics->vertAdvance = 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/reactos/subsys/win32k/freetype/ttsbit.h b/reactos/subsys/win32k/freetype/ttsbit.h new file mode 100644 index 00000000000..e77de538720 --- /dev/null +++ b/reactos/subsys/win32k/freetype/ttsbit.h @@ -0,0 +1,65 @@ +/***************************************************************************/ +/* */ +/* ttsbit.h */ +/* */ +/* TrueType and OpenType embedded bitmap support (specification). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error TT_Load_SBit_Strikes( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void TT_Free_SBit_Strikes( TT_Face face ); + + LOCAL_DEF + FT_Error TT_Load_SBit_Image( TT_Face face, + FT_Int x_ppem, + FT_Int y_ppem, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTSBIT_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/type1.c b/reactos/subsys/win32k/freetype/type1.c new file mode 100644 index 00000000000..e2e1ca22a96 --- /dev/null +++ b/reactos/subsys/win32k/freetype/type1.c @@ -0,0 +1,61 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* type1.c */ +/* */ +/* FreeType Type 1 driver component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "t1driver.c" +#include "t1objs.c" +#include "t1load.c" +#include "t1gload.c" +#include "t1tokens.c" +#include "t1parse.c" + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include "t1hinter.c" +#endif + +#ifndef T1_CONFIG_OPTION_NO_AFM +#include "t1afm.c" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include +#include +#include +#include + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + +#ifndef T1_CONFIG_OPTION_NO_AFM +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/type1cid.c b/reactos/subsys/win32k/freetype/type1cid.c new file mode 100644 index 00000000000..57f3b03a141 --- /dev/null +++ b/reactos/subsys/win32k/freetype/type1cid.c @@ -0,0 +1,42 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* cff.c */ +/* */ +/* FreeType OpenType driver component (body only). */ +/* */ +/* Copyright 1996-2000 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 + +#ifdef FT_FLAT_COMPILE + +#include "cidparse.c" +#include "cidload.c" +#include "cidobjs.c" +#include "cidriver.c" +#include "cidgload.c" + +#else + +#include +#include +#include +#include +#include + +#endif + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/type1z.c b/reactos/subsys/win32k/freetype/type1z.c new file mode 100644 index 00000000000..b784f0e7f41 --- /dev/null +++ b/reactos/subsys/win32k/freetype/type1z.c @@ -0,0 +1,51 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* type1z.c */ +/* */ +/* FreeType experimental Type 1 driver component (body only). */ +/* */ +/* Copyright 1996-2000 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 + + +#ifdef FT_FLAT_COMPILE + +#include "z1parse.c" +#include "z1load.c" +#include "z1objs.c" +#include "z1driver.c" +#include "z1gload.c" + +#ifndef Z1_CONFIG_OPTION_NO_AFM +#include "z1afm.c" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include +#include +#include + +#ifndef Z1_CONFIG_OPTION_NO_AFM +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/winfnt.c b/reactos/subsys/win32k/freetype/winfnt.c new file mode 100644 index 00000000000..8a8603ed083 --- /dev/null +++ b/reactos/subsys/win32k/freetype/winfnt.c @@ -0,0 +1,625 @@ +#define FT_FLAT_COMPILE + +/***************************************************************************/ +/* */ +/* winfnt.c */ +/* */ +/* FreeType font driver for Windows FNT/FON files */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "winfnt.h" + +#else + +#include + +#endif + + +#include +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* 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[] = + { + FT_FRAME_START( 64 ), + FT_FRAME_USHORT_LE ( WinMZ_Header, magic ), + FT_FRAME_SKIP_BYTES( 29 * 2 ), + FT_FRAME_ULONG_LE ( WinMZ_Header, lfanew ), + FT_FRAME_END + }; + + static + const FT_Frame_Field winne_header_fields[] = + { + FT_FRAME_START( 40 ), + FT_FRAME_USHORT_LE ( WinNE_Header, magic ), + FT_FRAME_SKIP_BYTES( 34 ), + FT_FRAME_USHORT_LE ( WinNE_Header, resource_tab_offset ), + FT_FRAME_USHORT_LE ( WinNE_Header, rname_tab_offset ), + FT_FRAME_END + }; + + static + const FT_Frame_Field winfnt_header_fields[] = + { + FT_FRAME_START( 134 ), + FT_FRAME_USHORT_LE( WinFNT_Header, version ), + FT_FRAME_ULONG_LE ( WinFNT_Header, file_size ), + FT_FRAME_BYTES ( WinFNT_Header, copyright, 60 ), + FT_FRAME_USHORT_LE( WinFNT_Header, file_type ), + FT_FRAME_USHORT_LE( WinFNT_Header, nominal_point_size ), + FT_FRAME_USHORT_LE( WinFNT_Header, vertical_resolution ), + FT_FRAME_USHORT_LE( WinFNT_Header, horizontal_resolution ), + FT_FRAME_USHORT_LE( WinFNT_Header, ascent ), + FT_FRAME_USHORT_LE( WinFNT_Header, internal_leading ), + FT_FRAME_USHORT_LE( WinFNT_Header, external_leading ), + FT_FRAME_BYTE ( WinFNT_Header, italic ), + FT_FRAME_BYTE ( WinFNT_Header, underline ), + FT_FRAME_BYTE ( WinFNT_Header, strike_out ), + FT_FRAME_USHORT_LE( WinFNT_Header, weight ), + FT_FRAME_BYTE ( WinFNT_Header, charset ), + FT_FRAME_USHORT_LE( WinFNT_Header, pixel_width ), + FT_FRAME_USHORT_LE( WinFNT_Header, pixel_height ), + FT_FRAME_BYTE ( WinFNT_Header, pitch_and_family ), + FT_FRAME_USHORT_LE( WinFNT_Header, avg_width ), + FT_FRAME_USHORT_LE( WinFNT_Header, max_width ), + FT_FRAME_BYTE ( WinFNT_Header, first_char ), + FT_FRAME_BYTE ( WinFNT_Header, last_char ), + FT_FRAME_BYTE ( WinFNT_Header, default_char ), + FT_FRAME_BYTE ( WinFNT_Header, break_char ), + FT_FRAME_USHORT_LE( WinFNT_Header, bytes_per_row ), + FT_FRAME_ULONG_LE ( WinFNT_Header, device_offset ), + FT_FRAME_ULONG_LE ( WinFNT_Header, face_name_offset ), + FT_FRAME_ULONG_LE ( WinFNT_Header, bits_pointer ), + FT_FRAME_ULONG_LE ( WinFNT_Header, bits_offset ), + FT_FRAME_BYTE ( WinFNT_Header, reserved ), + FT_FRAME_ULONG_LE ( WinFNT_Header, flags ), + FT_FRAME_USHORT_LE( WinFNT_Header, A_space ), + FT_FRAME_USHORT_LE( WinFNT_Header, B_space ), + FT_FRAME_USHORT_LE( WinFNT_Header, C_space ), + FT_FRAME_USHORT_LE( WinFNT_Header, color_table_offset ), + FT_FRAME_BYTES ( WinFNT_Header, reserved, 4 ), + FT_FRAME_END + }; + + + static + void fnt_done_font( FT_Stream stream, + FNT_Font* font ) + { + if ( font->fnt_frame ) + RELEASE_Frame( font->fnt_frame ); + + font->fnt_size = 0; + font->fnt_frame = 0; + } + + + static + FT_Error fnt_load_font( FT_Stream stream, + FNT_Font* font ) + { + 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 = FT_Err_Unknown_File_Format; + goto Exit; + } + + if ( header->file_type & 1 ) + { + FT_TRACE2(( "can't handle vector FNT fonts\n" )); + error = FT_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_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_done_font( stream, cur ); + + FREE( face->fonts ); + face->num_fonts = 0; + } + + static + FT_Error fnt_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 = FT_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 = FT_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 = 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 = FT_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_load_font( stream, cur ); + if ( error ) + goto Fail; + } + } + } + } + + Fail: + if ( error ) + fnt_done_fonts( face ); + + Exit: + return error; + } + + + static + void FNT_Done_Face( FNT_Face face ) + { + FT_Memory memory = FT_FACE_MEMORY( face ); + + + fnt_done_fonts( face ); + + FREE( face->root.available_sizes ); + face->root.num_fixed_sizes = 0; + } + + + static + FT_Error FNT_Init_Face( 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_get_dll_fonts( face ); + if ( error ) + { + /* this didn't work, now try to load a single FNT font */ + FT_Memory memory = FT_FACE_MEMORY( face ); + 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_load_font( stream, font ); + 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 = "Regular"; + + if ( root->style_flags & FT_STYLE_FLAG_BOLD ) + { + if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) + root->style_name = "Bold Italic"; + else + root->style_name = "Bold"; + } + else if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) + root->style_name = "Italic"; + } + + Fail: + if ( error ) + FNT_Done_Face( face ); + + Exit: + return error; + } + + + static + FT_Error FNT_Set_Pixel_Size( 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 ? FT_Err_Ok : FT_Err_Invalid_Argument ); + } + + + static + FT_UInt FNT_Get_Char_Index( FT_CharMap charmap, + FT_ULong char_code ) + { + FT_UInt result = char_code; + + + if ( charmap ) + { + FNT_Font* font = ((FNT_Face)charmap->face)->fonts; + FT_UInt first = font->header.first_char; + FT_UInt 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 = FT_Err_Invalid_Argument; + goto Exit; + } + + if ( glyph_index > 0 ) + glyph_index--; + else + glyph_index = font->header.default_char - font->header.first_char; + + new_format = 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; + + Exit: + return error; + } + + + 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_Init_Face, + (FTDriver_doneFace) FNT_Done_Face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) FNT_Set_Pixel_Size, + (FTDriver_setPixelSizes)FNT_Set_Pixel_Size, + + (FTDriver_loadGlyph) FNT_Load_Glyph, + (FTDriver_getCharIndex) FNT_Get_Char_Index, + + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, + (FTDriver_getAdvances) 0 + }; + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/winfnt.h b/reactos/subsys/win32k/freetype/winfnt.h new file mode 100644 index 00000000000..eaf308b875b --- /dev/null +++ b/reactos/subsys/win32k/freetype/winfnt.h @@ -0,0 +1,150 @@ +/***************************************************************************/ +/* */ +/* winfnt.h */ +/* */ +/* FreeType font driver for Windows FNT/FON files */ +/* */ +/* Copyright 1996-2000 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 + + + 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_EXPORT_VAR( const FT_Driver_Class ) winfnt_driver_class; + + +#endif /* WINFNT_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/z1afm.c b/reactos/subsys/win32k/freetype/z1afm.c new file mode 100644 index 00000000000..b329cd347f3 --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1afm.c @@ -0,0 +1,293 @@ +/***************************************************************************/ +/* */ +/* z1afm.c */ +/* */ +/* AFM support for Type 1 fonts (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "z1afm.h" + +#else + +#include + +#endif + + +#include +#include + +#include /* for qsort() */ +#include /* for strcmp() */ +#include /* 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_z1afm + + + LOCAL_FUNC + void Z1_Done_AFM( FT_Memory memory, + Z1_AFM* afm ) + { + FREE( afm->kern_pairs ); + afm->num_pairs = 0; + } + + +#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 = 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 */ + static + int compare_kern_pairs( const void* a, + const void* b ) + { + Z1_Kern_Pair* pair1 = (Z1_Kern_Pair*)a; + Z1_Kern_Pair* pair2 = (Z1_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 */ + LOCAL_FUNC + FT_Error Z1_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; + Z1_Kern_Pair* pair; + T1_Font* type1 = &((T1_Face)t1_face)->type1; + Z1_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, Z1_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; + + 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 ( Z1_Kern_Pair ), + compare_kern_pairs ); + + Exit: + if ( error ) + FREE( afm ); + + FORGET_Frame(); + + return error; + } + + + /* find the kerning for a given glyph pair */ + LOCAL_FUNC + void Z1_Get_Kerning( Z1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + Z1_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/reactos/subsys/win32k/freetype/z1afm.h b/reactos/subsys/win32k/freetype/z1afm.h new file mode 100644 index 00000000000..bfacce71358 --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1afm.h @@ -0,0 +1,79 @@ +/***************************************************************************/ +/* */ +/* z1afm.h */ +/* */ +/* AFM support for Type 1 fonts (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1AFM_H +#define Z1AFM_H + + +#ifdef FT_FLAT_COMPILE + +#include "z1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct Z1_Kern_Pair_ + { + FT_UInt glyph1; + FT_UInt glyph2; + FT_Vector kerning; + + } Z1_Kern_Pair; + + + typedef struct Z1_AFM_ + { + FT_Int num_pairs; + Z1_Kern_Pair* kern_pairs; + + } Z1_AFM; + + + LOCAL_DEF + FT_Error Z1_Read_AFM( FT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void Z1_Done_AFM( FT_Memory memory, + Z1_AFM* afm ); + + LOCAL_DEF + void Z1_Get_Kerning( Z1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* Z1AFM_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/z1driver.c b/reactos/subsys/win32k/freetype/z1driver.c new file mode 100644 index 00000000000..aea2c10f1f7 --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1driver.c @@ -0,0 +1,340 @@ +/***************************************************************************/ +/* */ +/* z1driver.c */ +/* */ +/* Experimental Type 1 driver interface (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "z1driver.h" +#include "z1gload.h" +#include "z1load.h" +#include "z1afm.h" + +#else + +#include +#include +#include +#include + +#endif + + +#include +#include +#include + +#include /* 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_z1driver + + + static + FT_Error get_z1_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 = strlen( gname ); + + + if (len >= buffer_max) + len = buffer_max - 1; + + MEM_Copy( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Interface */ + /* */ + /* */ + /* 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). */ + /* */ + /* */ + /* driver :: A handle to a driver object. */ + /* */ + /* */ + /* interface :: A string designing the interface. Examples are */ + /* `sfnt', `post_names', `charmaps', etc. */ + /* */ + /* */ + /* 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)get_z1_glyph_name; + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + if ( strcmp( (const char*)interface, "get_mm" ) == 0 ) + return (FT_Module_Interface)Z1_Get_Multi_Master; + + if ( strcmp( (const char*)interface, "set_mm_design") == 0 ) + return (FT_Module_Interface)Z1_Set_MM_Design; + + if ( strcmp( (const char*)interface, "set_mm_blend") == 0 ) + return (FT_Module_Interface)Z1_Set_MM_Blend; +#endif + return 0; + } + + +#ifndef Z1_CONFIG_OPTION_NO_AFM + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* 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 ) + { + Z1_AFM* afm; + + + kerning->x = 0; + kerning->y = 0; + + afm = (Z1_AFM*)face->afm_data; + if ( afm ) + Z1_Get_Kerning( afm, left_glyph, right_glyph, kerning ); + + return T1_Err_Ok; + } + + +#endif /* T1_CONFIG_OPTION_NO_AFM */ + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* 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; + } + + + 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)Z1_Init_Driver, + (FT_Module_Destructor) Z1_Done_Driver, + (FT_Module_Requester) Get_Interface, + }, + + sizeof( T1_FaceRec ), + sizeof( Z1_SizeRec ), + sizeof( Z1_GlyphSlotRec ), + + (FTDriver_initFace) Z1_Init_Face, + (FTDriver_doneFace) Z1_Done_Face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) 0, + (FTDriver_setPixelSizes)0, + (FTDriver_loadGlyph) Z1_Load_Glyph, + (FTDriver_getCharIndex) Get_Char_Index, + +#ifdef Z1_CONFIG_OPTION_NO_AFM + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, +#else + (FTDriver_getKerning) Get_Kerning, + (FTDriver_attachFile) Z1_Read_AFM, +#endif + (FTDriver_getAdvances) 0 + }; + + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void ) + { + return &t1z_driver_class; + } + +#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/z1driver.h b/reactos/subsys/win32k/freetype/z1driver.h new file mode 100644 index 00000000000..08bd544d566 --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1driver.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* z1driver.h */ +/* */ +/* High-level experimental Type 1 driver interface (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1DRIVER_H +#define Z1DRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Driver_Class ) t1_driver_class; + +#endif /* Z1DRIVER_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/z1gload.c b/reactos/subsys/win32k/freetype/z1gload.c new file mode 100644 index 00000000000..0b25d2ecc75 --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1gload.c @@ -0,0 +1,1482 @@ +/***************************************************************************/ +/* */ +/* z1gload.c */ +/* */ +/* Experimental Type 1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 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. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "z1gload.h" + +#else + +#include + +#endif + + +#include +#include +#include + +#include /* 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_z1gload + + + typedef enum Z1_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 */ + + } Z1_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 */ + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + LOCAL_FUNC + void Z1_Init_Builder( Z1_Builder* builder, + T1_Face face, + Z1_Size size, + Z1_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.loader; + + + builder->loader = loader; + builder->current = &loader->current.outline; + builder->base = &loader->base.outline; + + FT_GlyphLoader_Rewind( loader ); + } + + if ( size ) + { + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Builder */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + LOCAL_FUNC + void Z1_Done_Builder( Z1_Builder* builder ) + { + Z1_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + LOCAL_FUNC + void Z1_Init_Decoder( Z1_Decoder* decoder ) + { + decoder->top = 0; + decoder->zone = 0; + decoder->flex_state = 0; + decoder->num_flex_vectors = 0; + decoder->blend = 0; + + /* Clear loader */ + MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) ); + } + + + /* check that there is enough space for `count' more points */ + static + FT_Error check_points( Z1_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( Z1_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; + point->y = y; + *control = 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( Z1_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 space for a new contour, then add it */ + static + FT_Error add_contour( Z1_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return FT_Err_Ok; + } + + /* reallocate contours array if necessary */ + error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = 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( Z1_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + FT_Error error; + + + builder->path_begun = 1; + error = add_contour( builder ); + if ( error ) + return error; + } + return add_point1( builder, x, y ); + } + + + /* close the current contour */ + static + void close_contour( Z1_Builder* builder ) + { + FT_Outline* outline = builder->current; + + + /* XXX: 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; + + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* lookup_glyph_by_stdcharcode */ + /* */ + /* */ + /* Looks up a given glyph by its StandardEncoding charcode. Used */ + /* to implement the SEAC Type 1 operator. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + static + FT_Int lookup_glyph_by_stdcharcode( T1_Face face, + FT_Int charcode ) + { + FT_Int n; + const FT_String* glyph_name; + PSNames_Interface* psnames = (PSNames_Interface*)face->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 < face->type1.num_glyphs; n++ ) + { + FT_String* name = (FT_String*)face->type1.glyph_names[n]; + + + if ( name && strcmp( name,glyph_name ) == 0 ) + return n; + } + + return -1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_seac */ + /* */ + /* */ + /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error t1operator_seac( Z1_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; + T1_Face face = decoder->builder.face; + T1_Font* type1 = &face->type1; + + + bchar_index = lookup_glyph_by_stdcharcode( face, bchar ); + achar_index = lookup_glyph_by_stdcharcode( face, achar ); + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return T1_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->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 = Z1_Parse_CharStrings( decoder, + type1->charstrings [bchar_index], + type1->charstrings_len[bchar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + 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 = Z1_Parse_CharStrings( decoder, + type1->charstrings [achar_index], + type1->charstrings_len[achar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + return error; + + /* 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 = base->n_points - n_base_points; + dummy.points = base->points + n_base_points; + FT_Outline_Translate( &dummy, adx - asb, ady ); + } + + Exit: + return error; + } + + +#define USE_ARGS( n ) do \ + { \ + top -= n; \ + if ( top < decoder->stack ) \ + goto Stack_Underflow; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given Type 1 charstrings program. */ + /* */ + /* */ + /* 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. */ + /* */ + /* num_subrs :: The number of sub-routines. */ + /* */ + /* subrs_base :: An array of sub-routines addresses. */ + /* */ + /* subrs_len :: An array of sub-routines lengths. */ + /* */ + /* */ + /* Free error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ) + { + FT_Error error; + Z1_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + Z1_Builder* builder = &decoder->builder; + FT_Outline* outline; + FT_Pos x, y; + + + /* 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 = T1_Err_Ok; + outline = builder->current; + + x = builder->pos_x; + y = builder->pos_y; + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Int* top = decoder->top; + Z1_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(( "Z1_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(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + break; + + case 255: /* four bytes integer */ + if ( ip + 4 > limit ) + { + FT_ERROR(( "Z1_Parse_CharStrings: unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = ( (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(( "Z1_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(( "Z1_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(( "Z1_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(( "Z1_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(( "Z1_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(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if ( ip[0] != 12 || ip[1] != 17 ) + { + FT_ERROR(( "Z1_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_Int* delta; + FT_Int* values; + + + if ( !blend ) + { + FT_ERROR(( "Z1_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(( "Z1_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 x = values[0]; + + + for ( mm = 1; mm < blend->num_designs; mm++ ) + x += FT_MulFix( *delta++, blend->weight_vector[mm] ); + + *values++ = x; + } + /* note that `top' will be incremented later by calls to `pop' */ + break; + } + + default: + Unexpected_OtherSubr: + FT_ERROR(( "Z1_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 T1_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 T1_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 T1_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]; + 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]; + 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]; + break; + + case op_div: + FT_TRACE4(( " div" )); + + if ( top[1] ) + { + *top = top[0] / top[1]; + ++top; + } + else + { + FT_ERROR(( "Z1_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 >= num_subrs ) + { + FT_ERROR(( "Z1_Parse_CharStrings: invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "Z1_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = subrs_base[index]; + zone->limit = zone->base + subrs_len[index]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "Z1_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" )); + + /* theorically, the arguments are already on the stack */ + top++; + break; + + case op_return: + FT_TRACE4(( " return" )); + + if ( zone <= decoder->zones ) + { + FT_ERROR(( "Z1_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(( "Z1_Parse_CharStrings:" )); + FT_ERROR(( " unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + + default: + FT_ERROR(( "Z1_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 T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + + 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. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error Z1_Compute_Max_Advance( T1_Face face, + FT_Int* max_advance ) + { + FT_Error error; + Z1_Decoder decoder; + FT_Int glyph_index; + T1_Font* type1 = &face->type1; + + + *max_advance = 0; + + /* Initialize load decoder */ + Z1_Init_Decoder( &decoder ); + Z1_Init_Builder( &decoder.builder, face, 0, 0 ); + + decoder.blend = face->blend; + 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 < type1->num_glyphs; glyph_index++ ) + { + /* now get load the unscaled outline */ + error = Z1_Parse_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + /* 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' *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph, + Z1_Size size, + FT_Int glyph_index, + FT_Int load_flags ) + { + FT_Error error; + Z1_Decoder decoder; + T1_Face face = (T1_Face)glyph->root.face; + FT_Bool hinting; + T1_Font* type1 = &face->type1; + + + 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 = ( load_flags & FT_LOAD_NO_SCALE ) == 0 && + ( load_flags & FT_LOAD_NO_HINTING ) == 0; + + glyph->root.format = ft_glyph_format_outline; + + Z1_Init_Decoder( &decoder ); + Z1_Init_Builder( &decoder.builder, face, size, glyph ); + + decoder.blend = ((T1_Face)glyph->root.face)->blend; + decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0; + + /* now load the unscaled outline */ + error = Z1_Parse_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + + /* save new glyph tables */ + Z1_Done_Builder( &decoder.builder ); + + /* 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 ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.builder.advance.x; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.format = ft_glyph_format_outline; + + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= ft_outline_high_precision; + +#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 ); + } + + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, + &face->type1.font_matrix ); + + /* 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/reactos/subsys/win32k/freetype/z1gload.h b/reactos/subsys/win32k/freetype/z1gload.h new file mode 100644 index 00000000000..5bb6dc0a25a --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1gload.h @@ -0,0 +1,187 @@ +/***************************************************************************/ +/* */ +/* z1gload.h */ +/* */ +/* Experimental Type 1 Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1GLOAD_H +#define Z1GLOAD_H + + +#ifdef FT_FLAT_COMPILE + +#include "z1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* loader :: The current glyph loader. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* base :: The base glyph 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 (for composite glyphs). */ + /* */ + /* pos_y :: The vertical translation (for composite glyphs). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* no_recurse :: */ + /* */ + /* bbox :: The glyph's bounding box. */ + /* */ + /* path_begun :: A flag which indicates that a new path has begun. */ + /* */ + /* load_points :: A flag which indicates, if not set, that no points */ + /* are loaded. */ + /* */ + /* error :: The current error code. */ + /* */ + /* metrics_only :: A flag whether to compute metrics only. */ + /* */ + typedef struct Z1_Builder_ + { + FT_Memory memory; + T1_Face face; + Z1_GlyphSlot glyph; + FT_GlyphLoader* loader; + + FT_Outline* current; /* the current glyph outline */ + FT_Outline* base; /* the composite glyph outline */ + + 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; + + } Z1_Builder; + + + /* execution context charstring zone */ + typedef struct Z1_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } Z1_Decoder_Zone; + + + typedef struct Z1_Decoder_ + { + Z1_Builder builder; + + FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS]; + FT_Int* top; + + Z1_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1]; + Z1_Decoder_Zone* zone; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + T1_Blend* blend; /* for multiple masters */ + + } Z1_Decoder; + + + LOCAL_DEF + void Z1_Init_Builder( Z1_Builder* builder, + T1_Face face, + Z1_Size size, + Z1_GlyphSlot glyph ); + + LOCAL_DEF + void Z1_Done_Builder( Z1_Builder* builder ); + + LOCAL_DEF + void Z1_Init_Decoder( Z1_Decoder* decoder ); + + LOCAL_DEF + FT_Error Z1_Compute_Max_Advance( T1_Face face, + FT_Int* max_advance ); + + LOCAL_DEF + FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ); + + LOCAL_DEF + FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph, + Z1_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* Z1GLOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/z1load.c b/reactos/subsys/win32k/freetype/z1load.c new file mode 100644 index 00000000000..46478d1a85f --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1load.c @@ -0,0 +1,1725 @@ +/***************************************************************************/ +/* */ +/* z1load.c */ +/* */ +/* Experimental Type 1 font loader (body). */ +/* */ +/* Copyright 1996-2000 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 ... */ + /* */ + /* where 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 +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1load.h" + +#else + +#include + +#endif + + +#include /* for strncmp(), strcmp() */ +#include /* 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_z1load + + +#ifndef Z1_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; + } + + + LOCAL_FUNC + FT_Error Z1_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; + } + + + LOCAL_FUNC + FT_Error Z1_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 = FT_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 = FT_Err_Ok; + } + return error; + } + + + LOCAL_FUNC + FT_Error Z1_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 < 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 = Z1_Set_MM_Blend( face, num_coords, final_blends ); + } + + return error; + } + + + LOCAL_FUNC + void Z1_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, + Z1_Loader* loader ) + { + Z1_Token_Rec 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 */ + Z1_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++ ) + { + Z1_Token_Rec* token = axis_tokens + n; + FT_Byte* name; + FT_Int len; + + /* skip first slash, if any */ + if (token->start[0] == '/') + token->start++; + + len = 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.error = error; + } + + + static + void parse_blend_design_positions( T1_Face face, + Z1_Loader* loader ) + { + Z1_Token_Rec design_tokens[ T1_MAX_MM_DESIGNS ]; + FT_Int num_designs; + FT_Int num_axis; + Z1_Parser* parser = &loader->parser; + + FT_Error error = 0; + T1_Blend* blend; + + + /* get the array of design tokens - compute number of designs */ + Z1_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->cursor; + FT_Byte* old_limit = parser->limit; + FT_UInt n; + + + blend = face->blend; + num_axis = 0; /* make compiler happy */ + + for ( n = 0; n < (FT_UInt)num_designs; n++ ) + { + Z1_Token_Rec axis_tokens[ T1_MAX_MM_DESIGNS ]; + Z1_Token_Rec* token; + FT_Int axis, n_axis; + + + /* read axis/coordinates tokens */ + token = design_tokens + n; + parser->cursor = token->start - 1; + parser->limit = token->limit + 1; + Z1_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++ ) + { + Z1_Token_Rec* token2 = axis_tokens + axis; + + + parser->cursor = token2->start; + parser->limit = token2->limit; + blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 ); + } + } + + loader->parser.cursor = old_cursor; + loader->parser.limit = old_limit; + } + + Exit: + loader->parser.error = error; + } + + + static + void parse_blend_design_map( T1_Face face, + Z1_Loader* loader ) + { + FT_Error error = 0; + Z1_Parser* parser = &loader->parser; + T1_Blend* blend; + Z1_Token_Rec 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; + + + Z1_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->cursor; + old_limit = parser->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; + Z1_Token_Rec* token; + FT_Int p, num_points; + + + token = axis_tokens + n; + parser->cursor = token->start; + parser->limit = token->limit; + + /* count the number of map points */ + { + FT_Byte* p = token->start; + FT_Byte* limit = token->limit; + + + num_points = 0; + for ( ; p < limit; p++ ) + if ( p[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] = Z1_ToInt( parser ); + map->blend_points [p] = Z1_ToFixed( parser, 0 ); + } + } + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + parser->error = error; + } + + + static + void parse_weight_vector( T1_Face face, + Z1_Loader* loader ) + { + FT_Error error = 0; + Z1_Parser* parser = &loader->parser; + T1_Blend* blend = face->blend; + Z1_Token_Rec 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; + } + + Z1_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->cursor; + old_limit = parser->limit; + + parser->cursor = master.start; + parser->limit = master.limit; + + for ( n = 0; n < blend->num_designs; n++ ) + { + blend->default_weight_vector[n] = + blend->weight_vector[n] = Z1_ToFixed( parser, 0 ); + } + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + parser->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, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + + FT_UNUSED( face ); + + + parser->cursor = parser->limit; + parser->error = 0; + } + +#endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 1 SYMBOL PARSING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* First of all, define the token field static variables. This is a set */ + /* of Z1_Field_Rec variables used later. */ + /* */ + /*************************************************************************/ + +#define Z1_NEW_STRING( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_STRING( T1TYPE, _field ); + +#define Z1_NEW_BOOL( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_BOOL( T1TYPE, _field ); + +#define Z1_NEW_NUM( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM( T1TYPE, _field ); + +#define Z1_NEW_FIXED( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED( T1TYPE, _field, _power ); + +#define Z1_NEW_NUM_TABLE( _name, _field, _max, _count ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max ); + +#define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max ); + +#define Z1_NEW_NUM_TABLE2( _name, _field, _max ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max ); + +#define Z1_NEW_FIXED_TABLE2( _name, _field, _max ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max ); + + +#define Z1_FONTINFO_STRING( n, f ) Z1_NEW_STRING( n, f ) +#define Z1_FONTINFO_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_FONTINFO_BOOL( n, f ) Z1_NEW_BOOL( n, f ) +#define Z1_PRIVATE_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_PRIVATE_FIXED( n, f ) Z1_NEW_FIXED( n, f ) +#define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_NEW_NUM_TABLE( n, f, m, c ) +#define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_NEW_NUM_TABLE2( n, f, m ) +#define Z1_TOPDICT_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_NEW_FIXED_TABLE2( n, f, m ) + + + /* including this file defines all field variables */ +#ifdef FT_FLAT_COMPILE + +#include "z1tokens.h" + +#else + +#include + +#endif + + + /*************************************************************************/ + /* */ + /* Second, define the keyword variables. This is a set of Z1_KeyWord */ + /* structures used to model the way each keyword is `loaded'. */ + /* */ + /*************************************************************************/ + + typedef void (*Z1_Parse_Func)( T1_Face face, + Z1_Loader* loader ); + + + typedef enum Z1_KeyWord_Type_ + { + t1_keyword_callback = 0, + t1_keyword_field, + t1_keyword_field_table + + } Z1_KeyWord_Type; + + + typedef enum Z1_KeyWord_Location_ + { + t1_keyword_type1 = 0, + t1_keyword_font_info, + t1_keyword_private + + } Z1_KeyWord_Location; + + + typedef struct Z1_KeyWord_ + { + const char* name; + Z1_KeyWord_Type type; + Z1_KeyWord_Location location; + Z1_Parse_Func parsing; + const Z1_Field_Rec* field; + + } Z1_KeyWord; + + +#define Z1_KEYWORD_CALLBACK( name, callback ) \ + { \ + name, t1_keyword_callback, t1_keyword_type1, callback, 0 \ + } + +#define Z1_KEYWORD_TYPE1( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f \ + } + +#define Z1_KEYWORD_FONTINFO( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f \ + } + +#define Z1_KEYWORD_PRIVATE( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f \ + } + +#define Z1_KEYWORD_FONTINFO_TABLE( name, f ) \ + { \ + name, t1_keyword_field_table, t1_keyword_font_info, 0, \ + &t1_field_ ## f \ + } + +#define Z1_KEYWORD_PRIVATE_TABLE( name, f ) \ + { \ + name, t1_keyword_field_table, t1_keyword_private, 0, \ + &t1_field_ ## f \ + } + + +#undef Z1_FONTINFO_STRING +#undef Z1_FONTINFO_NUM +#undef Z1_FONTINFO_BOOL +#undef Z1_PRIVATE_NUM +#undef Z1_PRIVATE_FIXED +#undef Z1_PRIVATE_NUM_TABLE +#undef Z1_PRIVATE_NUM_TABLE2 +#undef Z1_TOPDICT_NUM +#undef Z1_TOPDICT_NUM_FIXED2 + +#define Z1_FONTINFO_STRING( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_FONTINFO_NUM( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_FONTINFO_BOOL( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_PRIVATE_NUM( n, f ) Z1_KEYWORD_PRIVATE( n, f ), +#define Z1_PRIVATE_FIXED( n, f ) Z1_KEYWORD_PRIVATE( n, f ), +#define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_KEYWORD_PRIVATE_TABLE( n, f ), +#define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_KEYWORD_PRIVATE_TABLE( n, f ), +#define Z1_TOPDICT_NUM( n, f ) Z1_KEYWORD_TYPE1( n, f ), +#define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_KEYWORD_TYPE1( n, f ), + + + static + FT_Error t1_load_keyword( T1_Face face, + Z1_Loader* loader, + Z1_KeyWord* keyword ) + { + 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 ( keyword->type == t1_keyword_callback ) + { + keyword->parsing( face, loader ); + error = loader->parser.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 ( keyword->location ) + { + case t1_keyword_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_keyword_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 ( keyword->type == t1_keyword_field_table ) + error = Z1_Load_Field_Table( &loader->parser, keyword->field, + objects, max_objects, 0 ); + else + error = Z1_Load_Field( &loader->parser, keyword->field, + objects, max_objects, 0 ); + + Exit: + return error; + } + + + static + int is_space( char c ) + { + return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ); + } + + + static + int is_alpha( char c ) + { + return ( isalnum( c ) || + ( c == '.' ) || + ( c == '_' ) ); + } + + + static + void skip_whitespace( Z1_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + + + while ( cur < parser->limit && is_space( *cur ) ) + cur++; + + parser->cursor = cur; + } + + + static + void skip_blackspace( Z1_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + + while ( cur < parser->limit && !is_space( *cur ) ) + cur++; + + parser->cursor = cur; + } + + + static + int read_binary_data( Z1_Parser* parser, + FT_Int* size, + FT_Byte** base ) + { + FT_Byte* cur; + FT_Byte* limit = parser->limit; + + + /* the binary data has the following format */ + /* */ + /* `size' [white*] RD white ....... ND */ + /* */ + + skip_whitespace( parser ); + cur = parser->cursor; + + if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 ) + { + *size = Z1_ToInt( parser ); + + skip_whitespace( parser ); + skip_blackspace( parser ); /* `RD' or `-|' or something else */ + + /* there is only one whitespace char after the */ + /* `RD' or `-|' token */ + *base = parser->cursor + 1; + + parser->cursor += *size+1; + return 1; + } + + FT_ERROR(( "read_binary_data: invalid size field\n" )); + parser->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, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Error error; + FT_Memory memory = parser->memory; + FT_Int len; + FT_Byte* cur; + FT_Byte* cur2; + FT_Byte* limit; + + + skip_whitespace( parser ); + + cur = parser->cursor; + limit = parser->limit; + + if ( cur >= limit - 1 || *cur != '/' ) + return; + + cur++; + cur2 = cur; + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + + len = cur2 - cur; + if ( len > 0 ) + { + if ( ALLOC( face->type1.font_name, len + 1 ) ) + { + parser->error = error; + return; + } + + MEM_Copy( face->type1.font_name, cur, len ); + face->type1.font_name[len] = '\0'; + } + parser->cursor = cur2; + } + + + static + void parse_font_bbox( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Short temp[4]; + FT_BBox* bbox = &face->type1.font_bbox; + + + (void)Z1_ToCoordArray( parser, 4, temp ); + bbox->xMin = temp[0]; + bbox->yMin = temp[1]; + bbox->xMax = temp[2]; + bbox->yMax = temp[3]; + } + + + static + void parse_font_matrix( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Matrix* matrix = &face->type1.font_matrix; + FT_Fixed temp[4]; + + + (void)Z1_ToFixedArray( parser, 4, temp, 3 ); + matrix->xx = temp[0]; + matrix->yx = temp[1]; + matrix->xy = temp[2]; + matrix->yy = temp[3]; + } + + + static + void parse_encoding( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + /* skip whitespace */ + while ( is_space( *cur ) ) + { + cur++; + if ( cur >= limit ) + { + FT_ERROR(( "parse_encoding: out of bounds!\n" )); + parser->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; + Z1_Table* char_table = &loader->encoding_table; + FT_Memory memory = parser->memory; + FT_Error error; + + + /* read the number of entries in the encoding, should be 256 */ + count = Z1_ToInt( parser ); + if ( parser->error ) + return; + + /* we use a Z1_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 = Z1_New_Table( char_table, count, memory ) ) != 0 ) + { + parser->error = error; + return; + } + + /* 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->cursor; + limit = parser->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->cursor = cur; + charcode = Z1_ToInt( parser ); + cur = parser->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 = cur2 - cur - 1; + + parser->error = Z1_Add_Table( char_table, charcode, + cur + 1, len + 1 ); + char_table->elements[charcode][len] = '\0'; + if ( parser->error ) + return; + + cur = cur2; + } + } + else + cur++; + } + + face->type1.encoding_type = t1_encoding_array; + parser->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->error = T1_Err_Invalid_File_Format; + } + } + } + + + static + void parse_subrs( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + Z1_Table* table = &loader->subrs; + FT_Memory memory = parser->memory; + FT_Error error; + FT_Int n; + + + loader->num_subrs = Z1_ToInt( parser ); + if ( parser->error ) + return; + + /* position the parser right before the `dup' of the first subr */ + skip_whitespace( parser ); + skip_blackspace( parser ); /* `array' */ + skip_whitespace( parser ); + + /* initialize subrs array */ + error = Z1_New_Table( 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->cursor, "dup", 3 ) != 0 ) + break; + + index = Z1_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. */ + skip_whitespace( parser ); + skip_blackspace( parser ); /* `NP' or `I' or `noaccess' */ + skip_whitespace( parser ); + + if ( strncmp( (char*)parser->cursor, "put", 3 ) == 0 ) + { + skip_blackspace( parser ); /* skip `put' */ + skip_whitespace( 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 ) + { + Z1_Decrypt( base, size, 4330 ); + size -= face->type1.private_dict.lenIV; + base += face->type1.private_dict.lenIV; + } + + error = Z1_Add_Table( table, index, base, size ); + if ( error ) + goto Fail; + } + return; + + Fail: + parser->error = error; + } + + + static + void parse_charstrings( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + Z1_Table* code_table = &loader->charstrings; + Z1_Table* name_table = &loader->glyph_names; + FT_Memory memory = parser->memory; + FT_Error error; + + FT_Byte* cur; + FT_Byte* limit = parser->limit; + FT_Int n; + + + loader->num_glyphs = Z1_ToInt( parser ); + if ( parser->error ) + return; + + /* initialize tables */ + error = Z1_New_Table( code_table, loader->num_glyphs, memory ) || + Z1_New_Table( name_table, loader->num_glyphs, 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' */ + /* */ + skip_whitespace( parser ); + + cur = parser->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 != '/' ) + skip_blackspace( parser ); + else + { + FT_Byte* cur2 = cur + 1; + FT_Int len; + + + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + len = cur2 - cur - 1; + + error = Z1_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'; + + parser->cursor = cur2; + if ( !read_binary_data( parser, &size, &base ) ) + return; + + if ( face->type1.private_dict.lenIV >= 0 ) + { + Z1_Decrypt( base, size, 4330 ); + size -= face->type1.private_dict.lenIV; + base += face->type1.private_dict.lenIV; + } + + error = Z1_Add_Table( code_table, n, base, size ); + if ( error ) + goto Fail; + + n++; + if ( n >= loader->num_glyphs ) + break; + } + } + loader->num_glyphs = n; + return; + + Fail: + parser->error = error; + } + + + static + const Z1_KeyWord t1_keywords[] = + { + +#ifdef FT_FLAT_COMPILE + +#include "z1tokens.h" + +#else + +#include + +#endif + + /* now add the special functions... */ + Z1_KEYWORD_CALLBACK( "FontName", parse_font_name ), + Z1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox ), + Z1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix ), + Z1_KEYWORD_CALLBACK( "Encoding", parse_encoding ), + Z1_KEYWORD_CALLBACK( "Subrs", parse_subrs ), + Z1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ), + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + Z1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ), + Z1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map ), + Z1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ), + Z1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector ), + Z1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ), +#endif + + Z1_KEYWORD_CALLBACK( 0, 0 ) + }; + + + static + FT_Error parse_dict( T1_Face face, + Z1_Loader* loader, + FT_Byte* base, + FT_Long size ) + { + Z1_Parser* parser = &loader->parser; + + + parser->cursor = base; + parser->limit = base + size; + parser->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 ) + { + Z1_Token_Rec token; + + + /* skip the `known' keyword and the token following it */ + cur += 5; + loader->parser.cursor = cur; + Z1_ToToken( &loader->parser, &token ); + + /* if the last token was an array, skip it! */ + if ( token.type == t1_token_array ) + cur2 = parser->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 = cur2 - cur; + if ( len > 0 && len < 22 ) + { + if ( !loader->fontdata ) + { + if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 ) + loader->fontdata = 1; + } + else + { + /* now, compare the immediate name to the keyword table */ + Z1_KeyWord* keyword = (Z1_KeyWord*)t1_keywords; + + + for (;;) + { + FT_Byte* name; + + + name = (FT_Byte*)keyword->name; + 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->cursor = cur2; + skip_whitespace( parser ); + parser->error = t1_load_keyword( face, loader, keyword ); + if ( parser->error ) + return parser->error; + + cur = parser->cursor; + break; + } + } + keyword++; + } + } + } + } + } + } + return parser->error; + } + + + static + void t1_init_loader( Z1_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->fontdata = 0; + } + + + static + void t1_done_loader( Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + + + /* finalize tables */ + Z1_Release_Table( &loader->encoding_table ); + Z1_Release_Table( &loader->charstrings ); + Z1_Release_Table( &loader->glyph_names ); + Z1_Release_Table( &loader->subrs ); + + /* finalize parser */ + Z1_Done_Parser( parser ); + } + + + LOCAL_FUNC + FT_Error Z1_Open_Face( T1_Face face ) + { + Z1_Loader loader; + Z1_Parser* parser; + T1_Font* type1 = &face->type1; + FT_Error error; + + + t1_init_loader( &loader, face ); + + /* default lenIV */ + type1->private_dict.lenIV = 4; + + parser = &loader.parser; + error = Z1_New_Parser( parser, face->root.stream, face->root.memory ); + if ( error ) + goto Exit; + + error = parse_dict( face, &loader, parser->base_dict, parser->base_len ); + if ( error ) + goto Exit; + + error = Z1_Get_Private_Dict( parser ); + 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 ) + { + FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" )); + error = T1_Err_Invalid_File_Format; + } + + if ( !loader.charstrings.init ) + { + FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" )); + error = T1_Err_Invalid_File_Format; + } + + 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; + + 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.num_elems; charcode++ ) + { + type1->encoding.char_index[charcode] = 0; + type1->encoding.char_name [charcode] = ".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] = index; + type1->encoding.char_name [charcode] = (char*)glyph_name; + + 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/reactos/subsys/win32k/freetype/z1load.h b/reactos/subsys/win32k/freetype/z1load.h new file mode 100644 index 00000000000..672b5531b66 --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1load.h @@ -0,0 +1,93 @@ +/***************************************************************************/ +/* */ +/* z1load.h */ +/* */ +/* Experimental Type 1 font loader (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1LOAD_H +#define Z1LOAD_H + +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1parse.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + typedef struct Z1_Loader_ + { + Z1_Parser parser; /* parser used to read the stream */ + + FT_Int num_chars; /* number of characters in encoding */ + Z1_Table encoding_table; /* Z1_Table used to store the */ + /* encoding character names */ + + FT_Int num_glyphs; + Z1_Table glyph_names; + Z1_Table charstrings; + + FT_Int num_subrs; + Z1_Table subrs; + FT_Bool fontdata; + + } Z1_Loader; + + + LOCAL_DEF + FT_Error Z1_Open_Face( T1_Face face ); + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + + LOCAL_DEF + FT_Error Z1_Get_Multi_Master( T1_Face face, + FT_Multi_Master* master ); + + LOCAL_DEF + FT_Error Z1_Set_MM_Blend( T1_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + LOCAL_DEF + FT_Error Z1_Set_MM_Design( T1_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + LOCAL_DEF + void Z1_Done_Blend( T1_Face face ); + +#endif /* !Z1_CONFIG_OPTION_NO_MM_SUPPORT */ + + +#ifdef __cplusplus + } +#endif + +#endif /* Z1LOAD_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/z1objs.c b/reactos/subsys/win32k/freetype/z1objs.c new file mode 100644 index 00000000000..e452bb5eddd --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1objs.c @@ -0,0 +1,398 @@ +/***************************************************************************/ +/* */ +/* z1objs.c */ +/* */ +/* Experimental Type 1 objects manager (body). */ +/* */ +/* Copyright 1996-2000 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 +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1gload.h" +#include "z1load.h" +#include "z1afm.h" + +#else + +#include +#include +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* 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_z1objs + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Face */ + /* */ + /* */ + /* The face object destructor. */ + /* */ + /* */ + /* face :: A typeless pointer to the face object to destroy. */ + /* */ + LOCAL_FUNC + void Z1_Done_Face( T1_Face face ) + { + FT_Memory memory; + T1_Font* type1 = &face->type1; + + + if ( face ) + { + memory = face->root.memory; + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + /* release multiple masters information */ + Z1_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->font_name ); + +#ifndef Z1_CONFIG_OPTION_NO_AFM + /* release afm data if present */ + if ( face->afm_data ) + Z1_Done_AFM( memory, (Z1_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; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Face */ + /* */ + /* */ + /* The face object constructor. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* face :: The face record to build. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_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; + + 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; + } + + /* open the tokenizer, this will also check the font format */ + error = Z1_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(( "Z1_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 = "Regular"; + } + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox = face->type1.font_bbox; + root->units_per_EM = 1000; + root->ascender = (FT_Short)face->type1.font_bbox.yMax; + root->descender = -(FT_Short)face->type1.font_bbox.yMin; + root->height = ( ( root->ascender + root->descender ) * 12 ) / 10; + + /* 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 = Z1_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; + + root->underline_position = face->type1.font_info.underline_position; + root->underline_thickness = face->type1.font_info.underline_thickness; + + root->max_points = 0; + root->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 ( 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 = FT_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; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Driver */ + /* */ + /* */ + /* Initializes a given Type 1 driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_Init_Driver( Z1_Driver driver ) + { + FT_UNUSED( driver ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Driver */ + /* */ + /* */ + /* Finalizes a given Type 1 driver. */ + /* */ + /* */ + /* driver :: A handle to the target Type 1 driver. */ + /* */ + LOCAL_DEF + void Z1_Done_Driver( Z1_Driver driver ) + { + FT_UNUSED( driver ); + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/z1objs.h b/reactos/subsys/win32k/freetype/z1objs.h new file mode 100644 index 00000000000..c655a673180 --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1objs.h @@ -0,0 +1,161 @@ +/***************************************************************************/ +/* */ +/* z1objs.h */ +/* */ +/* Experimental Type 1 objects manager (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1OBJS_H +#define Z1OBJS_H + +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + /* The following structures must be defined by the hinter */ + typedef struct Z1_Size_Hints_ Z1_Size_Hints; + typedef struct Z1_Glyph_Hints_ Z1_Glyph_Hints; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Driver */ + /* */ + /* */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct Z1_DriverRec_ *Z1_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Size */ + /* */ + /* */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct Z1_SizeRec_* Z1_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_GlyphSlot */ + /* */ + /* */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct Z1_GlyphSlotRec_* Z1_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_CharMap */ + /* */ + /* */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* */ + /* 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 Z1_CharMapRec_* Z1_CharMap; + + + /*************************************************************************/ + /* */ + /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_SizeRec */ + /* */ + /* */ + /* Type 1 size record. */ + /* */ + typedef struct Z1_SizeRec_ + { + FT_SizeRec root; + FT_Bool valid; + Z1_Size_Hints* hints; /* defined in the hinter. This allows */ + /* us to experiment with different */ + /* hinting schemes without having to */ + /* change `z1objs' each time. */ + } Z1_SizeRec; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_GlyphSlotRec */ + /* */ + /* */ + /* Type 1 glyph slot record. */ + /* */ + typedef struct Z1_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; + + Z1_Glyph_Hints* hints; /* defined in the hinter */ + + } Z1_GlyphSlotRec; + + + LOCAL_DEF + FT_Error Z1_Init_Face( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void Z1_Done_Face( T1_Face face ); + + LOCAL_DEF + FT_Error Z1_Init_Driver( Z1_Driver driver ); + + LOCAL_DEF + void Z1_Done_Driver( Z1_Driver driver ); + + +#ifdef __cplusplus + } +#endif + +#endif /* Z1OBJS_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/z1parse.c b/reactos/subsys/win32k/freetype/z1parse.c new file mode 100644 index 00000000000..9bc29138744 --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1parse.c @@ -0,0 +1,1398 @@ +/***************************************************************************/ +/* */ +/* z1parse.c */ +/* */ +/* Experimental Type 1 parser (body). */ +/* */ +/* Copyright 1996-2000 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 `Z1_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 `z1load.c' to see how data is loaded from the font file. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1parse.h" + +#else + +#include + +#endif + + +#include /* 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_z1parse + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** IMPLEMENTATION OF Z1_TABLE OBJECT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_New_Table */ + /* */ + /* */ + /* Initialises a Z1_Table. */ + /* */ + /* */ + /* table :: The address of the target table. */ + /* */ + /* */ + /* count :: The table size = the maximum number of elements. */ + /* */ + /* memory :: The memory object to use for all subsequent */ + /* reallocations. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_New_Table( Z1_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 = 0xdeadbeef; + table->num_elems = 0; + table->block = 0; + table->capacity = 0; + table->cursor = 0; + + Exit: + if ( error ) + FREE( table->elements ); + + return error; + } + + + static + void shift_elements( Z1_Table* table, + FT_Byte* old_base ) + { + FT_Long delta = table->block - old_base; + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + if ( delta ) + for ( ; offset < limit; offset++ ) + { + if ( offset[0] ) + offset[0] += delta; + } + } + + + static + FT_Error reallocate_t1_table( Z1_Table* table, + FT_Int new_size ) + { + FT_Memory memory = table->memory; + FT_Byte* old_base = table->block; + FT_Error error; + + + /* reallocate the base block */ + if ( REALLOC( table->block, table->capacity, new_size ) ) + return error; + + table->capacity = new_size; + + /* shift all offsets if necessary */ + if ( old_base ) + shift_elements( table, old_base ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Add_Table */ + /* */ + /* */ + /* Adds an object to a Z1_Table, possibly growing its memory block. */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* 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. */ + /* */ + /* */ + /* FreeType error code. 0 means success. An error is returned if a */ + /* reallocation fails. */ + /* */ + LOCAL_FUNC + FT_Error Z1_Add_Table( Z1_Table* table, + FT_Int index, + void* object, + FT_Int length ) + { + if ( index < 0 || index > table->max_elems ) + { + FT_ERROR(( "Z1_Add_Table: invalid index\n" )); + return T1_Err_Syntax_Error; + } + + /* grow the base block if needed */ + if ( table->cursor + length > table->capacity ) + { + FT_Error error; + FT_Int new_size = table->capacity; + + + while ( new_size < table->cursor + length ) + new_size += 1024; + + error = reallocate_t1_table( table, new_size ); + if ( error ) + return error; + } + + /* 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 T1_Err_Ok; + } + + +#if 0 + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Table */ + /* */ + /* */ + /* Finalizes a Z1_Table (i.e., reallocate it to its current cursor). */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* 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. */ + /* */ + LOCAL_FUNC + void Z1_Done_Table( Z1_Table* table ) + { + FT_Memory memory = table->memory; + FT_Error error; + FT_Byte* old_base; + + + /* should never fail, as rec.cursor <= rec.size */ + old_base = table->block; + if ( !old_base ) + return; + + (void)REALLOC( table->block, table->capacity, table->cursor ); + table->capacity = table->cursor; + + if ( old_base != table->block ) + shift_elements( table, old_base ); + } + +#endif /* 0 */ + + + LOCAL_FUNC + void Z1_Release_Table( Z1_Table* table ) + { + FT_Memory memory = table->memory; + + + if ( table->init == (FT_Long)0xDEADBEEF ) + { + FREE( table->block ); + FREE( table->elements ); + FREE( table->lengths ); + table->init = 0; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** INPUT STREAM PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define IS_Z1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' ) +#define IS_Z1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' ) + +#define IS_Z1_SPACE( c ) ( IS_Z1_WHITESPACE( c ) || IS_Z1_LINESPACE( c ) ) + + + LOCAL_FUNC + void Z1_Skip_Spaces( Z1_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( !IS_Z1_SPACE( c ) ) + break; + cur++; + } + parser->cursor = cur; + } + + + LOCAL_FUNC + void Z1_ToToken( Z1_Parser* parser, + Z1_Token_Rec* 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 */ + Z1_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_Z1_SPACE( *cur ) ) + cur++; + + token->limit = cur; + } + + if ( !token->limit ) + { + token->start = 0; + token->type = t1_token_none; + } + + parser->cursor = cur; + } + } + + + LOCAL_FUNC + void Z1_ToTokenArray( Z1_Parser* parser, + Z1_Token_Rec* tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ) + { + Z1_Token_Rec master; + + + *pnum_tokens = -1; + + Z1_ToToken( parser, &master ); + if ( master.type == t1_token_array ) + { + FT_Byte* old_cursor = parser->cursor; + FT_Byte* old_limit = parser->limit; + Z1_Token_Rec* cur = tokens; + Z1_Token_Rec* limit = cur + max_tokens; + + + parser->cursor = master.start; + parser->limit = master.limit; + + while ( parser->cursor < parser->limit ) + { + Z1_Token_Rec token; + + + Z1_ToToken( parser, &token ); + if ( !token.type ) + break; + + if ( cur < limit ) + *cur = token; + + cur++; + } + + *pnum_tokens = 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, 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, read the integer part */ + result = t1_toint( &cur, limit ) << 16; + num = 0; + divider = 1; + + if ( result < 0 ) + { + sign = 1; + result = -result; + } + + 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 */ + LOCAL_FUNC + FT_Error Z1_Load_Field( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ) + { + Z1_Token_Rec token; + FT_Byte* cur; + FT_Byte* limit; + FT_UInt count; + FT_UInt index; + FT_Error error; + + + Z1_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 = limit-cur; + + 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 ( pflags ) + *pflags |= 1L << field->flag_bit; + + error = FT_Err_Ok; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + +#define T1_MAX_TABLE_ELEMENTS 32 + + + LOCAL_FUNC + FT_Error Z1_Load_Field_Table( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ) + { + Z1_Token_Rec elements[T1_MAX_TABLE_ELEMENTS]; + Z1_Token_Rec* token; + FT_Int num_elements; + FT_Error error = 0; + FT_Byte* old_cursor; + FT_Byte* old_limit; + Z1_Field_Rec fieldrec = *(Z1_Field_Rec*)field; + + + Z1_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 ) = 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; + Z1_Load_Field( parser, &fieldrec, objects, max_objects, 0 ); + fieldrec.offset += fieldrec.size; + } + + if ( pflags ) + *pflags |= 1L << field->flag_bit; + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + + LOCAL_FUNC + FT_Long Z1_ToInt ( Z1_Parser* parser ) + { + return t1_toint( &parser->cursor, parser->limit ); + } + + + LOCAL_FUNC + FT_Long Z1_ToFixed( Z1_Parser* parser, + FT_Int power_ten ) + { + return t1_tofixed( &parser->cursor, parser->limit, power_ten ); + } + + + LOCAL_FUNC + FT_Int Z1_ToCoordArray( Z1_Parser* parser, + FT_Int max_coords, + FT_Short* coords ) + { + return t1_tocoordarray( &parser->cursor, parser->limit, + max_coords, coords ); + } + + + LOCAL_FUNC + FT_Int Z1_ToFixedArray( Z1_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 + + LOCAL_FUNC + FT_String* Z1_ToString( Z1_Parser* parser ) + { + return t1_tostring( &parser->cursor, parser->limit, parser->memory ); + } + + + LOCAL_FUNC + FT_Bool Z1_ToBool( Z1_Parser* parser ) + { + return t1_tobool( &parser->cursor, parser->limit ); + } + +#endif /* 0 */ + + + static + FT_Error read_pfb_tag( FT_Stream stream, + FT_UShort* tag, + FT_Long* size ) + { + FT_Error error; + + + if ( READ_UShort( *tag ) ) + goto Exit; + + if ( *tag == 0x8001 || *tag == 0x8002 ) + { + FT_Long asize; + + + if ( READ_ULong( asize ) ) + goto Exit; + + /* swap between big and little endianness */ + *size = ( ( asize & 0xFF000000L ) >> 24 ) | + ( ( asize & 0x00FF0000L ) >> 8 ) | + ( ( asize & 0x0000FF00L ) << 8 ) | + ( ( asize & 0x000000FFL ) << 24 ); + } + + Exit: + return error; + } + + + LOCAL_FUNC + FT_Error Z1_New_Parser( Z1_Parser* parser, + FT_Stream stream, + FT_Memory memory ) + { + FT_Error error; + FT_UShort tag; + FT_Long size; + + + parser->stream = stream; + parser->memory = memory; + 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; + + parser->cursor = 0; + parser->limit = 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 */ + (void)FILE_Seek( 0L ); + 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 = FT_Err_Unknown_File_Format; + } + else + { + parser->cursor = parser->base_dict; + parser->limit = parser->cursor + parser->base_len; + } + } + + Exit: + if ( error && !parser->in_memory ) + FREE( parser->base_dict ); + + return error; + } + + + LOCAL_FUNC + void Z1_Done_Parser( Z1_Parser* parser ) + { + FT_Memory memory = parser->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 ); + } + + + /* 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; + } + + + LOCAL_FUNC + void Z1_Decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ) + { + while ( length > 0 ) + { + FT_Byte plain; + + + plain = ( *buffer ^ ( seed >> 8 ) ); + seed = ( *buffer + seed ) * 52845 + 22719; + *buffer++ = plain; + length--; + } + } + + + LOCAL_FUNC + FT_Error Z1_Get_Private_Dict( Z1_Parser* parser ) + { + FT_Stream stream = parser->stream; + FT_Memory memory = parser->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; + FT_Long size; + + + 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(( "Z1_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 = FT_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(( "Z1_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 = 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++ = ( hex1 << 4 ) | hexa_value( cur[1] ); + count++; + cur++; + } + + /* put a safeguard */ + parser->private_len = write - parser->private_dict; + *write++ = 0; + } + } + + /* we now decrypt the encoded binary private dictionary */ + Z1_Decrypt( parser->private_dict, parser->private_len, 55665 ); + parser->cursor = parser->private_dict; + parser->limit = parser->cursor + parser->private_len; + + Fail: + Exit: + return error; + } + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/z1parse.h b/reactos/subsys/win32k/freetype/z1parse.h new file mode 100644 index 00000000000..d0b6a6503e2 --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1parse.h @@ -0,0 +1,363 @@ +/***************************************************************************/ +/* */ +/* z1parse.h */ +/* */ +/* Experimental Type 1 parser (specification). */ +/* */ +/* Copyright 1996-2000 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 Z1PARSE_H +#define Z1PARSE_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /* simple enumeration type used to identify token types */ + typedef enum Z1_Token_Type_ + { + t1_token_none = 0, + t1_token_any, + t1_token_string, + t1_token_array, + + /* do not remove */ + t1_token_max + + } Z1_Token_Type; + + + /* a simple structure used to identify tokens */ + typedef struct Z1_Token_Rec_ + { + FT_Byte* start; /* first character of token in input stream */ + FT_Byte* limit; /* first character after the token */ + Z1_Token_Type type; /* type of token.. */ + + } Z1_Token_Rec; + + + /* enumeration type used to identify object fields */ + typedef enum Z1_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, + + /* do not remove */ + t1_field_max + + } Z1_Field_Type; + + + /* structure type used to model object fields */ + typedef struct Z1_Field_Rec_ + { + Z1_Field_Type type; /* type of field */ + FT_UInt offset; /* offset of field in object */ + FT_UInt size; /* size of field in bytes */ + FT_UInt array_max; /* maximum number of elements for array */ + FT_UInt count_offset; /* offset of element count for arrays */ + FT_Int flag_bit; /* bit number for field flag */ + + } Z1_Field_Rec; + + +#define Z1_FIELD_REF( s, f ) ( ((s*)0)->f ) + +#define Z1_FIELD_BOOL( _ftype, _fname ) \ + { \ + t1_field_bool, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_NUM( _ftype, _fname ) \ + { \ + t1_field_integer, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_FIXED( _ftype, _fname, _power ) \ + { \ + t1_field_fixed, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_STRING( _ftype, _fname ) \ + { \ + t1_field_string, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_NUM_ARRAY( _ftype, _fname, _fcount, _fmax ) \ + { \ + t1_field_integer, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fcount ), \ + 0 \ + } + +#define Z1_FIELD_FIXED_ARRAY( _ftype, _fname, _fcount, _fmax ) \ + { \ + t1_field_fixed, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fcount ), \ + 0 \ + } + +#define Z1_FIELD_NUM_ARRAY2( _ftype, _fname, _fmax ) \ + { \ + t1_field_integer, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + 0, 0 \ + } + +#define Z1_FIELD_FIXED_ARRAY2( _ftype, _fname, _fmax ) \ + { \ + t1_field_fixed, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + 0, 0 \ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Table */ + /* */ + /* */ + /* A Z1_Table is a simple object used to store an array of objects in */ + /* a single memory block. */ + /* */ + /* */ + /* block :: The address in memory of the growheap's block. This */ + /* can change between two object adds, due to the use of */ + /* reallocation. */ + /* */ + /* cursor :: The current top of the grow heap within its block. */ + /* */ + /* capacity :: The current size of the heap block. Increments in */ + /* 1kByte blocks. */ + /* */ + /* init :: A boolean. Set when the table has been initialized */ + /* (the table user should set this field). */ + /* */ + /* max_elems :: The maximum number of elements in the table. */ + /* */ + /* num_elems :: The current number of elements in the table. */ + /* */ + /* elements :: A table of element addresses within the block. */ + /* */ + /* lengths :: A table of element sizes within the block. */ + /* */ + /* memory :: The memory object used for memory operations */ + /* (allocation/reallocation). */ + /* */ + typedef struct Z1_Table_ + { + FT_Byte* block; /* current memory block */ + FT_Int cursor; /* current cursor in memory block */ + FT_Int 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; + + } Z1_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Parser */ + /* */ + /* */ + /* A Z1_Parser is an object used to parse a Type 1 fonts very */ + /* quickly. */ + /* */ + /* */ + /* stream :: The current input stream. */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* 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. */ + /* */ + /* cursor :: The current parser cursor. */ + /* */ + /* limit :: The current parser limit (first byte after the */ + /* current dictionary). */ + /* */ + /* error :: The current parsing error. */ + /* */ + typedef struct Z1_Parser_ + { + FT_Stream stream; + FT_Memory memory; + + 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; + + FT_Byte* cursor; + FT_Byte* limit; + FT_Error error; + + } Z1_Parser; + + + LOCAL_DEF + FT_Error Z1_New_Table( Z1_Table* table, + FT_Int count, + FT_Memory memory ); + + + LOCAL_DEF + FT_Error Z1_Add_Table( Z1_Table* table, + FT_Int index, + void* object, + FT_Int length ); + +#if 0 + LOCAL_DEF + void Z1_Done_Table( Z1_Table* table ); +#endif + + LOCAL_DEF + void Z1_Release_Table( Z1_Table* table ); + + LOCAL_DEF + FT_Long Z1_ToInt( Z1_Parser* parser ); + + LOCAL_DEF + FT_Long Z1_ToFixed( Z1_Parser* parser, + FT_Int power_ten ); + + LOCAL_DEF + FT_Int Z1_ToCoordArray( Z1_Parser* parser, + FT_Int max_coords, + FT_Short* coords ); + + LOCAL_DEF + FT_Int Z1_ToFixedArray( Z1_Parser* parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ); + +#if 0 + LOCAL_DEF + FT_String* Z1_ToString( Z1_Parser* parser ); + + LOCAL_DEF + FT_Bool Z1_ToBool( Z1_Parser* parser ); +#endif + + + LOCAL_DEF + void Z1_Skip_Spaces( Z1_Parser* parser ); + + LOCAL_DEF + void Z1_ToToken( Z1_Parser* parser, + Z1_Token_Rec* token ); + + LOCAL_FUNC + void Z1_ToTokenArray( Z1_Parser* parser, + Z1_Token_Rec* tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ); + + LOCAL_DEF + FT_Error Z1_Load_Field( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ); + + LOCAL_DEF + FT_Error Z1_Load_Field_Table( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ); + + + LOCAL_DEF + FT_Error Z1_New_Parser( Z1_Parser* parser, + FT_Stream stream, + FT_Memory memory ); + + LOCAL_DEF + FT_Error Z1_Get_Private_Dict( Z1_Parser* parser ); + + LOCAL_DEF + void Z1_Decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ); + + LOCAL_DEF + void Z1_Done_Parser( Z1_Parser* parser ); + +#ifdef __cplusplus + } +#endif + +#endif /* Z1PARSE_H */ + + +/* END */ diff --git a/reactos/subsys/win32k/freetype/z1tokens.h b/reactos/subsys/win32k/freetype/z1tokens.h new file mode 100644 index 00000000000..73c0228e53f --- /dev/null +++ b/reactos/subsys/win32k/freetype/z1tokens.h @@ -0,0 +1,132 @@ +/***************************************************************************/ +/* */ +/* z1tokens.h */ +/* */ +/* Experimental Type 1 tokenizer (specification). */ +/* */ +/* Copyright 1996-2000 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 T1TYPE +#define T1TYPE T1_FontInfo + + Z1_FONTINFO_STRING( "version", version ) + Z1_FONTINFO_STRING( "Notice", notice ) + Z1_FONTINFO_STRING( "FullName", full_name ) + Z1_FONTINFO_STRING( "FamilyName", family_name ) + Z1_FONTINFO_STRING( "Weight", weight ) + + Z1_FONTINFO_NUM ( "ItalicAngle", italic_angle ) + Z1_FONTINFO_BOOL ( "isFixedPitch", is_fixed_pitch ) + Z1_FONTINFO_NUM ( "UnderlinePosition", underline_position ) + Z1_FONTINFO_NUM ( "UnderlineThickness", underline_thickness ) + + +#undef T1TYPE +#define T1TYPE T1_Private + + Z1_PRIVATE_NUM ( "UniqueID", unique_id ) + Z1_PRIVATE_NUM ( "lenIV", lenIV ) + Z1_PRIVATE_NUM ( "LanguageGroup", language_group ) + Z1_PRIVATE_NUM ( "password", password ) + + Z1_PRIVATE_FIXED ( "BlueScale", blue_scale ) + Z1_PRIVATE_NUM ( "BlueShift", blue_shift ) + Z1_PRIVATE_NUM ( "BlueFuzz", blue_fuzz ) + + Z1_PRIVATE_NUM_TABLE ( "BlueValues", blue_values, 14, num_blue_values ) + Z1_PRIVATE_NUM_TABLE ( "OtherBlues", other_blues, 10, num_other_blues ) + Z1_PRIVATE_NUM_TABLE ( "FamilyBlues", family_blues, 14, num_family_blues ) + Z1_PRIVATE_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10, \ + num_family_other_blues ) + + Z1_PRIVATE_NUM_TABLE2( "StdHW", standard_width, 1 ) + Z1_PRIVATE_NUM_TABLE2( "StdVW", standard_height, 1 ) + Z1_PRIVATE_NUM_TABLE2( "MinFeature", min_feature, 2 ) + + Z1_PRIVATE_NUM_TABLE ( "StemSnapH", snap_widths, 12, num_snap_widths ) + Z1_PRIVATE_NUM_TABLE ( "StemSnapV", snap_heights, 12, num_snap_heights ) + + +#undef T1TYPE +#define T1TYPE T1_Font + + Z1_TOPDICT_NUM( "PaintType", paint_type ) + Z1_TOPDICT_NUM( "FontType", font_type ) + Z1_TOPDICT_NUM( "StrokeWidth", stroke_width ) + + +#if 0 + + /* define the font info dictionary parsing callbacks */ +#undef FACE +#define FACE (face->type1.font_info) + + PARSE_STRING( "version", version ) + PARSE_STRING( "Notice", notice ) + PARSE_STRING( "FullName", full_name ) + PARSE_STRING( "FamilyName", family_name ) + PARSE_STRING( "Weight", weight ) + + PARSE_INT ( "ItalicAngle", italic_angle ) + PARSE_BOOL ( "isFixedPitch", is_fixed_pitch ) + PARSE_NUM ( "UnderlinePosition", underline_position, FT_Short ) + PARSE_NUM ( "UnderlineThickness", underline_thickness, FT_UShort ) + + + /* define the private dict parsing callbacks */ +#undef FACE +#define FACE (face->type1.private_dict) + + PARSE_INT ("UniqueID", unique_id ) + PARSE_INT ("lenIV", lenIV ) + + PARSE_COORDS ( "BlueValues", num_blues, 14, blue_values) + PARSE_COORDS ( "OtherBlues", num_other_blues, 10, other_blues) + + PARSE_COORDS ( "FamilyBlues", num_family_blues, 14, family_blues ) + PARSE_COORDS ( "FamilyOtherBlues", num_family_other_blues, 10, + family_other_blues ) + + PARSE_FIXED ( "BlueScale", blue_scale ) + PARSE_INT ( "BlueShift", blue_shift ) + + PARSE_INT ( "BlueFuzz", blue_fuzz ) + + PARSE_COORDS2( "StdHW", 1, standard_width ) + PARSE_COORDS2( "StdVW", 1, standard_height ) + + PARSE_COORDS ( "StemSnapH", num_snap_widths, 12, stem_snap_widths ) + PARSE_COORDS ( "StemSnapV", num_snap_heights, 12, stem_snap_heights ) + + PARSE_INT ( "LanguageGroup", language_group ) + PARSE_INT ( "password", password ) + PARSE_COORDS2( "MinFeature", 2, min_feature ) + + + /* define the top-level dictionary parsing callbacks */ +#undef FACE +#define FACE (face->type1) + +/*PARSE_STRING ( "FontName", font_name ) -- handled by special routine */ + PARSE_NUM ( "PaintType", paint_type, FT_Byte ) + PARSE_NUM ( "FontType", font_type, FT_Byte ) + PARSE_FIXEDS2( "FontMatrix", 4, font_matrix ) +/*PARSE_COORDS2( "FontBBox", 4, font_bbox ) -- handled by special routine */ + PARSE_INT ( "StrokeWidth", stroke_width ) + +#undef FACE + +#endif /* 0 */ + + +/* END */